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