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 #include "le_idle.h"
20
IsValid_(const EventEpoll * loop)21 static int IsValid_(const EventEpoll *loop)
22 {
23 return loop->epollFd >= 0;
24 }
25
GetEpollEvent_(int fd,int op,struct epoll_event * event)26 static void GetEpollEvent_(int fd, int op, struct epoll_event *event)
27 {
28 event->data.fd = fd;
29 if (LE_TEST_FLAGS(op, Event_Read)) {
30 event->events = EPOLLIN;
31 }
32 if (LE_TEST_FLAGS(op, Event_Write)) {
33 event->events = EPOLLOUT;
34 }
35 }
36
Close_(const EventLoop * loop)37 static LE_STATUS Close_(const EventLoop *loop)
38 {
39 LE_CHECK(loop != NULL, return LE_FAILURE, "Invalid loop");
40 EventEpoll *epoll = (EventEpoll *)loop;
41 LE_LOGV("Close_ epollFd %d", epoll->epollFd);
42 close(epoll->epollFd);
43 free(epoll);
44 return LE_SUCCESS;
45 }
46
AddEvent_(const EventLoop * loop,const BaseTask * task,int op)47 static LE_STATUS AddEvent_(const EventLoop *loop, const BaseTask *task, int op)
48 {
49 int ret = LE_FAILURE;
50 LE_CHECK(loop != NULL, return LE_FAILURE, "Invalid loop");
51 EventEpoll *epoll = (EventEpoll *)loop;
52
53 struct epoll_event event = {};
54 int fd = GetSocketFd((const TaskHandle)task);
55 GetEpollEvent_(fd, op, &event);
56 if (IsValid_(epoll) && fd >= 0) {
57 ret = epoll_ctl(epoll->epollFd, EPOLL_CTL_ADD, fd, &event);
58 }
59 LE_CHECK(ret == 0, return LE_FAILURE, "Failed to add epoll_ctl %d ret %d", fd, errno);
60 return LE_SUCCESS;
61 }
62
ModEvent_(const EventLoop * loop,const BaseTask * task,int op)63 static LE_STATUS ModEvent_(const EventLoop *loop, const BaseTask *task, int op)
64 {
65 int ret = LE_FAILURE;
66 LE_CHECK(loop != NULL, return LE_FAILURE, "Invalid loop");
67 EventEpoll *epoll = (EventEpoll *)loop;
68
69 struct epoll_event event = {};
70 int fd = GetSocketFd((const TaskHandle)task);
71 GetEpollEvent_(fd, op, &event);
72 if (IsValid_(epoll) && fd >= 0) {
73 ret = epoll_ctl(epoll->epollFd, EPOLL_CTL_MOD, fd, &event);
74 }
75 LE_CHECK(ret == 0, return LE_FAILURE, "Failed to mod epoll_ctl %d ret %d", fd, errno);
76 return LE_SUCCESS;
77 }
78
DelEvent_(const EventLoop * loop,int fd,int op)79 static LE_STATUS DelEvent_(const EventLoop *loop, int fd, int op)
80 {
81 LE_CHECK(loop != NULL, return LE_FAILURE, "Invalid loop");
82 EventEpoll *epoll = (EventEpoll *)loop;
83
84 struct epoll_event event = {};
85 GetEpollEvent_(fd, op, &event);
86 if (IsValid_(epoll) && fd >= 0) {
87 (void)epoll_ctl(epoll->epollFd, EPOLL_CTL_DEL, fd, &event);
88 }
89 return LE_SUCCESS;
90 }
91
RunLoop_(const EventLoop * loop)92 static LE_STATUS RunLoop_(const EventLoop *loop)
93 {
94 LE_CHECK(loop != NULL, return LE_FAILURE, "Invalid loop");
95 EventEpoll *epoll = (EventEpoll *)loop;
96 if (!IsValid_(epoll)) {
97 return LE_FAILURE;
98 }
99 while (1) {
100 LE_RunIdle((LoopHandle)&(epoll->loop));
101
102 int number = epoll_wait(epoll->epollFd, epoll->waitEvents, loop->maxevents, -1);
103 for (int index = 0; index < number; index++) {
104 if ((epoll->waitEvents[index].events & EPOLLIN) == EPOLLIN) {
105 ProcessEvent(loop, epoll->waitEvents[index].data.fd, Event_Read);
106 }
107 if ((epoll->waitEvents[index].events & EPOLLOUT) == EPOLLOUT) {
108 ProcessEvent(loop, epoll->waitEvents[index].data.fd, Event_Write);
109 }
110 if ((epoll->waitEvents[index].events & EPOLLERR) == EPOLLERR) {
111 LE_LOGV("RunLoop_ error %d", epoll->waitEvents[index].data.fd);
112 ProcessEvent(loop, epoll->waitEvents[index].data.fd, Event_Error);
113 }
114 if ((epoll->waitEvents[index].events & EPOLLHUP) == EPOLLHUP) {
115 LE_LOGV("RunLoop_ error %d", epoll->waitEvents[index].data.fd);
116 ProcessEvent(loop, epoll->waitEvents[index].data.fd, Event_Error);
117 }
118 }
119 if (loop->stop) {
120 break;
121 }
122 }
123 return LE_SUCCESS;
124 }
125
CreateEpollLoop(EventLoop ** loop,uint32_t maxevents,uint32_t timeout)126 LE_STATUS CreateEpollLoop(EventLoop **loop, uint32_t maxevents, uint32_t timeout)
127 {
128 LE_CHECK(loop != NULL, return LE_FAILURE, "Invalid loop");
129 EventEpoll *epoll = (EventEpoll *)malloc(sizeof(EventEpoll) + sizeof(struct epoll_event) * (maxevents));
130 LE_CHECK(epoll != NULL, return LE_FAILURE, "Failed to alloc memory for epoll");
131 epoll->epollFd = epoll_create(maxevents);
132 LE_CHECK(epoll->epollFd >= 0, free(epoll);
133 return LE_FAILURE, "Failed to create epoll");
134
135 *loop = (EventLoop *)epoll;
136 epoll->loop.maxevents = maxevents;
137 epoll->loop.timeout = timeout;
138 epoll->loop.close = Close_;
139 epoll->loop.runLoop = RunLoop_;
140 epoll->loop.delEvent = DelEvent_;
141 epoll->loop.addEvent = AddEvent_;
142 epoll->loop.modEvent = ModEvent_;
143 return LE_SUCCESS;
144 }
145