• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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