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 "nstackx_epoll.h"
17 #include "nstackx_log.h"
18 #include "nstackx_error.h"
19 
20 #define TAG "nStackXEpoll"
21 #define MAX_EPOLL_SIZE 128
22 
RefreshEpollTask(EpollTask * task,uint32_t events)23 int32_t RefreshEpollTask(EpollTask *task, uint32_t events)
24 {
25     struct epoll_event event;
26     if (task == NULL) {
27         return NSTACKX_EINVAL;
28     }
29     event.data.ptr = task;
30     event.events = events;
31 
32     if (epoll_ctl(task->epollfd, EPOLL_CTL_MOD, task->taskfd, &event) < 0) {
33         LOGE(TAG, "Refresh task failed: %d", errno);
34         return NSTACKX_EFAILED;
35     }
36 
37     return NSTACKX_EOK;
38 }
39 
RegisterEpollTask(EpollTask * task,uint32_t events)40 int32_t RegisterEpollTask(EpollTask *task, uint32_t events)
41 {
42     struct epoll_event event;
43     if (task == NULL) {
44         return NSTACKX_EINVAL;
45     }
46     event.data.ptr = task;
47     event.events = events;
48     if (epoll_ctl(task->epollfd, EPOLL_CTL_ADD, task->taskfd, &event) < 0) {
49         LOGE(TAG, "Register task failed: %d", errno);
50         return NSTACKX_EFAILED;
51     }
52     return NSTACKX_EOK;
53 }
54 
DeRegisterEpollTask(EpollTask * task)55 int32_t DeRegisterEpollTask(EpollTask *task)
56 {
57     if (task == NULL) {
58         return NSTACKX_EINVAL;
59     }
60     if (epoll_ctl(task->epollfd, EPOLL_CTL_DEL, task->taskfd, NULL) < 0) {
61         LOGE(TAG, "De-register task failed: %d", errno);
62         return NSTACKX_EFAILED;
63     }
64 
65     return NSTACKX_EOK;
66 }
67 
CreateEpollDesc(void)68 EpollDesc CreateEpollDesc(void)
69 {
70     return epoll_create(1);
71 }
72 
EpollLoop(EpollDesc epollfd,int32_t timeout)73 int32_t EpollLoop(EpollDesc epollfd, int32_t timeout)
74 {
75     int32_t i, nfds;
76     EpollTask *task = NULL;
77     struct epoll_event events[MAX_EPOLL_SIZE];
78 
79     nfds = epoll_wait(epollfd, events, MAX_EPOLL_SIZE, timeout);
80     if (nfds < 0) {
81         if (errno == EINTR) {
82             LOGD(TAG, "epoll_wait EINTR");
83             return NSTACKX_EINTR;
84         }
85         LOGE(TAG, "epoll_wait returned n=%d, error: %d", nfds, errno);
86         return NSTACKX_EFAILED;
87     }
88 
89     for (i = 0; i < nfds; i++) {
90         task = events[i].data.ptr;
91         if (task == NULL) {
92             continue;
93         }
94 
95         if (events[i].events & EPOLLIN) {
96             if (task->readHandle != NULL) {
97                 task->readHandle(task);
98             }
99         }
100 
101         if (events[i].events & EPOLLOUT) {
102             if (task->writeHandle != NULL) {
103                 task->writeHandle(task);
104             }
105         }
106     }
107 
108     return ((nfds > 0) ? nfds : NSTACKX_ETIMEOUT);
109 }
110