1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include "evloop.h"
static int m_kq;
static struct kevent m_evs[100];
static uint8_t m_valid[100];
int
evloop_init(void)
{
if (timeheap_init() != 0)
return -1;
m_kq = kqueue();
return m_kq >= 0 ? 0 : -1;
}
int
fdev_new(struct fdev *ev, int fd, uint16_t flags, evloop_cb_t cb, void *arg)
{
ev->fd = fd;
ev->cb = cb;
ev->arg = arg;
ev->flags = 0;
ev->rdidx = -1;
ev->wridx = -1;
return fdev_enable(ev, flags);
}
int
fdev_enable(struct fdev *ev, uint16_t flags)
{
struct kevent kev[2], *kp = NULL;
int count = 0;
uint16_t sf = ev->flags;
ev->flags |= flags;
if ((sf & EV_READ) == 0 && (flags & EV_READ) != 0) {
EV_SET(&kev[0], ev->fd, EVFILT_READ, EV_ADD, 0, 0, ev);
kp = kev;
count = 1;
}
if ((sf & EV_WRITE) == 0 && (flags & EV_WRITE) != 0) {
EV_SET(&kev[1], ev->fd, EVFILT_WRITE, EV_ADD, 0, 0, ev);
if (count == 0)
kp = &kev[1];
count++;
}
return count > 0 ? kevent(m_kq, kp, count, NULL, 0, NULL) : 0;
}
int
fdev_disable(struct fdev *ev, uint16_t flags)
{
struct kevent kev[2], *kp = NULL;
int count = 0;
uint16_t sf = ev->flags;
ev->flags &= ~flags;
if ((sf & EV_READ) != 0 && (flags & EV_READ) != 0) {
EV_SET(&kev[0], ev->fd, EVFILT_READ, EV_DELETE, 0, 0, ev);
kp = kev;
count = 1;
}
if ((sf & EV_WRITE) != 0 && (flags & EV_WRITE) != 0) {
EV_SET(&kev[1], ev->fd, EVFILT_WRITE, EV_DELETE, 0, 0, ev);
if (count == 0)
kp = &kev[1];
count++;
}
return count > 0 ? kevent(m_kq, kp, count, NULL, 0, NULL) : 0;
}
int
fdev_del(struct fdev *ev)
{
if (ev->rdidx >= 0)
m_valid[ev->rdidx] = 0;
if (ev->wridx >= 0)
m_valid[ev->wridx] = 0;
return fdev_disable(ev, EV_READ|EV_WRITE);
}
int
evloop(void)
{
int nev, i;
struct timespec delay;
while (1) {
evtimers_run();
delay = evtimer_delay();
if ((nev = kevent(m_kq, NULL, 0, m_evs, 100, &delay)) < 0) {
if (errno == EINTR)
continue;
else
return -1;
}
memset(m_valid, 1, nev);
for (i = 0; i < nev; i++) {
if (m_evs[i].flags & EV_ERROR) {
errno = m_evs[i].data;
return -1;
}
struct fdev *ev = (struct fdev *)m_evs[i].udata;
switch (m_evs[i].filter) {
case EVFILT_READ:
ev->rdidx = i;
break;
case EVFILT_WRITE:
ev->wridx = i;
break;
}
}
for (i = 0; i < nev; i++) {
if (!m_valid[i])
continue;
struct fdev *ev = (struct fdev *)m_evs[i].udata;
switch (m_evs[i].filter) {
case EVFILT_READ:
if (ev->flags & EV_READ)
ev->cb(ev->fd, EV_READ, ev->arg);
if (m_valid[i])
ev->rdidx = -1;
break;
case EVFILT_WRITE:
if (ev->flags & EV_WRITE)
ev->cb(ev->fd, EV_WRITE, ev->arg);
if (m_valid[i])
ev->wridx = -1;
break;
}
}
}
}
|