]> git.llucax.com Git - software/libev.git/blobdiff - ev.c
*** empty log message ***
[software/libev.git] / ev.c
diff --git a/ev.c b/ev.c
index e5992c339d538a2a0e8d152117edca027640e0bd..8911cb8466145287be2f6b82f6537ae5bdb36257 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
@@ -200,7 +207,7 @@ extern "C" {
 #else
 # define expect(expr,value)         (expr)
 # define inline_speed               static
-# define inline_minimal             static
+# define inline_size                static
 # define noinline
 #endif
 
@@ -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
@@ -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))
         {
@@ -1560,73 +1578,158 @@ ev_periodic_again (EV_P_ ev_periodic *w)
 }
 #endif
 
+#ifndef SA_RESTART
+# define SA_RESTART 0
+#endif
+
 void
-ev_idle_start (EV_P_ ev_idle *w)
+ev_signal_start (EV_P_ ev_signal *w)
 {
+#if EV_MULTIPLICITY
+  assert (("signal watchers are only supported in the default loop", loop == ev_default_loop_ptr));
+#endif
   if (expect_false (ev_is_active (w)))
     return;
 
-  ev_start (EV_A_ (W)w, ++idlecnt);
-  array_needsize (ev_idle *, idles, idlemax, idlecnt, EMPTY2);
-  idles [idlecnt - 1] = w;
+  assert (("ev_signal_start called with illegal signal number", w->signum > 0));
+
+  ev_start (EV_A_ (W)w, 1);
+  array_needsize (ANSIG, signals, signalmax, w->signum, signals_init);
+  wlist_add ((WL *)&signals [w->signum - 1].head, (WL)w);
+
+  if (!((WL)w)->next)
+    {
+#if _WIN32
+      signal (w->signum, sighandler);
+#else
+      struct sigaction sa;
+      sa.sa_handler = sighandler;
+      sigfillset (&sa.sa_mask);
+      sa.sa_flags = SA_RESTART; /* if restarting works we save one iteration */
+      sigaction (w->signum, &sa, 0);
+#endif
+    }
 }
 
 void
-ev_idle_stop (EV_P_ ev_idle *w)
+ev_signal_stop (EV_P_ ev_signal *w)
 {
   ev_clear_pending (EV_A_ (W)w);
   if (expect_false (!ev_is_active (w)))
     return;
 
-  {
-    int active = ((W)w)->active;
-    idles [active - 1] = idles [--idlecnt];
-    ((W)idles [active - 1])->active = active;
-  }
+  wlist_del ((WL *)&signals [w->signum - 1].head, (WL)w);
+  ev_stop (EV_A_ (W)w);
+
+  if (!signals [w->signum - 1].head)
+    signal (w->signum, SIG_DFL);
+}
+
+void
+ev_child_start (EV_P_ ev_child *w)
+{
+#if EV_MULTIPLICITY
+  assert (("child watchers are only supported in the default loop", loop == ev_default_loop_ptr));
+#endif
+  if (expect_false (ev_is_active (w)))
+    return;
 
+  ev_start (EV_A_ (W)w, 1);
+  wlist_add ((WL *)&childs [w->pid & (EV_PID_HASHSIZE - 1)], (WL)w);
+}
+
+void
+ev_child_stop (EV_P_ ev_child *w)
+{
+  ev_clear_pending (EV_A_ (W)w);
+  if (expect_false (!ev_is_active (w)))
+    return;
+
+  wlist_del ((WL *)&childs [w->pid & (EV_PID_HASHSIZE - 1)], (WL)w);
   ev_stop (EV_A_ (W)w);
 }
 
+#if EV_STAT_ENABLE
+
+# ifdef _WIN32
+#  undef lstat
+#  define lstat(a,b) _stati64 (a,b)
+# endif
+
+#define DEF_STAT_INTERVAL 5.0074891
+#define MIN_STAT_INTERVAL 0.1074891
+
 void
