Author: Ghostwolf <foxxe@wtfs.net>
[ircu2.10.12-pk.git] / ircd / engine_kqueue.c
index aafbb59b692822a4463495a0213d4028e1c4c689..892c595daa231df0625106febf548bbedc030553 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "ircd.h"
 #include "ircd_alloc.h"
+#include "ircd_features.h"
 #include "ircd_log.h"
 #include "s_debug.h"
 
@@ -40,8 +41,6 @@
 #define KQUEUE_ERROR_THRESHOLD 20      /* after 20 kqueue errors, restart */
 #define ERROR_EXPIRE_TIME      3600    /* expire errors after an hour */
 
-#define POLLS_PER_KQUEUE       20      /* get 20 kevents per turn */
-
 static struct Socket** sockList;
 static int kqueue_max;
 static int kqueue_id;
@@ -177,7 +176,7 @@ set_or_clear(struct Socket* sock, unsigned int clear, unsigned int set)
     i++; /* advance count... */
   }
 
-  if (kevent(kqueue_id, chglist, i, 0, 0, 0) < 0)
+  if (kevent(kqueue_id, chglist, i, 0, 0, 0) < 0 && errno != EBADF)
     event_generate(ET_ERROR, sock, errno); /* report error */
 }
 
@@ -278,7 +277,8 @@ engine_delete(struct Socket* sock)
 static void
 engine_loop(struct Generators* gen)
 {
-  struct kevent events[POLLS_PER_KQUEUE];
+  struct kevent *events;
+  int events_count;
   struct Socket* sock;
   struct timespec wait;
   int nevs;
@@ -286,7 +286,16 @@ engine_loop(struct Generators* gen)
   int errcode;
   size_t codesize;
 
+  if ((events_count = feature_int(FEAT_POLLS_PER_LOOP)) < 20)
+    events_count = 20;
+  events = (struct kevent *)MyMalloc(sizeof(struct kevent) * events_count);
+
   while (running) {
+    if ((i = feature_int(FEAT_POLLS_PER_LOOP)) >= 20 && i != events_count) {
+      events = (struct kevent *)MyRealloc(events, sizeof(struct kevent) * i);
+      events_count = i;
+    }
+
     /* set up the sleep time */
     wait.tv_sec = timer_next(gen) ? (timer_next(gen) - CurrentTime) : -1;
     wait.tv_nsec = 0;
@@ -295,7 +304,7 @@ engine_loop(struct Generators* gen)
           CurrentTime, wait.tv_sec));
 
     /* check for active events */
-    nevs = kevent(kqueue_id, 0, 0, events, POLLS_PER_KQUEUE,
+    nevs = kevent(kqueue_id, 0, 0, events, events_count,
                  wait.tv_sec < 0 ? 0 : &wait);
 
     CurrentTime = time(0); /* set current time... */
@@ -305,7 +314,7 @@ engine_loop(struct Generators* gen)
        /* Log the kqueue error */
        log_write(LS_SOCKET, L_ERROR, 0, "kevent() error: %m");
        if (!errors++)
-         timer_add(&clear_error, error_clear, 0, TT_PERIODIC,
+         timer_add(timer_init(&clear_error), error_clear, 0, TT_PERIODIC,
                    ERROR_EXPIRE_TIME);
        else if (errors > KQUEUE_ERROR_THRESHOLD) /* too many errors... */
          server_restart("too many kevent errors");