]> git.llucax.com Git - software/libev.git/blobdiff - ev.c
- argl, same bug as with check etc. watchers in timers and periodics
[software/libev.git] / ev.c
diff --git a/ev.c b/ev.c
index 40e229202319dc8addb2e11810669428005e77d8..06c0ec362f458bff846bd171e7758e1f726b54ed 100644 (file)
--- a/ev.c
+++ b/ev.c
@@ -158,6 +158,14 @@ extern "C" {
 # define EV_USE_PORT 0
 #endif
 
+#ifndef EV_PID_HASHSIZE
+# if EV_MINIMAL
+#  define EV_PID_HASHSIZE 1
+# else
+#  define EV_PID_HASHSIZE 16
+# endif
+#endif
+
 /**/
 
 #ifndef CLOCK_MONOTONIC
@@ -178,7 +186,6 @@ extern "C" {
 
 #define MIN_TIMEJUMP  1. /* minimum timejump that gets detected (if monotonic clock available) */
 #define MAX_BLOCKTIME 59.743 /* never wait longer than this time (to detect time jumps) */
-#define PID_HASHSIZE  16 /* size of pid hash table, must be power of two */
 /*#define CLEANUP_INTERVAL (MAX_BLOCKTIME * 5.) /* how often to try to free memory and re-check fds */
 
 #ifdef EV_H
@@ -248,22 +255,22 @@ syserr (const char *msg)
     }
 }
 
-static void *(*alloc)(void *ptr, long size);
+static void *(*alloc)(void *ptr, size_t size) = realloc;
 
 void
-ev_set_allocator (void *(*cb)(void *ptr, long size))
+ev_set_allocator (void *(*cb)(void *ptr, size_t size))
 {
   alloc = cb;
 }
 
-static void *
-ev_realloc (void *ptr, long size)
+inline_speed void *
+ev_realloc (void *ptr, size_t size)
 {
-  ptr = alloc ? alloc (ptr, size) : realloc (ptr, size);
+  ptr = alloc (ptr, size);
 
   if (!ptr && size)
     {
-      fprintf (stderr, "libev: cannot allocate %ld bytes, aborting.", size);
+      fprintf (stderr, "libev: cannot allocate %ld bytes, aborting.", (long)size);
       abort ();
     }
 
@@ -711,7 +718,7 @@ siginit (EV_P)
 
 /*****************************************************************************/
 
-static ev_child *childs [PID_HASHSIZE];
+static ev_child *childs [EV_PID_HASHSIZE];
 
 #ifndef _WIN32
 
@@ -722,7 +729,7 @@ child_reap (EV_P_ ev_signal *sw, int chain, int pid, int status)
 {
   ev_child *w;
 
-  for (w = (ev_child *)childs [chain & (PID_HASHSIZE - 1)]; w; w = (ev_child *)((WL)w)->next)
+  for (w = (ev_child *)childs [chain & (EV_PID_HASHSIZE - 1)]; w; w = (ev_child *)((WL)w)->next)
     if (w->pid == pid || !w->pid)
       {
         ev_priority (w) = ev_priority (sw); /* need to do it *now* */
@@ -753,7 +760,8 @@ childcb (EV_P_ ev_signal *sw, int revents)
   ev_feed_event (EV_A_ (W)sw, EV_SIGNAL);
 
   child_reap (EV_A_ sw, pid, pid, status);
-  child_reap (EV_A_ sw,   0, pid, status); /* this might trigger a watcher twice, but feed_event catches that */
+  if (EV_PID_HASHSIZE > 1)
+    child_reap (EV_A_ sw, 0, pid, status); /* this might trigger a watcher twice, but feed_event catches that */
 }
 
 #endif
@@ -846,7 +854,7 @@ ev_backend (EV_P)
   return backend;
 }
 
-static void
+static void noinline
 loop_init (EV_P_ unsigned int flags)
 {
   if (!backend)
@@ -894,7 +902,7 @@ loop_init (EV_P_ unsigned int flags)
     }
 }
 
-static void
+static void noinline
 loop_destroy (EV_P)
 {
   int i;
@@ -931,7 +939,7 @@ loop_destroy (EV_P)
   backend = 0;
 }
 
