45
45
#include <string.h>
46
46
#include <unistd.h>
54
#define log_error(x) perror(x)
48
#ifdef CHECK_INVARIANTS
58
53
#include "event-internal.h"
59
54
#include "evsignal.h"
61
57
extern volatile sig_atomic_t evsignal_caught;
64
60
int event_count; /* Highest number alloc */
61
int nfds; /* Size of event_* */
62
int fd_count; /* Size of idxplus1_by_fd */
65
63
struct pollfd *event_set;
66
struct event **event_back;
64
struct event **event_r_back;
65
struct event **event_w_back;
66
int *idxplus1_by_fd; /* Index into event_set by fd; we add 1 so
67
* that 0 (which is easy to memset) can mean
67
69
sigset_t evsigmask;
112
114
return (evsignal_recalc(&pop->evsigmask));
117
#ifdef CHECK_INVARIANTS
119
poll_check_ok(struct pollop *pop)
124
for (i = 0; i < pop->fd_count; ++i) {
125
idx = pop->idxplus1_by_fd[i]-1;
128
assert(pop->event_set[idx].fd == i);
129
if (pop->event_set[idx].events & POLLIN) {
130
ev = pop->event_r_back[idx];
132
assert(ev->ev_events & EV_READ);
133
assert(ev->ev_fd == i);
135
if (pop->event_set[idx].events & POLLOUT) {
136
ev = pop->event_w_back[idx];
138
assert(ev->ev_events & EV_WRITE);
139
assert(ev->ev_fd == i);
142
for (i = 0; i < pop->nfds; ++i) {
143
struct pollfd *pfd = &pop->event_set[i];
144
assert(pop->idxplus1_by_fd[pfd->fd] == i+1);
148
#define poll_check_ok(pop)
116
152
poll_dispatch(struct event_base *base, void *arg, struct timeval *tv)
118
int res, i, count, sec, nfds;
154
int res, i, sec, nfds;
120
155
struct pollop *pop = arg;
122
count = pop->event_count;
124
TAILQ_FOREACH(ev, &base->eventqueue, ev_next) {
125
if (nfds + 1 >= count) {
131
/* We need more file descriptors */
132
pop->event_set = realloc(pop->event_set,
133
count * sizeof(struct pollfd));
134
if (pop->event_set == NULL) {
135
log_error("realloc");
138
pop->event_back = realloc(pop->event_back,
139
count * sizeof(struct event *));
140
if (pop->event_back == NULL) {
141
log_error("realloc");
144
pop->event_count = count;
146
if (ev->ev_events & EV_WRITE) {
147
struct pollfd *pfd = &pop->event_set[nfds];
149
pfd->events = POLLOUT;
152
pop->event_back[nfds] = ev;
156
if (ev->ev_events & EV_READ) {
157
struct pollfd *pfd = &pop->event_set[nfds];
160
pfd->events = POLLIN;
163
pop->event_back[nfds] = ev;
169
157
if (evsignal_deliver(&pop->evsigmask) == -1)
172
161
sec = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000;
173
163
res = poll(pop->event_set, nfds, sec);
175
165
if (evsignal_recalc(&pop->evsigmask) == -1)
186
176
} else if (evsignal_caught)
187
177
evsignal_process();
189
LOG_DBG((LOG_MISC, 80, "%s: poll reports %d", __func__, res));
179
event_debug(("%s: poll reports %d", __func__, res));
194
184
for (i = 0; i < nfds; i++) {
195
185
int what = pop->event_set[i].revents;
186
struct event *r_ev = NULL, *w_ev = NULL;
199
192
/* If the file gets closed notify */
193
if (what & (POLLHUP|POLLERR))
201
194
what |= POLLIN|POLLOUT;
203
what |= POLLIN|POLLOUT;
197
r_ev = pop->event_r_back[i];
199
if (what & POLLOUT) {
201
w_ev = pop->event_w_back[i];
211
ev = pop->event_back[i];
212
res &= ev->ev_events;
215
if (!(ev->ev_events & EV_PERSIST))
217
event_active(ev, res, 1);
206
if (r_ev && (res & r_ev->ev_events)) {
207
if (!(r_ev->ev_events & EV_PERSIST))
209
event_active(r_ev, res & r_ev->ev_events, 1);
211
if (w_ev && w_ev != r_ev && (res & w_ev->ev_events)) {
212
if (!(w_ev->ev_events & EV_PERSIST))
214
event_active(w_ev, res & w_ev->ev_events, 1);
225
222
poll_add(void *arg, struct event *ev)
227
224
struct pollop *pop = arg;
225
struct pollfd *pfd = NULL;
229
228
if (ev->ev_events & EV_SIGNAL)
230
229
return (evsignal_add(&pop->evsigmask, ev));
230
if (!(ev->ev_events & (EV_READ|EV_WRITE)))
234
if (pop->nfds + 1 >= pop->event_count) {
235
if (pop->event_count < 32)
236
pop->event_count = 32;
238
pop->event_count *= 2;
240
/* We need more file descriptors */
241
pop->event_set = realloc(pop->event_set,
242
pop->event_count * sizeof(struct pollfd));
243
if (pop->event_set == NULL) {
244
event_warn("realloc");
247
pop->event_r_back = realloc(pop->event_r_back,
248
pop->event_count * sizeof(struct event *));
249
pop->event_w_back = realloc(pop->event_w_back,
250
pop->event_count * sizeof(struct event *));
251
if (pop->event_r_back == NULL ||
252
pop->event_w_back == NULL) {
253
event_warn("realloc");
257
if (ev->ev_fd >= pop->fd_count) {
259
if (pop->fd_count < 32)
262
new_count = pop->fd_count * 2;
263
while (new_count <= ev->ev_fd)
265
pop->idxplus1_by_fd =
266
realloc(pop->idxplus1_by_fd, new_count*sizeof(int));
267
if (pop->idxplus1_by_fd == NULL) {
268
event_warn("realloc");
271
memset(pop->idxplus1_by_fd + pop->fd_count,
272
0, sizeof(int)*(new_count - pop->fd_count));
273
pop->fd_count = new_count;
276
i = pop->idxplus1_by_fd[ev->ev_fd] - 1;
278
pfd = &pop->event_set[i];
281
pfd = &pop->event_set[i];
284
pop->event_w_back[i] = pop->event_r_back[i] = NULL;
285
pop->idxplus1_by_fd[ev->ev_fd] = i + 1;
289
if (ev->ev_events & EV_WRITE) {
290
pfd->events |= POLLOUT;
291
pop->event_w_back[i] = ev;
293
if (ev->ev_events & EV_READ) {
294
pfd->events |= POLLIN;
295
pop->event_r_back[i] = ev;
240
307
poll_del(void *arg, struct event *ev)
242
309
struct pollop *pop = arg;
244
if (!(ev->ev_events & EV_SIGNAL))
247
return (evsignal_del(&pop->evsigmask, ev));
310
struct pollfd *pfd = NULL;
313
if (ev->ev_events & EV_SIGNAL)
314
return (evsignal_del(&pop->evsigmask, ev));
316
if (!(ev->ev_events & (EV_READ|EV_WRITE)))
320
i = pop->idxplus1_by_fd[ev->ev_fd] - 1;
324
/* Do we still want to read or write? */
325
pfd = &pop->event_set[i];
326
if (ev->ev_events & EV_READ) {
327
pfd->events &= ~POLLIN;
328
pop->event_r_back[i] = NULL;
330
if (ev->ev_events & EV_WRITE) {
331
pfd->events &= ~POLLOUT;
332
pop->event_w_back[i] = NULL;
336
/* Another event cares about that fd. */
339
/* Okay, so we aren't interested in that fd anymore. */
340
pop->idxplus1_by_fd[ev->ev_fd] = 0;
343
if (i != pop->nfds) {
345
* Shift the last pollfd down into the now-unoccupied
348
memcpy(&pop->event_set[i], &pop->event_set[pop->nfds],
349
sizeof(struct pollfd));
350
pop->event_r_back[i] = pop->event_r_back[pop->nfds];
351
pop->event_w_back[i] = pop->event_w_back[pop->nfds];
352
pop->idxplus1_by_fd[pop->event_set[i].fd] = i + 1;