• 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 #include <stdio.h>
18 #include <fcntl.h>
19 #include "le_epoll.h"
20 #include "le_idle.h"
21 #include "le_timer.h"
22 
23 #define MAX_TIMEOUT_MILLISECONDS (20 * 1000) // 20s
24 
IsValid_(const EventEpoll * loop)25 static int IsValid_(const EventEpoll *loop)
26 {
27     return loop->epollFd >= 0;
28 }
29 
GetEpollEvent_(int fd,int op,struct epoll_event * event)30 static void GetEpollEvent_(int fd, int op, struct epoll_event *event)
31 {
32     event->data.fd = fd;
33     if (LE_TEST_FLAGS(op, EVENT_READ)) {
34         event->events |= EPOLLIN;
35     }
36     if (LE_TEST_FLAGS(op, EVENT_WRITE)) {
37         event->events |= EPOLLOUT;
38     }
39 }
40 
Close_(const EventLoop * loop)41 static LE_STATUS Close_(const EventLoop *loop)
42 {
43     LE_CHECK(loop != NULL, return LE_FAILURE, "Invalid loop");
44     EventEpoll *epoll = (EventEpoll *)loop;
45     LE_LOGV("Close_ epollFd %d", epoll->epollFd);
46     close(epoll->epollFd);
47     free(epoll);
48     return LE_SUCCESS;
49 }
50 
AddEvent_(const EventLoop * loop,const BaseTask * task,int op)51 static LE_STATUS AddEvent_(const EventLoop *loop, const BaseTask *task, int op)
52 {
53     LE_CHECK(loop != NULL, return LE_FAILURE, "Invalid loop");
54     EventEpoll *epoll = (EventEpoll *)loop;
55 
56     int ret = LE_FAILURE;
57     struct epoll_event event = {};
58     int fd = GetSocketFd((const TaskHandle)task);
59     GetEpollEvent_(fd, op, &event);
60     if (IsValid_(epoll) && fd >= 0) {
61         ret = epoll_ctl(epoll->epollFd, EPOLL_CTL_ADD, fd, &event);
62     }
63     LE_CHECK(ret == 0, return LE_FAILURE, "Failed to add epoll_ctl %d ret %d", fd, errno);
64     return LE_SUCCESS;
65 }
66 
ModEvent_(const EventLoop * loop,const BaseTask * task,int op)67 static LE_STATUS ModEvent_(const EventLoop *loop, const BaseTask *task, int op)
68 {
69     LE_CHECK(loop != NULL, return LE_FAILURE, "Invalid loop");
70     EventEpoll *epoll = (EventEpoll *)loop;
71 
72     int ret = LE_FAILURE;
73     struct epoll_event event = {};
74     int fd = GetSocketFd((const TaskHandle)task);
75     GetEpollEvent_(fd, op, &event);
76     if (IsValid_(epoll) && fd >= 0) {
77         ret = epoll_ctl(epoll->epollFd, EPOLL_CTL_MOD, fd, &event);
78     }
79     LE_CHECK(ret == 0, return LE_FAILURE, "Failed to mod epoll_ctl %d ret %d", fd, errno);
80     return LE_SUCCESS;
81 }
82 
DelEvent_(const EventLoop * loop,int fd,int op)83 static LE_STATUS DelEvent_(const EventLoop *loop, int fd, int op)
84 {
85     LE_CHECK(loop != NULL, return LE_FAILURE, "Invalid loop");
86     EventEpoll *epoll = (EventEpoll *)loop;
87 
88     int ret = LE_FAILURE;
89     struct epoll_event event = {};
90     GetEpollEvent_(fd, op, &event);
91     if (IsValid_(epoll) && fd >= 0) {
92         ret = epoll_ctl(epoll->epollFd, EPOLL_CTL_DEL, fd, &event);
93     }
94     LE_CHECK(ret == 0, return LE_FAILURE, "Failed to del epoll_ctl %d ret %d", fd, errno);
95     return LE_SUCCESS;
96 }
97 
RunLoop_(const EventLoop * loop)98 static LE_STATUS RunLoop_(const EventLoop *loop)
99 {
100     LE_CHECK(loop != NULL, return LE_FAILURE, "Invalid loop");
101 
102     EventEpoll *epoll = (EventEpoll *)loop;
103     if (!IsValid_(epoll)) {
104         return LE_FAILURE;
105     }
106 
107     int pid = getpid();
108     while (1) {
109         LE_RunIdle((LoopHandle)&(epoll->loop));
110 
111         uint64_t minTimePeriod = GetMinTimeoutPeriod(loop);
112         int timeout = 0;
113         if (minTimePeriod == 0) {
114             timeout = -1;
115         } else if (GetCurrentTimespec(0) >= minTimePeriod) {
116             timeout = 0;
117         } else {
118             timeout = (int)(minTimePeriod - GetCurrentTimespec(0));
119         }
120         if (timeout < 0 || timeout > MAX_TIMEOUT_MILLISECONDS) {
121             LE_LOGW("timeout:%d", timeout);
122         }
123 
124         int number = epoll_wait(epoll->epollFd, epoll->waitEvents, loop->maxevents, timeout);
125         if (number > 1 && pid != 1) {
126             LE_LOGI("RunLoop_ epoll_wait with number %d", number);
127         }
128         for (int index = 0; index < number; index++) {
129             if ((epoll->waitEvents[index].events & EPOLLIN) == EPOLLIN) {
130                 ProcessEvent(loop, epoll->waitEvents[index].data.fd, EVENT_READ);
131             }
132             if ((epoll->waitEvents[index].events & EPOLLOUT) == EPOLLOUT) {
133                 ProcessEvent(loop, epoll->waitEvents[index].data.fd, EVENT_WRITE);
134             }
135             if (epoll->waitEvents[index].events & (EPOLLERR | EPOLLHUP)) {
136                 LE_LOGV("RunLoop_ fd:%d, error:%d", epoll->waitEvents[index].data.fd, errno);
137                 ProcessEvent(loop, epoll->waitEvents[index].data.fd, EVENT_ERROR);
138             }
139         }
140 
141         if (number > 1 && pid != 1) {
142             LE_LOGI("RunLoop_ epoll_wait finish");
143         }
144         if (GetCurrentTimespec(0) >= minTimePeriod) {
145             CheckTimeoutOfTimer((EventLoop *)loop, GetCurrentTimespec(0));
146         }
147 
148         if (loop->stop) {
149             break;
150         }
151     }
152     return LE_SUCCESS;
153 }
154 
CreateEpollLoop(EventLoop ** loop,uint32_t maxevents,uint32_t timeout)155 LE_STATUS CreateEpollLoop(EventLoop **loop, uint32_t maxevents, uint32_t timeout)
156 {
157     LE_CHECK(loop != NULL, return LE_FAILURE, "Invalid loop");
158     EventEpoll *epoll = (EventEpoll *)malloc(sizeof(EventEpoll) + sizeof(struct epoll_event) * (maxevents));
159     LE_CHECK(epoll != NULL, return LE_FAILURE, "Failed to alloc memory for epoll");
160     epoll->epollFd = epoll_create(maxevents);
161     LE_CHECK(epoll->epollFd >= 0, free(epoll);
162         return LE_FAILURE, "Failed to create epoll");
163     if (fcntl(epoll->epollFd, F_SETFD, FD_CLOEXEC) == -1) {
164         LE_LOGE("fcntl setfd close_on_exec failed, errno: %d", errno);
165     }
166     *loop = (EventLoop *)epoll;
167     epoll->loop.maxevents = maxevents;
168     epoll->loop.timeout = timeout;
169     epoll->loop.close = Close_;
170     epoll->loop.runLoop = RunLoop_;
171     epoll->loop.delEvent = DelEvent_;
172     epoll->loop.addEvent = AddEvent_;
173     epoll->loop.modEvent = ModEvent_;
174     return LE_SUCCESS;
175 }
176