xref: /f-stack/lib/ff_epoll.c (revision 2aa28acd)
1 #include <stdio.h>
2 #include <stdint.h>
3 #include <string.h>
4 #include <stdlib.h>
5 #include <stdarg.h>
6 #include <sched.h>
7 #include <fcntl.h>
8 #include <errno.h>
9 #include <assert.h>
10 #include <unistd.h>
11 #include <netinet/in.h>
12 #include <sys/types.h>
13 #include <sys/socket.h>
14 #include <sys/time.h>
15 #include <sys/select.h>
16 #include <sys/syscall.h>
17 #include <arpa/inet.h>
18 #include <sys/epoll.h>
19 
20 #include "ff_api.h"
21 #include "ff_errno.h"
22 
23 
24 int
25 ff_epoll_create(int size __attribute__((__unused__)))
26 {
27     return ff_kqueue();
28 }
29 
30 int
31 ff_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
32 {
33     struct kevent kev[3];
34 
35     if (!event && op != EPOLL_CTL_DEL) {
36         errno = EINVAL;
37         return -1;
38     }
39 
40     if (op == EPOLL_CTL_ADD){
41         EV_SET(&kev[0], fd, EVFILT_READ,
42             EV_ADD | (event->events & EPOLLIN ? 0 : EV_DISABLE), 0, 0, NULL);
43         EV_SET(&kev[1], fd, EVFILT_WRITE,
44             EV_ADD | (event->events & EPOLLOUT ? 0 : EV_DISABLE), 0, 0, NULL);
45         EV_SET(&kev[2], fd, EVFILT_USER, EV_ADD,
46                 event->events & EPOLLRDHUP ? 1 : 0, 0, NULL);
47     } else if (op == EPOLL_CTL_DEL) {
48         EV_SET(&kev[0], fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
49         EV_SET(&kev[1], fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
50         EV_SET(&kev[2], fd, EVFILT_USER, EV_DELETE, 0, 0, NULL);
51     } else if (op == EPOLL_CTL_MOD) {
52         EV_SET(&kev[0], fd, EVFILT_READ,
53             event->events & EPOLLIN ? EV_ENABLE : EV_DISABLE, 0, 0, NULL);
54         EV_SET(&kev[1], fd, EVFILT_WRITE,
55             event->events & EPOLLOUT ? EV_ENABLE : EV_DISABLE, 0, 0, NULL);
56         EV_SET(&kev[2], fd, EVFILT_USER, 0,
57             NOTE_FFCOPY | (event->events & EPOLLRDHUP ? 1 : 0), 0, NULL);
58     } else {
59         errno = EINVAL;
60         return -1;
61     }
62 
63     return ff_kevent(epfd, kev, 3, NULL, 0, NULL);
64 }
65 
66 static void
67 ff_event_to_epoll(void **ev, struct kevent *kev)
68 {
69     unsigned int event_one = 0;
70     struct epoll_event **ppev = (struct epoll_event **)ev;
71 
72     if (kev->filter == EVFILT_READ) {
73         if (kev->data || !(kev->flags & EV_EOF)) {
74             event_one |= EPOLLIN;
75         }
76     } else if (kev->filter == EVFILT_WRITE) {
77         event_one |= EPOLLOUT;
78     }
79 
80     if (kev->flags & EV_ERROR) {
81         event_one |= EPOLLERR;
82     }
83 
84     if (kev->flags & EV_EOF) {
85         event_one |= EPOLLHUP;
86 
87         if (kev->fflags) {
88             event_one |= EPOLLERR;
89         }
90 
91         if (kev->filter == EVFILT_READ) {
92             event_one |= EPOLLIN;
93         } else if (kev->filter == EVFILT_WRITE) {
94             event_one |= EPOLLERR;
95         }
96     }
97 
98     (*ppev)->events   = event_one;
99     (*ppev)->data.fd  = kev->ident;
100     (*ppev)++;
101 }
102 
103 int
104 ff_epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)
105 {
106     int i, ret;
107     if (!events || maxevents < 1) {
108         errno = EINVAL;
109         return -1;
110     }
111 
112     return ff_kevent_do_each(epfd, NULL, 0, events, maxevents, NULL, ff_event_to_epoll);
113 }
114 
115