+
+ head = &(*head)->next;
+ }
+}
+
+void inline_speed
+clear_pending (EV_P_ W w)
+{
+ if (w->pending)
+ {
+ pendings [ABSPRI (w)][w->pending - 1].w = 0;
+ w->pending = 0;
+ }
+}
+
+int
+ev_clear_pending (EV_P_ void *w)
+{
+ W w_ = (W)w;
+ int pending = w_->pending;
+
+ if (expect_true (pending))
+ {
+ ANPENDING *p = pendings [ABSPRI (w_)] + pending - 1;
+ w_->pending = 0;
+ p->w = 0;
+ return p->events;
+ }
+ else
+ return 0;
+}
+
+void inline_size
+pri_adjust (EV_P_ W w)
+{
+ int pri = w->priority;
+ pri = pri < EV_MINPRI ? EV_MINPRI : pri;
+ pri = pri > EV_MAXPRI ? EV_MAXPRI : pri;
+ w->priority = pri;
+}
+
+void inline_speed
+ev_start (EV_P_ W w, int active)
+{
+ pri_adjust (EV_A_ w);
+ w->active = active;
+ ev_ref (EV_A);
+}
+
+void inline_size
+ev_stop (EV_P_ W w)
+{
+ ev_unref (EV_A);
+ w->active = 0;
+}
+
+/*****************************************************************************/
+
+void noinline
+ev_io_start (EV_P_ ev_io *w)
+{
+ int fd = w->fd;
+
+ if (expect_false (ev_is_active (w)))
+ return;
+
+ assert (("ev_io_start called with negative fd", fd >= 0));
+
+ ev_start (EV_A_ (W)w, 1);
+ array_needsize (ANFD, anfds, anfdmax, fd + 1, anfds_init);
+ wlist_add (&anfds[fd].head, (WL)w);
+
+ fd_change (EV_A_ fd, w->events & EV_IOFDSET | 1);
+ w->events &= ~EV_IOFDSET;
+}
+
+void noinline
+ev_io_stop (EV_P_ ev_io *w)
+{
+ clear_pending (EV_A_ (W)w);
+ if (expect_false (!ev_is_active (w)))
+ return;
+
+ assert (("ev_io_start called with illegal fd (must stay constant after start!)", w->fd >= 0 && w->fd < anfdmax));
+
+ wlist_del (&anfds[w->fd].head, (WL)w);
+ ev_stop (EV_A_ (W)w);
+
+ fd_change (EV_A_ w->fd, 1);
+}
+
+void noinline
+ev_timer_start (EV_P_ ev_timer *w)
+{
+ if (expect_false (ev_is_active (w)))
+ return;
+
+ ((WT)w)->at += mn_now;
+
+ assert (("ev_timer_start called with negative timer repeat value", w->repeat >= 0.));
+
+ ev_start (EV_A_ (W)w, ++timercnt);
+ array_needsize (WT, timers, timermax, timercnt, EMPTY2);
+ timers [timercnt - 1] = (WT)w;
+ upheap (timers, timercnt - 1);
+
+ /*assert (("internal timer heap corruption", timers [((W)w)->active - 1] == w));*/
+}
+
+void noinline
+ev_timer_stop (EV_P_ ev_timer *w)
+{
+ clear_pending (EV_A_ (W)w);
+ if (expect_false (!ev_is_active (w)))
+ return;
+
+ assert (("internal timer heap corruption", timers [((W)w)->active - 1] == (WT)w));
+
+ {
+ int active = ((W)w)->active;
+
+ if (expect_true (--active < --timercnt))
+ {
+ timers [active] = timers [timercnt];
+ adjustheap (timers, timercnt, active);
+ }
+ }
+
+ ((WT)w)->at -= mn_now;
+
+ ev_stop (EV_A_ (W)w);
+}
+
+void noinline
+ev_timer_again (EV_P_ ev_timer *w)
+{
+ if (ev_is_active (w))
+ {
+ if (w->repeat)
+ {
+ ((WT)w)->at = mn_now + w->repeat;
+ adjustheap (timers, timercnt, ((W)w)->active - 1);
+ }
+ else
+ ev_timer_stop (EV_A_ w);
+ }
+ else if (w->repeat)
+ {
+ w->at = w->repeat;
+ ev_timer_start (EV_A_ w);
+ }
+}
+
+#if EV_PERIODIC_ENABLE
+void noinline
+ev_periodic_start (EV_P_ ev_periodic *w)
+{
+ if (expect_false (ev_is_active (w)))
+ return;
+
+ if (w->reschedule_cb)
+ ((WT)w)->at = w->reschedule_cb (w, ev_rt_now);
+ else if (w->interval)
+ {
+ assert (("ev_periodic_start called with negative interval value", w->interval >= 0.));
+ /* this formula differs from the one in periodic_reify because we do not always round up */
+ ((WT)w)->at = w->offset + ceil ((ev_rt_now - w->offset) / w->interval) * w->interval;
+ }
+ else
+ ((WT)w)->at = w->offset;
+
+ ev_start (EV_A_ (W)w, ++periodiccnt);
+ array_needsize (WT, periodics, periodicmax, periodiccnt, EMPTY2);
+ periodics [periodiccnt - 1] = (WT)w;
+ upheap (periodics, periodiccnt - 1);
+
+ /*assert (("internal periodic heap corruption", periodics [((W)w)->active - 1] == w));*/
+}
+
+void noinline
+ev_periodic_stop (EV_P_ ev_periodic *w)
+{
+ clear_pending (EV_A_ (W)w);
+ if (expect_false (!ev_is_active (w)))
+ return;
+
+ assert (("internal periodic heap corruption", periodics [((W)w)->active - 1] == (WT)w));
+
+ {
+ int active = ((W)w)->active;
+
+ if (expect_true (--active < --periodiccnt))
+ {
+ periodics [active] = periodics [periodiccnt];
+ adjustheap (periodics, periodiccnt, active);
+ }
+ }
+
+ ev_stop (EV_A_ (W)w);
+}
+
+void noinline
+ev_periodic_again (EV_P_ ev_periodic *w)
+{
+ /* TODO: use adjustheap and recalculation */
+ ev_periodic_stop (EV_A_ w);
+ ev_periodic_start (EV_A_ w);
+}
+#endif
+
+#ifndef SA_RESTART
+# define SA_RESTART 0
+#endif
+
+void noinline
+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;
+
+ assert (("ev_signal_start called with illegal signal number", w->signum > 0));
+
+ {
+#ifndef _WIN32
+ sigset_t full, prev;
+ sigfillset (&full);
+ sigprocmask (SIG_SETMASK, &full, &prev);
+#endif
+
+ array_needsize (ANSIG, signals, signalmax, w->signum, signals_init);
+
+#ifndef _WIN32
+ sigprocmask (SIG_SETMASK, &prev, 0);
+#endif
+ }
+
+ ev_start (EV_A_ (W)w, 1);
+ wlist_add (&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