]> jfr.im git - irc/rqf/shadowircd.git/blobdiff - libratbox/src/kqueue.c
Update FAQ.
[irc/rqf/shadowircd.git] / libratbox / src / kqueue.c
index faeacd3d532411a8b60cb5d611df3bd842e5d548..08f3666f856c5ab3b7feb4d60df368e551a77db0 100644 (file)
@@ -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 <libratbox_config.h>
@@ -34,8 +34,6 @@
 
 #include <sys/event.h>
 
-#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;
@@ -97,28 +96,35 @@ kq_update_events(rb_fde_t * F, short filter, PF * handler)
 
                if(handler != NULL)
                {
-                       if(filter == EVFILT_WRITE)
-                               kep_flags = (EV_ADD | EV_ONESHOT);
-                       else
-                               kep_flags = EV_ADD;
+                       kep_flags = EV_ADD | EV_ONESHOT;
                }
                else
                {
                        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;
                }
@@ -147,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;
@@ -161,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));
 
@@ -198,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)
@@ -236,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;
@@ -261,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;
@@ -270,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:
@@ -280,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)
@@ -298,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;
@@ -319,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;
 }
 
@@ -329,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);
 }
 
@@ -338,6 +348,7 @@ rb_kqueue_init_event(void)
 {
        return;
 }
+#endif /* KQUEUE_SCHED_EVENT */
 
 #else /* kqueue not supported */
 int
@@ -348,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;
@@ -362,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;