/
poll.c
142 lines (127 loc) · 3.12 KB
/
poll.c
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
141
142
#include <assert.h>
#include <errno.h>
#include <poll.h>
#include <stdlib.h>
#include <string.h>
#include "evloop.h"
#define POLL_INIT_SIZE 64
struct poll_ev {
struct fdev *ev;
evloop_cb_t cb;
void *arg;
};
static struct pollfd *m_pfds;
static struct poll_ev *m_pevs;
static int m_cap, m_size;
static int m_cur = -1, m_curdel;
static int
poll_grow(void)
{
int ncap = m_cap * 2;
struct pollfd *nm_pfds = realloc(m_pfds, ncap * sizeof(*m_pfds));
struct poll_ev *nm_pevs = realloc(m_pevs, ncap * sizeof(*m_pevs));
if (nm_pfds != NULL)
m_pfds = nm_pfds;
if (nm_pevs != NULL)
m_pevs = nm_pevs;
if (nm_pfds == NULL || nm_pevs == NULL)
return errno;
m_cap = ncap;
return 0;
}
int
evloop_init(void)
{
if (timeheap_init() != 0)
return -1;
m_cap = POLL_INIT_SIZE;
m_size = 0;
if ((m_pfds = calloc(m_cap, sizeof(*m_pfds))) == NULL)
return -1;
if ((m_pevs = calloc(m_cap, sizeof(*m_pevs))) == NULL) {
free(m_pfds);
return -1;
}
return 0;
}
int
fdev_new(struct fdev *ev, int fd, uint16_t flags, evloop_cb_t cb, void *arg)
{
if (m_size == m_cap && poll_grow() != 0)
return errno;
ev->i = m_size;
m_size++;
m_pfds[ev->i].fd = fd;
m_pfds[ev->i].events =
((flags & EV_READ) ? POLLIN : 0) |
((flags & EV_WRITE) ? POLLOUT : 0);
m_pevs[ev->i].ev = ev;
m_pevs[ev->i].cb = cb;
m_pevs[ev->i].arg = arg;
return 0;
}
int
fdev_enable(struct fdev *ev, uint16_t flags)
{
m_pfds[ev->i].events |=
((flags & EV_READ) ? POLLIN : 0) |
((flags & EV_WRITE) ? POLLOUT : 0);
return 0;
}
int
fdev_disable(struct fdev *ev, uint16_t flags)
{
short pflags =
((flags & EV_READ) ? POLLIN : 0) |
((flags & EV_WRITE) ? POLLOUT : 0);
m_pfds[ev->i].events &= ~pflags;
return 0;
}
int
fdev_del(struct fdev *ev)
{
assert(ev->i < m_size);
m_size--;
m_pfds[ev->i] = m_pfds[m_size];
m_pevs[ev->i] = m_pevs[m_size];
m_pevs[ev->i].ev->i = ev->i;
if (ev->i == m_cur)
m_curdel = 1;
return 0;
}
int
evloop(void)
{
int millisecs;
struct timespec delay;
while (1) {
evtimers_run();
delay = evtimer_delay();
if (delay.tv_sec >= 0)
millisecs = delay.tv_sec * 1000 + delay.tv_nsec / 1000000;
else
millisecs = -1;
if (poll(m_pfds, m_size, millisecs) < 0) {
if (errno == EINTR)
continue;
else
return -1;
}
m_cur = 0;
while (m_cur < m_size) {
struct pollfd *pfd = &m_pfds[m_cur];
struct poll_ev *pev = &m_pevs[m_cur];
if ((pfd->events & POLLIN &&
pfd->revents & (POLLIN|POLLERR|POLLHUP)))
pev->cb(pfd->fd, EV_READ, pev->arg);
if ((!m_curdel && pfd->events & POLLOUT &&
pfd->revents & (POLLOUT|POLLERR|POLLHUP)))
pev->cb(pfd->fd, EV_WRITE, pev->arg);
if (!m_curdel)
m_cur++;
else
m_curdel = 0;
}
m_cur = -1;
}
}