-ev_prepare_start (EV_P_ ev_prepare *w)
+ev_stat_stat (EV_P_ ev_stat *w)
+{
+  if (lstat (w->path, &w->attr) < 0)
+    w->attr.st_nlink = 0;
+  else if (!w->attr.st_nlink)
+    w->attr.st_nlink = 1;
+}
+
+static void
+stat_timer_cb (EV_P_ ev_timer *w_, int revents)
+{
+  ev_stat *w = (ev_stat *)(((char *)w_) - offsetof (ev_stat, timer));
+
+  /* we copy this here each the time so that */
+  /* prev has the old value when the callback gets invoked */
+  w->prev = w->attr;
+  ev_stat_stat (EV_A_ w);
+
+  if (memcmp (&w->prev, &w->attr, sizeof (ev_statdata)))
+    ev_feed_event (EV_A_ w, EV_STAT);
+}
+
+void
+ev_stat_start (EV_P_ ev_stat *w)
 {
   if (expect_false (ev_is_active (w)))
     return;
 
-  ev_start (EV_A_ (W)w, ++preparecnt);
-  array_needsize (ev_prepare *, prepares, preparemax, preparecnt, EMPTY2);
-  prepares [preparecnt - 1] = w;
+  /* since we use memcmp, we need to clear any padding data etc. */
+  memset (&w->prev, 0, sizeof (ev_statdata));
+  memset (&w->attr, 0, sizeof (ev_statdata));
+
+  ev_stat_stat (EV_A_ w);
+
+  if (w->interval < MIN_STAT_INTERVAL)
+    w->interval = w->interval ? MIN_STAT_INTERVAL : DEF_STAT_INTERVAL;
+
+  ev_timer_init (&w->timer, stat_timer_cb, w->interval, w->interval);
+  ev_set_priority (&w->timer, ev_priority (w));
+  ev_timer_start (EV_A_ &w->timer);
+
+  ev_start (EV_A_ (W)w, 1);
 }
 
 void
-ev_prepare_stop (EV_P_ ev_prepare *w)
+ev_stat_stop (EV_P_ ev_stat *w)
 {
   ev_clear_pending (EV_A_ (W)w);
   if (expect_false (!ev_is_active (w)))
     return;
 
-  {
-    int active = ((W)w)->active;
-    prepares [active - 1] = prepares [--preparecnt];
-    ((W)prepares [active - 1])->active = active;
-  }
+  ev_timer_stop (EV_A_ &w->timer);
 
   ev_stop (EV_A_ (W)w);
 }
+#endif
 
 void
-ev_check_start (EV_P_ ev_check *w)
+ev_idle_start (EV_P_ ev_idle *w)
 {
   if (expect_false (ev_is_active (w)))
     return;
 
-  ev_start (EV_A_ (W)w, ++checkcnt);
-  array_needsize (ev_check *, checks, checkmax, checkcnt, EMPTY2);
-  checks [checkcnt - 1] = w;
+  ev_start (EV_A_ (W)w, ++idlecnt);
+  array_needsize (ev_idle *, idles, idlemax, idlecnt, EMPTY2);
+  idles [idlecnt - 1] = w;
 }
 
 void
-ev_check_stop (EV_P_ ev_check *w)
+ev_idle_stop (EV_P_ ev_idle *w)
 {
   ev_clear_pending (EV_A_ (W)w);
   if (expect_false (!ev_is_active (w)))
@@ -1634,81 +1737,64 @@ ev_check_stop (EV_P_ ev_check *w)
 
   {
     int active = ((W)w)->active;
-    checks [active - 1] = checks [--checkcnt];
-    ((W)checks [active - 1])->active = active;
+    idles [active - 1] = idles [--idlecnt];
+    ((W)idles [active - 1])->active = active;
   }
 
   ev_stop (EV_A_ (W)w);
 }
 
-#ifndef SA_RESTART
-# define SA_RESTART 0
-#endif
-
 void
-ev_signal_start (EV_P_ ev_signal *w)
+ev_prepare_start (EV_P_ ev_prepare *w)
 {
-#if EV_MULTIPLICITY
-  assert (("signal watchers are only supported in the default loop", loop == ev_default_loop_ptr));
-#endif
   if (expect_false (ev_is_active (w)))
     return;
 
-  assert (("ev_signal_start called with illegal signal number", w->signum > 0));
-
-  ev_start (EV_A_ (W)w, 1);
-  array_needsize (ANSIG, signals, signalmax, w->signum, signals_init);
-  wlist_add ((WL *)&signals [w->signum - 1].head, (WL)w);
-
-  if (!((WL)w)->next)
-    {
-#if _WIN32
-      signal (w->signum, sighandler);
-#else
-      struct sigaction sa;
-      sa.sa_handler = sighandler;
-      sigfillset (&sa.sa_mask);
-      sa.sa_flags = SA_RESTART; /* if restarting works we save one iteration */
-      sigaction (w->signum, &sa, 0);
-#endif
-    }
+  ev_start (EV_A_ (W)w, ++preparecnt);
+  array_needsize (ev_prepare *, prepares, preparemax, preparecnt, EMPTY2);
+  prepares [preparecnt - 1] = w;
 }
 
 void
