X-Git-Url: https://jfr.im/git/irc/rqf/shadowircd.git/blobdiff_plain/c50bb62ccd99bec85d252ea46c09b75d5c6b8f80..36fb4e9a7743326d1a2ca7601bc9bf1c5b9a0bcb:/libratbox/src/kqueue.c diff --git a/libratbox/src/kqueue.c b/libratbox/src/kqueue.c index 72763c0..08f3666 100644 --- a/libratbox/src/kqueue.c +++ b/libratbox/src/kqueue.c @@ -22,7 +22,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA * - * $Id: kqueue.c 25038 2008-01-23 16:03:08Z androsyn $ + * $Id: kqueue.c 26092 2008-09-19 15:13:52Z androsyn $ */ #include @@ -34,8 +34,6 @@ #include -#define KE_LENGTH 128 - /* jlemon goofed up and didn't add EV_SET until fbsd 4.3 */ #ifndef EV_SET @@ -59,18 +57,19 @@ static int kq; static struct timespec zero_timespec; static struct kevent *kqlst; /* kevent buffer */ +static struct kevent *kqout; /* kevent output buffer */ static int kqmax; /* max structs to buffer */ static int kqoff; /* offset into the buffer */ int -rb_setup_fd_kqueue(rb_fde_t * F) +rb_setup_fd_kqueue(rb_fde_t *F) { return 0; } static void -kq_update_events(rb_fde_t * F, short filter, PF * handler) +kq_update_events(rb_fde_t *F, short filter, PF * handler) { PF *cur_handler; int kep_flags; @@ -104,18 +103,28 @@ kq_update_events(rb_fde_t * F, short filter, PF * handler) kep_flags = EV_DELETE; } - EV_SET(kep, (uintptr_t) F->fd, filter, kep_flags, 0, 0, (void *) F); + EV_SET(kep, (uintptr_t)F->fd, filter, kep_flags, 0, 0, (void *)F); if(++kqoff == kqmax) { - int ret; - - ret = kevent(kq, kqlst, kqoff, NULL, 0, &zero_timespec); - /* jdc -- someone needs to do error checking... */ - if(ret == -1) + int ret, i; + + /* Add them one at a time, because there may be + * already closed fds in it. The kernel will try + * to report invalid fds in the output; if there + * is no space, it silently stops processing the + * array at that point. We cannot give output space + * because that would also return events we cannot + * process at this point. + */ + for(i = 0; i < kqoff; i++) { - rb_lib_log("kq_update_events(): kevent(): %s", strerror(errno)); - return; + ret = kevent(kq, kqlst + i, 1, NULL, 0, &zero_timespec); + /* jdc -- someone needs to do error checking... */ + /* EBADF is normal here -- jilles */ + if(ret == -1 && errno != EBADF) + rb_lib_log("kq_update_events(): kevent(): %s", + strerror(errno)); } kqoff = 0; } @@ -144,6 +153,7 @@ rb_init_netio_kqueue(void) } kqmax = getdtablesize(); kqlst = rb_malloc(sizeof(struct kevent) * kqmax); + kqout = rb_malloc(sizeof(struct kevent) * kqmax); rb_open(kq, RB_FD_UNKNOWN, "kqueue fd"); zero_timespec.tv_sec = 0; zero_timespec.tv_nsec = 0; @@ -158,7 +168,7 @@ rb_init_netio_kqueue(void) * and deregister interest in a pending IO state for a given FD. */ void -rb_setselect_kqueue(rb_fde_t * F, unsigned int type, PF * handler, void *client_data) +rb_setselect_kqueue(rb_fde_t *F, unsigned int type, PF * handler, void *client_data) { lrb_assert(IsFDOpen(F)); @@ -195,24 +205,25 @@ int rb_select_kqueue(long delay) { int num, i; - static struct kevent ke[KE_LENGTH]; struct timespec poll_time; struct timespec *pt; rb_fde_t *F; - if(delay < 0) { + if(delay < 0) + { pt = NULL; } - else { + else + { pt = &poll_time; poll_time.tv_sec = delay / 1000; poll_time.tv_nsec = (delay % 1000) * 1000000; } - for (;;) + for(;;) { - num = kevent(kq, kqlst, kqoff, ke, KE_LENGTH, pt); + num = kevent(kq, kqlst, kqoff, kqout, kqmax, pt); kqoff = 0; if(num >= 0) @@ -233,22 +244,22 @@ rb_select_kqueue(long delay) if(num == 0) return RB_OK; /* No error.. */ - for (i = 0; i < num; i++) + for(i = 0; i < num; i++) { PF *hdl = NULL; - if(ke[i].flags & EV_ERROR) + if(kqout[i].flags & EV_ERROR) { - errno = ke[i].data; + errno = kqout[i].data; /* XXX error == bad! -- adrian */ continue; /* XXX! */ } - switch (ke[i].filter) + switch (kqout[i].filter) { case EVFILT_READ: - F = ke[i].udata; + F = kqout[i].udata; if((hdl = F->read_handler) != NULL) { F->read_handler = NULL; @@ -258,7 +269,7 @@ rb_select_kqueue(long delay) break; case EVFILT_WRITE: - F = ke[i].udata; + F = kqout[i].udata; if((hdl = F->write_handler) != NULL) { F->write_handler = NULL; @@ -267,7 +278,7 @@ rb_select_kqueue(long delay) break; #if defined(EVFILT_TIMER) case EVFILT_TIMER: - rb_run_event(ke[i].udata); + rb_run_event(kqout[i].udata); break; #endif default: @@ -277,6 +288,8 @@ rb_select_kqueue(long delay) } return RB_OK; } + +#if defined(KQUEUE_SCHED_EVENT) static int can_do_event = 0; int rb_kqueue_supports_event(void) @@ -295,7 +308,7 @@ rb_kqueue_supports_event(void) ts.tv_nsec = 1000; - EV_SET(&kv, (uintptr_t) 0x0, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 1, 0); + EV_SET(&kv, (uintptr_t)0x0, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 1, 0); if(kevent(xkq, &kv, 1, NULL, 0, NULL) < 0) { can_do_event = -1; @@ -316,9 +329,9 @@ rb_kqueue_sched_event(struct ev_entry *event, int when) kep_flags = EV_ADD; if(event->frequency == 0) kep_flags |= EV_ONESHOT; - EV_SET(&kev, (uintptr_t) event, EVFILT_TIMER, kep_flags, 0, when * 1000, event); + EV_SET(&kev, (uintptr_t)event, EVFILT_TIMER, kep_flags, 0, when * 1000, event); if(kevent(kq, &kev, 1, NULL, 0, NULL) < 0) - return 0; + return 0; return 1; } @@ -326,7 +339,7 @@ void rb_kqueue_unsched_event(struct ev_entry *event) { struct kevent kev; - EV_SET(&kev, (uintptr_t) event, EVFILT_TIMER, EV_DELETE, 0, 0, event); + EV_SET(&kev, (uintptr_t)event, EVFILT_TIMER, EV_DELETE, 0, 0, event); kevent(kq, &kev, 1, NULL, 0, NULL); } @@ -335,6 +348,7 @@ rb_kqueue_init_event(void) { return; } +#endif /* KQUEUE_SCHED_EVENT */ #else /* kqueue not supported */ int @@ -345,7 +359,7 @@ rb_init_netio_kqueue(void) } void -rb_setselect_kqueue(rb_fde_t * F, unsigned int type, PF * handler, void *client_data) +rb_setselect_kqueue(rb_fde_t *F, unsigned int type, PF * handler, void *client_data) { errno = ENOSYS; return; @@ -359,7 +373,7 @@ rb_select_kqueue(long delay) } int -rb_setup_fd_kqueue(rb_fde_t * F) +rb_setup_fd_kqueue(rb_fde_t *F) { errno = ENOSYS; return -1;