更新日期: 2022/06/01 来源: https://gitee.com/weharmony/kernel_liteos_a_note
fs_epoll.c
浏览该文件的文档.
1/*
2 * Copyright (c) 2021-2021 Huawei Device Co., Ltd. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification,
5 * are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 *
14 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific prior written
16 * permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include "epoll.h"
32#include <stdint.h>
33#include <poll.h>
34#include <errno.h>
35#include <string.h>
36#include "pthread.h"
37
38/* 100, the number of fd one epollfd can control */
39#define EPOLL_DEFAULT_SIZE 100
40
41/* Internal data, used to manage each epoll fd */
42struct epoll_head {
43 int size;
46};
47
48STATIC pthread_mutex_t g_epollMutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
49
50#ifndef MAX_EPOLL_FD
51#define MAX_EPOLL_FD CONFIG_EPOLL_DESCRIPTORS
52#endif
53
54/* Record the kernel fd of epoll */
55STATIC fd_set g_epollFdSet;
56
57/* Record the private data of epoll */
58STATIC struct epoll_head *g_epPrivBuf[MAX_EPOLL_FD];
59
60/**
61 * Alloc sysFd, storage epoll private data, set using bit.
62 *
63 * @param maxfdp: Maximum allowed application of sysFd.
64 * @param head: Private data.
65 * @return the index of the new fd; -1 on error
66 */
67static int EpollAllocSysFd(int maxfdp, struct epoll_head *head)
68{
69 int i;
70
71 fd_set *fdset = &g_epollFdSet;
72
73 for (i = 0; i < maxfdp; i++) {
74 if (fdset && !(FD_ISSET(i, fdset))) {
75 FD_SET(i, fdset);
76 if (!g_epPrivBuf[i]) {
77 g_epPrivBuf[i] = head;
78 return i + EPOLL_FD_OFFSET;
79 }
80 }
81 }
82
83 set_errno(EMFILE);
84 return -1;
85}
86
87/**
88 * free sysFd, delete epoll private data, clear using bit.
89 *
90 * @param fd: epoll fd.
91 * @return 0 or -1
92 */
93static int EpollFreeSysFd(int fd)
94{
95 int efd = fd - EPOLL_FD_OFFSET;
96
97 if ((efd < 0) || (efd >= MAX_EPOLL_FD)) {
98 set_errno(EMFILE);
99 return -1;
100 }
101
102 fd_set *fdset = &g_epollFdSet;
103 if (fdset && FD_ISSET(efd, fdset)) {
104 FD_CLR(efd, fdset);
105 g_epPrivBuf[efd] = NULL;
106 }
107
108 return 0;
109}
110
111/**
112 * get private data by epoll fd
113 *
114 * @param fd: epoll fd.
115 * @return point to epoll_head
116 */
117static struct epoll_head *EpollGetDataBuff(int fd)
118{
119 int id = fd - EPOLL_FD_OFFSET;
120
121 if ((id < 0) || (id >= MAX_EPOLL_FD)) {
122 return NULL;
123 }
124
125 return g_epPrivBuf[id];
126}
127
128/**
129 * when do EPOLL_CTL_ADD, need check if fd exist
130 *
131 * @param epHead: epoll control head, find by epoll id .
132 * @param fd: ctl add fd.
133 * @return 0 or -1
134 */
135static int CheckFdExist(struct epoll_head *epHead, int fd)
136{
137 int i;
138 for (i = 0; i < epHead->nodeCount; i++) {
139 if (epHead->evs[i].data.fd == fd) {
140 return -1;
141 }
142 }
143
144 return 0;
145}
146
147/**
148 * close epoll
149 *
150 * @param epHead: epoll control head.
151 * @return void
152 */
153static VOID DoEpollClose(struct epoll_head *epHead)
154{
155 if (epHead != NULL) {
156 if (epHead->evs != NULL) {
157 free(epHead->evs);
158 }
159
160 free(epHead);
161 }
162
163 return;
164}
165
166/**
167 * epoll_create unsupported api
168 *
169 * epoll_create is implemented by calling epoll_create1, it's parameter 'size' is useless.
170 *
171 * epoll_create1,
172 * The simple version of epoll does not use red-black trees,
173 * so when fd is normal value (greater than 0),
174 * actually allocated epoll can manage num of EPOLL_DEFAULT_SIZE
175 *
176 * @param flags: not actually used
177 * @return epoll fd
178 */
179int epoll_create1(int flags)
180{
181 (void)flags;
182 int fd = -1;
183
184 struct epoll_head *epHead = (struct epoll_head *)malloc(sizeof(struct epoll_head));
185 if (epHead == NULL) {
186 set_errno(ENOMEM);
187 return fd;
188 }
189
190 /* actually allocated epoll can manage num is EPOLL_DEFAULT_SIZE */
191 epHead->size = EPOLL_DEFAULT_SIZE;
192 epHead->nodeCount = 0;
193 epHead->evs = malloc(sizeof(struct epoll_event) * EPOLL_DEFAULT_SIZE);
194 if (epHead->evs == NULL) {
195 free(epHead);
196 set_errno(ENOMEM);
197 return fd;
198 }
199
200 /* fd set, get sysfd, for close */
202 fd = EpollAllocSysFd(MAX_EPOLL_FD, epHead);
203 if (fd == -1) {
205 DoEpollClose(epHead);
206 set_errno(EMFILE);
207 return fd;
208 }
210 return fd;
211}
212
213/**
214 * epoll_close,
215 * called by close
216 * @param epfd: epoll fd
217 * @return 0 or -1
218 */
219int epoll_close(int epfd)
220{
221 struct epoll_head *epHead = NULL;
222
223 epHead = EpollGetDataBuff(epfd);
224 if (epHead == NULL) {
225 set_errno(EBADF);
226 return -1;
227 }
228
229 DoEpollClose(epHead);
230 return EpollFreeSysFd(epfd);
231}
232
233int epoll_ctl(int epfd, int op, int fd, struct epoll_event *ev)
234{
235 struct epoll_head *epHead = NULL;
236 int i;
237 int ret = -1;
238
239 epHead = EpollGetDataBuff(epfd);
240 if (epHead == NULL) {
241 set_errno(EBADF);
242 return ret;
243 }
244
245 if (ev == NULL) {
246 set_errno(EINVAL);
247 return -1;
248 }
249
250 switch (op) {
251 case EPOLL_CTL_ADD:
252 ret = CheckFdExist(epHead, fd);
253 if (ret == -1) {
254 set_errno(EEXIST);
255 return -1;
256 }
257
258 if (epHead->nodeCount == EPOLL_DEFAULT_SIZE) {
259 set_errno(ENOMEM);
260 return -1;
261 }
262
263 epHead->evs[epHead->nodeCount].events = ev->events | POLLERR | POLLHUP;
264 epHead->evs[epHead->nodeCount].data.fd = fd;
265 epHead->nodeCount++;
266 return 0;
267 case EPOLL_CTL_DEL:
268 for (i = 0; i < epHead->nodeCount; i++) {
269 if (epHead->evs[i].data.fd != fd) {
270 continue;
271 }
272
273 if (i != epHead->nodeCount - 1) {
274 memmove_s(&epHead->evs[i], epHead->nodeCount - i, &epHead->evs[i + 1],
275 epHead->nodeCount - i);
276 }
277 epHead->nodeCount--;
278 return 0;
279 }
280 set_errno(ENOENT);
281 return -1;
282 case EPOLL_CTL_MOD:
283 for (i = 0; i < epHead->nodeCount; i++) {
284 if (epHead->evs[i].data.fd == fd) {
285 epHead->evs[i].events = ev->events | POLLERR | POLLHUP;
286 return 0;
287 }
288 }
289 set_errno(ENOENT);
290 return -1;
291 default:
292 set_errno(EINVAL);
293 return -1;
294 }
295}
296
297int epoll_wait(int epfd, FAR struct epoll_event *evs, int maxevents, int timeout)
298{
299 struct epoll_head *epHead = NULL;
300 int ret;
301 int counter;
302 int i;
303 struct pollfd *pFd = NULL;
304 int pollSize;
305
306 epHead = EpollGetDataBuff(epfd);
307 if (epHead== NULL) {
308 set_errno(EBADF);
309 return -1;
310 }
311
312 if ((maxevents <= 0) || (evs == NULL)) {
313 set_errno(EINVAL);
314 return -1;
315 }
316
317 if (maxevents > epHead->nodeCount) {
318 pollSize = epHead->nodeCount;
319 } else {
320 pollSize = maxevents;
321 }
322
323 pFd = malloc(sizeof(struct pollfd) * pollSize);
324 if (pFd == NULL) {
325 set_errno(EINVAL);
326 return -1;
327 }
328
329 for (i = 0; i < epHead->nodeCount; i++) {
330 pFd[i].fd = epHead->evs[i].data.fd;
331 pFd[i].events = (short)epHead->evs[i].events;
332 }
333
334
335 ret = poll(pFd, pollSize, timeout);
336 if (ret <= 0) {
337 free(pFd);
338 return 0;
339 }
340
341 for (i = 0, counter = 0; i < ret && counter < pollSize; counter++) {
342 if (pFd[counter].revents != 0) {
343 evs[i].data.fd = pFd[counter].fd;
344 evs[i].events = pFd[counter].revents;
345 i++;
346 }
347 }
348
349 free(pFd);
350 return i;
351}
352
static int EpollAllocSysFd(int maxfdp, struct epoll_head *head)
Definition: fs_epoll.c:67
int epoll_close(int epfd)
Definition: fs_epoll.c:219
int epoll_wait(int epfd, FAR struct epoll_event *evs, int maxevents, int timeout)
Definition: fs_epoll.c:297
static int EpollFreeSysFd(int fd)
Definition: fs_epoll.c:93
STATIC fd_set g_epollFdSet
Definition: fs_epoll.c:55
static struct epoll_head * EpollGetDataBuff(int fd)
Definition: fs_epoll.c:117
STATIC struct epoll_head * g_epPrivBuf[MAX_EPOLL_FD]
Definition: fs_epoll.c:58
static int CheckFdExist(struct epoll_head *epHead, int fd)
Definition: fs_epoll.c:135
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *ev)
Definition: fs_epoll.c:233
static VOID DoEpollClose(struct epoll_head *epHead)
Definition: fs_epoll.c:153
int epoll_create1(int flags)
Definition: fs_epoll.c:179
STATIC pthread_mutex_t g_epollMutex
Definition: fs_epoll.c:48
void * malloc(size_t size)
动态分配内存块大小
Definition: malloc.c:81
void free(void *ptr)
释放ptr所指向的内存空间
Definition: malloc.c:66
int pthread_mutex_lock(pthread_mutex_t *mutex)
互斥锁加锁操作
int pthread_mutex_unlock(pthread_mutex_t *mutex)
解锁互斥锁
UINT32 events
Definition: epoll.h:71
epoll_data_t data
Definition: epoll.h:72
int nodeCount
Definition: fs_epoll.c:44
int size
Definition: fs_epoll.c:43
struct epoll_event * evs
Definition: fs_epoll.c:45
ARG_NUM_3 ARG_NUM_1 ARG_NUM_2 ARG_NUM_2 ARG_NUM_3 ARG_NUM_1 ARG_NUM_4 ARG_NUM_2 ARG_NUM_2 ARG_NUM_5 ARG_NUM_2 void
int fd
Definition: epoll.h:65