X-Git-Url: http://git.pk910.de/?p=ircu2.10.12-pk.git;a=blobdiff_plain;f=ircd%2Fengine_kqueue.c;h=b3f535f7d8db52825068a42f959ac06d62cadd9b;hp=577cac01d57cd4785dbbe70a26f00b61fda9daa8;hb=f50e98744ac3e53605d59a2f313d610c9abc8f26;hpb=ee016334f39740735682d5ceb068b340ddd42ec3 diff --git a/ircd/engine_kqueue.c b/ircd/engine_kqueue.c index 577cac0..b3f535f 100644 --- a/ircd/engine_kqueue.c +++ b/ircd/engine_kqueue.c @@ -49,6 +49,12 @@ static struct Socket** sockList; static int kqueue_max; /** File descriptor for kqueue pseudo-file. */ static int kqueue_id; +/** Current array of event descriptors. */ +static struct kevent *events; +/** Number of ::events elements that have been populated. */ +static int events_used; +/** Current processing position in ::events. */ +static int events_i; /** Number of recent errors from kqueue. */ static int errors = 0; @@ -101,7 +107,7 @@ engine_signal(struct Signal* sig) struct kevent sigevent; struct sigaction act; - assert(0 != signal); + assert(0 != sig); Debug((DEBUG_ENGINE, "kqueue: Adding filter for signal %d [%p]", sig_signal(sig), sig)); @@ -276,7 +282,7 @@ engine_events(struct Socket* sock, unsigned int new_events) static void engine_delete(struct Socket* sock) { - struct kevent dellist[2]; + int ii; assert(0 != sock); assert(sock == sockList[s_fd(sock)]); @@ -284,21 +290,14 @@ engine_delete(struct Socket* sock) Debug((DEBUG_ENGINE, "kqueue: Deleting socket %d [%p], state %s", s_fd(sock), sock, state_to_name(s_state(sock)))); - dellist[0].ident = s_fd(sock); /* set up the delete list */ - dellist[0].filter = EVFILT_READ; /* readable filter */ - dellist[0].flags = EV_DELETE; /* delete it */ - dellist[0].fflags = 0; - dellist[0].data = 0; - dellist[0].udata = 0; - - dellist[1].ident = s_fd(sock); - dellist[1].filter = EVFILT_WRITE; /* writable filter */ - dellist[1].flags = EV_DELETE; /* delete it */ - dellist[1].fflags = 0; - dellist[1].data = 0; - dellist[1].udata = 0; - sockList[s_fd(sock)] = 0; + + /* Drop any unprocessed events citing this socket. */ + for (ii = events_i; ii < events_used; ii++) { + if (events[ii].ident == s_fd(sock)) { + events[ii] = events[--events_used]; + } + } } /** Run engine event loop. @@ -307,14 +306,13 @@ engine_delete(struct Socket* sock) static void engine_loop(struct Generators* gen) { - struct kevent *events; int events_count; + struct kevent *evt; struct Socket* sock; struct timespec wait; - int nevs; int i; int errcode; - size_t codesize; + socklen_t codesize; if ((events_count = feature_int(FEAT_POLLS_PER_LOOP)) < 20) events_count = 20; @@ -330,16 +328,16 @@ engine_loop(struct Generators* gen) wait.tv_sec = timer_next(gen) ? (timer_next(gen) - CurrentTime) : -1; wait.tv_nsec = 0; - Debug((DEBUG_INFO, "kqueue: delay: %Tu (%Tu) %Tu", timer_next(gen), + Debug((DEBUG_ENGINE, "kqueue: delay: %Tu (%Tu) %Tu", timer_next(gen), CurrentTime, wait.tv_sec)); /* check for active events */ - nevs = kevent(kqueue_id, 0, 0, events, events_count, - wait.tv_sec < 0 ? 0 : &wait); + events_used = kevent(kqueue_id, 0, 0, events, events_count, + wait.tv_sec < 0 ? 0 : &wait); CurrentTime = time(0); /* set current time... */ - if (nevs < 0) { + if (events_used < 0) { if (errno != EINTR) { /* ignore kevent interrupts */ /* Log the kqueue error */ log_write(LS_SOCKET, L_ERROR, 0, "kevent() error: %m"); @@ -355,21 +353,22 @@ engine_loop(struct Generators* gen) continue; } - for (i = 0; i < nevs; i++) { - if (events[i].filter == EVFILT_SIGNAL) { + for (events_i = 0; events_i < events_used; events_i++) { + evt = &events[events_i]; + + if (evt->filter == EVFILT_SIGNAL) { /* it's a signal; deal appropriately */ - event_generate(ET_SIGNAL, events[i].udata, events[i].ident); + event_generate(ET_SIGNAL, evt->udata, evt->ident); continue; /* skip socket processing loop */ } - assert(events[i].filter == EVFILT_READ || - events[i].filter == EVFILT_WRITE); + assert(evt->filter == EVFILT_READ || evt->filter == EVFILT_WRITE); - sock = sockList[events[i].ident]; + sock = sockList[evt->ident]; if (!sock) /* slots may become empty while processing events */ continue; - assert(s_fd(sock) == events[i].ident); + assert(s_fd(sock) == evt->ident); gen_ref_inc(sock); /* can't have it going away on us */ @@ -395,14 +394,14 @@ engine_loop(struct Generators* gen) switch (s_state(sock)) { case SS_CONNECTING: - if (events[i].filter == EVFILT_WRITE) { /* connection completed */ + if (evt->filter == EVFILT_WRITE) { /* connection completed */ Debug((DEBUG_ENGINE, "kqueue: Connection completed")); event_generate(ET_CONNECT, sock, 0); } break; case SS_LISTENING: - if (events[i].filter == EVFILT_READ) { /* connect. to be accept. */ + if (evt->filter == EVFILT_READ) { /* connect. to be accept. */ Debug((DEBUG_ENGINE, "kqueue: Ready for accept")); event_generate(ET_ACCEPT, sock, 0); } @@ -410,22 +409,22 @@ engine_loop(struct Generators* gen) case SS_NOTSOCK: /* doing nothing socket-specific */ case SS_CONNECTED: - if (events[i].filter == EVFILT_READ) { /* data on socket */ + if (evt->filter == EVFILT_READ) { /* data on socket */ Debug((DEBUG_ENGINE, "kqueue: EOF or data to be read")); - event_generate(events[i].flags & EV_EOF ? ET_EOF : ET_READ, sock, 0); + event_generate(evt->flags & EV_EOF ? ET_EOF : ET_READ, sock, 0); } - if (events[i].filter == EVFILT_WRITE) { /* socket writable */ + if (evt->filter == EVFILT_WRITE) { /* socket writable */ Debug((DEBUG_ENGINE, "kqueue: Data can be written")); event_generate(ET_WRITE, sock, 0); } break; case SS_DATAGRAM: case SS_CONNECTDG: - if (events[i].filter == EVFILT_READ) { /* socket readable */ + if (evt->filter == EVFILT_READ) { /* socket readable */ Debug((DEBUG_ENGINE, "kqueue: Datagram to be read")); event_generate(ET_READ, sock, 0); } - if (events[i].filter == EVFILT_WRITE) { /* socket writable */ + if (evt->filter == EVFILT_WRITE) { /* socket writable */ Debug((DEBUG_ENGINE, "kqueue: Datagram can be written")); event_generate(ET_WRITE, sock, 0); }