X-Git-Url: https://git.llucax.com/software/libev.git/blobdiff_plain/b57eb07483ea889f20500834cba164374cdec35b..6800c1e86d28e4bc573747e6d327c770b2e00df4:/ev.c diff --git a/ev.c b/ev.c index e5992c3..8911cb8 100644 --- 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); }