33 #include <sys/types.h>
34 #ifdef HAVE_SYS_TIME_H
37 #include <sys/_time.h>
39 #ifdef HAVE_SYS_SELECT_H
40 #include <sys/select.h>
42 #include <sys/queue.h>
49 #ifdef CHECK_INVARIANTS
54 #include "event-internal.h"
59 #define howmany(x, y) (((x)+((y)-1))/(y))
65 fd_set *event_readset_in;
66 fd_set *event_writeset_in;
67 fd_set *event_readset_out;
68 fd_set *event_writeset_out;
69 struct event **event_r_by_fd;
70 struct event **event_w_by_fd;
73 static void *select_init (
struct event_base *);
74 static int select_add (
void *,
struct event *);
75 static int select_del (
void *,
struct event *);
77 static void select_dealloc (
struct event_base *,
void *);
79 const struct eventop selectops = {
89 static int select_resize(
struct selectop *sop,
int fdsz);
97 if (getenv(
"EVENT_NOSELECT"))
100 if (!(sop = calloc(1,
sizeof(
struct selectop))))
103 select_resize(sop, howmany(32 + 1, NFDBITS)*
sizeof(fd_mask));
110 #ifdef CHECK_INVARIANTS
112 check_selectop(
struct selectop *sop)
115 for (i = 0; i <= sop->event_fds; ++
i) {
116 if (FD_ISSET(i, sop->event_readset_in)) {
117 assert(sop->event_r_by_fd[i]);
118 assert(sop->event_r_by_fd[i]->ev_events & EV_READ);
119 assert(sop->event_r_by_fd[i]->ev_fd == i);
121 assert(! sop->event_r_by_fd[i]);
123 if (FD_ISSET(i, sop->event_writeset_in)) {
124 assert(sop->event_w_by_fd[i]);
125 assert(sop->event_w_by_fd[i]->ev_events & EV_WRITE);
126 assert(sop->event_w_by_fd[i]->ev_fd == i);
128 assert(! sop->event_w_by_fd[i]);
134 #define check_selectop(sop) do { (void) sop; } while (0)
145 memcpy(sop->event_readset_out, sop->event_readset_in,
147 memcpy(sop->event_writeset_out, sop->event_writeset_in,
150 res = select(sop->event_fds + 1, sop->event_readset_out,
151 sop->event_writeset_out, NULL, tv);
156 if (errno != EINTR) {
157 event_warn(
"select");
161 evsignal_process(base);
163 }
else if (base->sig.evsignal_caught) {
164 evsignal_process(base);
167 event_debug((
"%s: select reports %d", __func__, res));
170 i = random() % (sop->event_fds+1);
171 for (j = 0; j <= sop->event_fds; ++j) {
172 struct event *r_ev = NULL, *w_ev = NULL;
173 if (++i >= sop->event_fds+1)
177 if (FD_ISSET(i, sop->event_readset_out)) {
178 r_ev = sop->event_r_by_fd[
i];
181 if (FD_ISSET(i, sop->event_writeset_out)) {
182 w_ev = sop->event_w_by_fd[
i];
185 if (r_ev && (res & r_ev->ev_events)) {
186 event_active(r_ev, res & r_ev->ev_events, 1);
188 if (w_ev && w_ev != r_ev && (res & w_ev->ev_events)) {
189 event_active(w_ev, res & w_ev->ev_events, 1);
199 select_resize(
struct selectop *sop,
int fdsz)
201 int n_events, n_events_old;
203 fd_set *readset_in = NULL;
204 fd_set *writeset_in = NULL;
205 fd_set *readset_out = NULL;
206 fd_set *writeset_out = NULL;
207 struct event **r_by_fd = NULL;
208 struct event **w_by_fd = NULL;
210 n_events = (fdsz/
sizeof(fd_mask)) * NFDBITS;
211 n_events_old = (sop->event_fdsz/
sizeof(fd_mask)) * NFDBITS;
213 if (sop->event_readset_in)
216 if ((readset_in = realloc(sop->event_readset_in, fdsz)) == NULL)
218 sop->event_readset_in = readset_in;
219 if ((readset_out = realloc(sop->event_readset_out, fdsz)) == NULL)
221 sop->event_readset_out = readset_out;
222 if ((writeset_in = realloc(sop->event_writeset_in, fdsz)) == NULL)
224 sop->event_writeset_in = writeset_in;
225 if ((writeset_out = realloc(sop->event_writeset_out, fdsz)) == NULL)
227 sop->event_writeset_out = writeset_out;
228 if ((r_by_fd = realloc(sop->event_r_by_fd,
229 n_events*
sizeof(
struct event*))) == NULL)
231 sop->event_r_by_fd = r_by_fd;
232 if ((w_by_fd = realloc(sop->event_w_by_fd,
233 n_events *
sizeof(
struct event*))) == NULL)
235 sop->event_w_by_fd = w_by_fd;
237 memset((
char *)sop->event_readset_in + sop->event_fdsz, 0,
238 fdsz - sop->event_fdsz);
239 memset((
char *)sop->event_writeset_in + sop->event_fdsz, 0,
240 fdsz - sop->event_fdsz);
241 memset(sop->event_r_by_fd + n_events_old, 0,
242 (n_events-n_events_old) *
sizeof(
struct event*));
243 memset(sop->event_w_by_fd + n_events_old, 0,
244 (n_events-n_events_old) *
sizeof(
struct event*));
246 sop->event_fdsz = fdsz;
252 event_warn(
"malloc");
258 select_add(
void *arg,
struct event *ev)
262 if (ev->ev_events & EV_SIGNAL)
263 return (evsignal_add(ev));
270 if (sop->event_fds < ev->ev_fd) {
271 int fdsz = sop->event_fdsz;
273 if (fdsz <
sizeof(fd_mask))
274 fdsz =
sizeof(fd_mask);
277 (howmany(ev->ev_fd + 1, NFDBITS) *
sizeof(fd_mask)))
280 if (fdsz != sop->event_fdsz) {
281 if (select_resize(sop, fdsz)) {
287 sop->event_fds = ev->ev_fd;
290 if (ev->ev_events & EV_READ) {
291 FD_SET(ev->ev_fd, sop->event_readset_in);
292 sop->event_r_by_fd[ev->ev_fd] = ev;
294 if (ev->ev_events & EV_WRITE) {
295 FD_SET(ev->ev_fd, sop->event_writeset_in);
296 sop->event_w_by_fd[ev->ev_fd] = ev;
308 select_del(
void *arg,
struct event *ev)
313 if (ev->ev_events & EV_SIGNAL)
314 return (evsignal_del(ev));
316 if (sop->event_fds < ev->ev_fd) {
321 if (ev->ev_events & EV_READ) {
322 FD_CLR(ev->ev_fd, sop->event_readset_in);
323 sop->event_r_by_fd[ev->ev_fd] = NULL;
326 if (ev->ev_events & EV_WRITE) {
327 FD_CLR(ev->ev_fd, sop->event_writeset_in);
328 sop->event_w_by_fd[ev->ev_fd] = NULL;
336 select_dealloc(
struct event_base *base,
void *arg)
340 evsignal_dealloc(base);
341 if (sop->event_readset_in)
342 free(sop->event_readset_in);
343 if (sop->event_writeset_in)
344 free(sop->event_writeset_in);
345 if (sop->event_readset_out)
346 free(sop->event_readset_out);
347 if (sop->event_writeset_out)
348 free(sop->event_writeset_out);
349 if (sop->event_r_by_fd)
350 free(sop->event_r_by_fd);
351 if (sop->event_w_by_fd)
352 free(sop->event_w_by_fd);
354 memset(sop, 0,
sizeof(
struct selectop));