1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <errno.h>
17
18 #include "le_epoll.h"
19
IsValid_(const EventEpoll * loop)20 static int IsValid_(const EventEpoll *loop)
21 {
22 return loop->epollFd >= 0;
23 }
24
GetEpollEvent_(int fd,int op,struct epoll_event * event)25 static void GetEpollEvent_(int fd, int op, struct epoll_event *event)
26 {
27 event->data.fd = fd;
28 if (LE_TEST_FLAGS(op, Event_Read)) {
29 event->events = EPOLLIN;
30 }
31 if (LE_TEST_FLAGS(op, Event_Write)) {
32 event->events = EPOLLOUT;
33 }
34 }
35
Close_(const EventLoop * loop)36 static LE_STATUS Close_(const EventLoop *loop)
37 {
38 LE_CHECK(loop != NULL, return LE_FAILURE, "Invalid loop");
39 EventEpoll *epoll = (EventEpoll *)loop;
40 LE_LOGV("Close_ epollFd %d", epoll->epollFd);
41 close(epoll->epollFd);
42 free(epoll);
43 return LE_SUCCESS;
44 }
45
AddEvent_(const EventLoop * loop,const BaseTask * task,int op)46 static LE_STATUS AddEvent_(const EventLoop *loop, const BaseTask *task, int op)
47 {
48 int ret = LE_FAILURE;
49 LE_CHECK(loop != NULL, return LE_FAILURE, "Invalid loop");
50 EventEpoll *epoll = (EventEpoll *)loop;
51
52 struct epoll_event event = {};
53 int fd = GetSocketFd((const TaskHandle)task);
54 GetEpollEvent_(fd, op, &event);
55 if (IsValid_(epoll) && fd >= 0) {
56 ret = epoll_ctl(epoll->epollFd, EPOLL_CTL_ADD, fd, &event);
57 }
58 LE_CHECK(ret == 0, return LE_FAILURE, "Failed to add epoll_ctl %d ret %d", fd, errno);
59 return LE_SUCCESS;
60 }
61
ModEvent_(const EventLoop * loop,const BaseTask * task,int op)62 static LE_STATUS ModEvent_(const EventLoop *loop, const BaseTask *task, int op)
63 {
64 int ret = LE_FAILURE;
65 LE_CHECK(loop != NULL, return LE_FAILURE, "Invalid loop");
66 EventEpoll *epoll = (EventEpoll *)loop;
67
68 struct epoll_event event = {};
69 int fd = GetSocketFd((const TaskHandle)task);
70 GetEpollEvent_(fd, op, &event);
71 if (IsValid_(epoll) && fd >= 0) {
72 ret = epoll_ctl(epoll->epollFd, EPOLL_CTL_MOD, fd, &event);
73 }
74 LE_CHECK(ret == 0, return LE_FAILURE, "Failed to mod epoll_ctl %d ret %d", fd, errno);
75 return LE_SUCCESS;
76 }
77
DelEvent_(const EventLoop * loop,int fd,int op)78 static LE_STATUS DelEvent_(const EventLoop *loop, int fd, int op)
79 {
80 LE_CHECK(loop != NULL, return LE_FAILURE, "Invalid loop");
81 EventEpoll *epoll = (EventEpoll *)loop;
82
83 struct epoll_event event = {};
84 GetEpollEvent_(fd, op, &event);
85 if (IsValid_(epoll) && fd >= 0) {
86 (void)epoll_ctl(epoll->epollFd, EPOLL_CTL_DEL, fd, &event);
87 }
88 return LE_SUCCESS;
89 }
90
RunLoop_(const EventLoop * loop)91 static LE_STATUS RunLoop_(const EventLoop *loop)
92 {
93 LE_CHECK(loop != NULL, return LE_FAILURE, "Invalid loop");
94 EventEpoll *epoll = (EventEpoll *)loop;
95 if (!IsValid_(epoll)) {
96 return LE_FAILURE;
97 }
98 while (1) {
99 int number = epoll_wait(epoll->epollFd, epoll->waitEvents, loop->maxevents, -1);
100 for (int index = 0; index < number; index++) {
101 if ((epoll->waitEvents[index].events & EPOLLIN) == EPOLLIN) {
102 ProcessEvent(loop, epoll->waitEvents[index].data.fd, Event_Read);
103 }
104 if ((epoll->waitEvents[index].events & EPOLLOUT) == EPOLLOUT) {
105 ProcessEvent(loop, epoll->waitEvents[index].data.fd, Event_Write);
106 }
107 if ((epoll->waitEvents[index].events & EPOLLERR) == EPOLLERR) {
108 LE_LOGV("RunLoop_ error %d", epoll->waitEvents[index].data.fd);
109 ProcessEvent(loop, epoll->waitEvents[index].data.fd, Event_Error);
110 }
111 if ((epoll->waitEvents[index].events & EPOLLHUP) == EPOLLHUP) {
112 LE_LOGV("RunLoop_ error %d", epoll->waitEvents[index].data.fd);
113 ProcessEvent(loop, epoll->waitEvents[index].data.fd, Event_Error);
114 }
115 }
116 if (loop->stop) {
117 break;
118 }
119 }
120 return LE_SUCCESS;
121 }
122
CreateEpollLoop(EventLoop ** loop,uint32_t maxevents,uint32_t timeout)123 LE_STATUS CreateEpollLoop(EventLoop **loop, uint32_t maxevents, uint32_t timeout)
124 {
125 LE_CHECK(loop != NULL, return LE_FAILURE, "Invalid loop");
126 EventEpoll *epoll = (EventEpoll *)malloc(sizeof(EventEpoll) + sizeof(struct epoll_event) * (maxevents));
127 LE_CHECK(epoll != NULL, return LE_FAILURE, "Failed to alloc memory for epoll");
128 epoll->epollFd = epoll_create(maxevents);
129 LE_CHECK(epoll->epollFd >= 0, free(epoll);
130 return LE_FAILURE, "Failed to create epoll");
131
132 *loop = (EventLoop *)epoll;
133 epoll->loop.maxevents = maxevents;
134 epoll->loop.timeout = timeout;
135 epoll->loop.close = Close_;
136 epoll->loop.runLoop = RunLoop_;
137 epoll->loop.delEvent = DelEvent_;
138 epoll->loop.addEvent = AddEvent_;
139 epoll->loop.modEvent = ModEvent_;
140 return LE_SUCCESS;
141 }
142