-ev_signal_stop (EV_P_ ev_signal *w)
+ev_prepare_stop (EV_P_ ev_prepare *w)
 {
   ev_clear_pending (EV_A_ (W)w);
   if (expect_false (!ev_is_active (w)))
     return;
 
-  wlist_del ((WL *)&signals [w->signum - 1].head, (WL)w);
-  ev_stop (EV_A_ (W)w);
+  {
+    int active = ((W)w)->active;
+    prepares [active - 1] = prepares [--preparecnt];
+    ((W)prepares [active - 1])->active = active;
+  }
 
-  if (!signals [w->signum - 1].head)
-    signal (w->signum, SIG_DFL);
+  ev_stop (EV_A_ (W)w);
 }
 
 void
-ev_child_start (EV_P_ ev_child *w)
+ev_check_start (EV_P_ ev_check *w)
 {
-#if EV_MULTIPLICITY
-  assert (("child watchers are only supported in the default loop", loop == ev_default_loop_ptr));
-#endif
   if (expect_false (ev_is_active (w)))
     return;
 
-  ev_start (EV_A_ (W)w, 1);
-  wlist_add ((WL *)&childs [w->pid & (PID_HASHSIZE - 1)], (WL)w);
+  ev_start (EV_A_ (W)w, ++checkcnt);
+  array_needsize (ev_check *, checks, checkmax, checkcnt, EMPTY2);
+  checks [checkcnt - 1] = w;
 }
 
 void
-ev_child_stop (EV_P_ ev_child *w)
+ev_check_stop (EV_P_ ev_check *w)
 {
   ev_clear_pending (EV_A_ (W)w);
   if (expect_false (!ev_is_active (w)))
     return;
 
-  wlist_del ((WL *)&childs [w->pid & (PID_HASHSIZE - 1)], (WL)w);
+  {
+    int active = ((W)w)->active;
+    checks [active - 1] = checks [--checkcnt];
+    ((W)checks [active - 1])->active = active;
+  }
+
   ev_stop (EV_A_ (W)w);
 }
 
@@ -1761,62 +1847,30 @@ ev_embed_stop (EV_P_ ev_embed *w)
 }
 #endif
 
-#if EV_STAT_ENABLE
-
-# ifdef _WIN32
-#  define lstat(a,b) stat(a,b)
-# endif
-
+#if EV_FORK_ENABLE
 void
-ev_stat_stat (EV_P_ ev_stat *w)
-{
-  if (lstat (w->path, &w->attr) < 0)
-    w->attr.st_nlink = 0;
-  else if (!w->attr.st_nlink)
-    w->attr.st_nlink = 1;
-}
-
-static void
-stat_timer_cb (EV_P_ ev_timer *w_, int revents)
-{
-  ev_stat *w = (ev_stat *)(((char *)w_) - offsetof (ev_stat, timer));
-
-  /* we copy this here each the time so that */
-  /* prev has the old value when the callback gets invoked */
-  w->prev = w->attr;
-  ev_stat_stat (EV_A_ w);
-
-  if (memcmp (&w->prev, &w->attr, sizeof (ev_statdata)))
-    ev_feed_event (EV_A_ w, EV_STAT);
-}
-
-void
-ev_stat_start (EV_P_ ev_stat *w)
+ev_fork_start (EV_P_ ev_fork *w)
 {
   if (expect_false (ev_is_active (w)))
     return;
 
-  /* since we use memcmp, we need to clear any padding data etc. */
-  memset (&w->prev, 0, sizeof (ev_statdata));
-  memset (&w->attr, 0, sizeof (ev_statdata));
-
-  ev_stat_stat (EV_A_ w);
-
-  ev_timer_init (&w->timer, stat_timer_cb, w->interval, w->interval);
-  ev_set_priority (&w->timer, ev_priority (w));
-  ev_timer_start (EV_A_ &w->timer);
-
-  ev_start (EV_A_ (W)w, 1);
+  ev_start (EV_A_ (W)w, ++forkcnt);
+  array_needsize (ev_fork *, forks, forkmax, forkcnt, EMPTY2);
+  forks [forkcnt - 1] = w;
 }
 
 void
-ev_stat_stop (EV_P_ ev_stat *w)
+ev_fork_stop (EV_P_ ev_fork *w)
 {
   ev_clear_pending (EV_A_ (W)w);
   if (expect_false (!ev_is_active (w)))
     return;
 
-  ev_timer_stop (EV_A_ &w->timer);
+  {
+    int active = ((W)w)->active;
+    forks [active - 1] = forks [--forkcnt];
+    ((W)forks [active - 1])->active = active;
+  }
 
   ev_stop (EV_A_ (W)w);
 }