-static void
+void inline_size
 loop_fork (EV_P)
 {
 #if EV_USE_PORT
@@ -1091,7 +1099,7 @@ call_pending (EV_P)
 
         if (expect_true (p->w))
           {
-            assert (("non-pending watcher on pending list", p->w->pending));
+            /*assert (("non-pending watcher on pending list", p->w->pending));*/
 
             p->w->pending = 0;
             EV_CB_INVOKE (p->w, p->events);
@@ -1106,7 +1114,7 @@ timers_reify (EV_P)
     {
       ev_timer *w = timers [0];
 
-      assert (("inactive timer on timer heap detected", ev_is_active (w)));
+      /*assert (("inactive timer on timer heap detected", ev_is_active (w)));*/
 
       /* first reschedule or stop timer */
       if (w->repeat)
@@ -1134,7 +1142,7 @@ periodics_reify (EV_P)
     {
       ev_periodic *w = periodics [0];
 
-      assert (("inactive timer on periodic heap detected", ev_is_active (w)));
+      /*assert (("inactive timer on periodic heap detected", ev_is_active (w)));*/
 
       /* first reschedule or stop timer */
       if (w->reschedule_cb)
@@ -1278,6 +1286,16 @@ ev_loop (EV_P_ int flags)
 
   while (activecnt)
     {
+      /* we might have forked, so reify kernel state if necessary */
+      #if EV_FORK_ENABLE
+        if (expect_false (postfork))
+          if (forkcnt)
+            {
+              queue_events (EV_A_ (W *)forks, forkcnt, EV_FORK);
+              call_pending (EV_A);
+            }
+      #endif
+
       /* queue check watchers (and execute them) */
       if (expect_false (preparecnt))
         {
@@ -1466,7 +1484,7 @@ ev_timer_start (EV_P_ ev_timer *w)
   timers [timercnt - 1] = w;
   upheap ((WT *)timers, timercnt - 1);
 
-  assert (("internal timer heap corruption", timers [((W)w)->active - 1] == w));
+  /*assert (("internal timer heap corruption", timers [((W)w)->active - 1] == w));*/
 }
 
 void
@@ -1478,11 +1496,15 @@ ev_timer_stop (EV_P_ ev_timer *w)
 
   assert (("internal timer heap corruption", timers [((W)w)->active - 1] == w));
 
-  if (expect_true (((W)w)->active < timercnt--))
-    {
-      timers [((W)w)->active - 1] = timers [timercnt];
-      adjustheap ((WT *)timers, timercnt, ((W)w)->active - 1);
-    }
+  {
+    int active = ((W)w)->active;
+
+    if (expect_true (--active < --timercnt))
+      {
+        timers [active] = timers [timercnt];
+        adjustheap ((WT *)timers, timercnt, active);
+      }
+  }
 
   ((WT)w)->at -= mn_now;
 
@@ -1530,7 +1552,7 @@ ev_periodic_start (EV_P_ ev_periodic *w)
   periodics [periodiccnt - 1] = w;
   upheap ((WT *)periodics, periodiccnt - 1);
 
-  assert (("internal periodic heap corruption", periodics [((W)w)->active - 1] == w));
+  /*assert (("internal periodic heap corruption", periodics [((W)w)->active - 1] == w));*/
 }
 
 void
@@ -1542,11 +1564,15 @@ ev_periodic_stop (EV_P_ ev_periodic *w)
 
   assert (("internal periodic heap corruption", periodics [((W)w)->active - 1] == w));
 
-  if (expect_true (((W)w)->active < periodiccnt--))
-    {
-      periodics [((W)w)->active - 1] = periodics [periodiccnt];
-      adjustheap ((WT *)periodics, periodiccnt, ((W)w)->active - 1);
-    }
+  {
+    int active = ((W)w)->active;
+
+    if (expect_true (--active < --periodiccnt))
+      {
+        periodics [active] = periodics [periodiccnt];
+        adjustheap ((WT *)periodics, periodiccnt, active);
+      }
+  }
 
   ev_stop (EV_A_ (W)w);
 }
@@ -1617,7 +1643,7 @@ ev_child_start (EV_P_ ev_child *w)
     return;
 
   ev_start (EV_A_ (W)w, 1);
-  wlist_add ((WL *)&childs [w->pid & (PID_HASHSIZE - 1)], (WL)w);
+  wlist_add ((WL *)&childs [w->pid & (EV_PID_HASHSIZE - 1)], (WL)w);
 }
 
 void
@@ -1627,7 +1653,7 @@ ev_child_stop (EV_P_ ev_child *w)
   if (expect_false (!ev_is_active (w)))
     return;
 
-  wlist_del ((WL *)&childs [w->pid & (PID_HASHSIZE - 1)], (WL)w);
+  wlist_del ((WL *)&childs [w->pid & (EV_PID_HASHSIZE - 1)], (WL)w);
   ev_stop (EV_A_ (W)w);
 }
 
@@ -1829,6 +1855,35 @@ ev_embed_stop (EV_P_ ev_embed *w)
 }
 #endif
 
+#if EV_FORK_ENABLE
+void
+ev_fork_start (EV_P_ ev_fork *w)
+{
+  if (expect_false (ev_is_active (w)))
+    return;
+
+  ev_start (EV_A_ (W)w, ++forkcnt);
+  array_needsize (ev_fork *, forks, forkmax, forkcnt, EMPTY2);
+  forks [forkcnt - 1] = w;
+}
+
+void
+ev_fork_stop (EV_P_ ev_fork *w)
+{
+  ev_clear_pending (EV_A_ (W)w);
+  if (expect_false (!ev_is_active (w)))
+    return;
+
+  {
+    int active = ((W)w)->active;
+    forks [active - 1] = forks [--forkcnt];
+    ((W)forks [active - 1])->active = active;
+  }
+
+  ev_stop (EV_A_ (W)w);
+}
+#endif
+
 /*****************************************************************************/
 
 struct ev_once