/*****************************************************************************/
+/* file descriptor info structure */
typedef struct
{
WL head;
- unsigned char events;
- unsigned char reify;
- unsigned char emask; /* the epoll backend stores the actual kernel mask in here */
+ unsigned char events; /* the events watched for */
+ unsigned char reify; /* flag set when this ANFD needs reification */
+ unsigned char emask; /* the epoll backend stores the actual kernel mask in here */
unsigned char unused;
#if EV_USE_EPOLL
- unsigned int egen; /* generation counter to counter epoll bugs */
+ unsigned int egen; /* generation counter to counter epoll bugs */
#endif
#if EV_SELECT_IS_WINSOCKET
SOCKET handle;
#endif
} ANFD;
+/* stores the pending event set for a given watcher */
typedef struct
{
W w;
- int events;
+ int events; /* the pending event set for the given watcher */
} ANPENDING;
#if EV_USE_INOTIFY
/* Heap Entry */
#if EV_HEAP_CACHE_AT
+ /* a heap element */
typedef struct {
ev_tstamp at;
WT w;
#define ANHE_at(he) (he).at /* access cached at, read-only */
#define ANHE_at_cache(he) (he).at = (he).w->at /* update at from watcher */
#else
+ /* a heap element */
typedef WT ANHE;
#define ANHE_w(he) (he)
#define MALLOC_ROUND 4096 /* prefer to allocate in chunks of this size, must be 2**n and >> 4 longs */
+/* find a suitable new size for the given array, */
+/* hopefully by rounding to a ncie-to-malloc size */
inline_size int
array_nextsize (int elem, int cur, int cnt)
{
/*****************************************************************************/
+/* dummy callback for pending events */
+static void noinline
+pendingcb (EV_P_ ev_prepare *w, int revents)
+{
+}
+
void noinline
ev_feed_event (EV_P_ void *w, int revents)
{
fd_event (EV_A_ fd, revents);
}
+/* make sure the external fd watch events are in-sync */
+/* with the kernel/libev internal state */
inline_size void
fd_reify (EV_P)
{
fdchangecnt = 0;
}
+/* something about the given fd changed */
inline_size void
fd_change (EV_P_ int fd, int flags)
{
}
}
+/* the given fd is invalid/unusable, so make sure it doesn't hurt us anymore */
inline_speed void
fd_kill (EV_P_ int fd)
{
}
}
+/* check whether the given fd is atcually valid, for error recovery */
inline_size int
fd_valid (int fd)
{
ev_active (ANHE_w (he)) = k;
}
+/* move an element suitably so it is in a correct place */
inline_size void
adjustheap (ANHE *heap, int N, int k)
{
/*****************************************************************************/
+/* associate signal watchers to a signal signal */
typedef struct
{
WL head;
/*****************************************************************************/
+/* used to prepare libev internal fd's */
+/* this is not fork-safe */
inline_speed void
fd_intern (int fd)
{
static void noinline
evpipe_init (EV_P)
{
- if (!ev_is_active (&pipeev))
+ if (!ev_is_active (&pipe_w))
{
#if EV_USE_EVENTFD
if ((evfd = eventfd (0, 0)) >= 0)
{
evpipe [0] = -1;
fd_intern (evfd);
- ev_io_set (&pipeev, evfd, EV_READ);
+ ev_io_set (&pipe_w, evfd, EV_READ);
}
else
#endif
fd_intern (evpipe [0]);
fd_intern (evpipe [1]);
- ev_io_set (&pipeev, evpipe [0], EV_READ);
+ ev_io_set (&pipe_w, evpipe [0], EV_READ);
}
- ev_io_start (EV_A_ &pipeev);
+ ev_io_start (EV_A_ &pipe_w);
ev_unref (EV_A); /* watcher should not keep loop alive */
}
}
}
}
+/* called whenever the libev signal pipe */
+/* got some events (signal, async) */
static void
pipecb (EV_P_ ev_io *iow, int revents)
{
# define WIFCONTINUED(status) 0
#endif
+/* handle a single child status event */
inline_speed void
child_reap (EV_P_ int chain, int pid, int status)
{
# define WCONTINUED 0
#endif
+/* called on sigchld etc., calls waitpid */
static void
childcb (EV_P_ ev_signal *sw, int revents)
{
timeout_blocktime = interval;
}
+/* initialise a loop structure, must be zero-initialised */
static void noinline
loop_init (EV_P_ unsigned int flags)
{
if (!backend && (flags & EVBACKEND_SELECT)) backend = select_init (EV_A_ flags);
#endif
- ev_init (&pipeev, pipecb);
- ev_set_priority (&pipeev, EV_MAXPRI);
+ ev_prepare_init (&pending_w, pendingcb);
+
+ ev_init (&pipe_w, pipecb);
+ ev_set_priority (&pipe_w, EV_MAXPRI);
}
}
+/* free up a loop structure */
static void noinline
loop_destroy (EV_P)
{
int i;
- if (ev_is_active (&pipeev))
+ if (ev_is_active (&pipe_w))
{
ev_ref (EV_A); /* signal watcher */
- ev_io_stop (EV_A_ &pipeev);
+ ev_io_stop (EV_A_ &pipe_w);
#if EV_USE_EVENTFD
if (evfd >= 0)
infy_fork (EV_A);
#endif
- if (ev_is_active (&pipeev))
+ if (ev_is_active (&pipe_w))
{
/* this "locks" the handlers against writing to the pipe */
/* while we modify the fd vars */
#endif
ev_ref (EV_A);
- ev_io_stop (EV_A_ &pipeev);
+ ev_io_stop (EV_A_ &pipe_w);
#if EV_USE_EVENTFD
if (evfd >= 0)
evpipe_init (EV_A);
/* now iterate over everything, in case we missed something */
- pipecb (EV_A_ &pipeev, EV_READ);
+ pipecb (EV_A_ &pipe_w, EV_READ);
}
postfork = 0;
{
ANPENDING *p = pendings [pri] + --pendingcnt [pri];
- if (expect_true (p->w))
- {
- /*assert (("libev: non-pending watcher on pending list", p->w->pending));*/
+ /*assert (("libev: non-pending watcher on pending list", p->w->pending));*/
+ /* ^ this is no longer true, as pending_w could be here */
- p->w->pending = 0;
- EV_CB_INVOKE (p->w, p->events);
- EV_FREQUENT_CHECK;
- }
+ p->w->pending = 0;
+ EV_CB_INVOKE (p->w, p->events);
+ EV_FREQUENT_CHECK;
}
}
#if EV_IDLE_ENABLE
+/* make idle watchers pending. this handles the "call-idle */
+/* only when higher priorities are idle" logic */
inline_size void
idle_reify (EV_P)
{
}
#endif
+/* make timers pending */
inline_size void
timers_reify (EV_P)
{
}
#if EV_PERIODIC_ENABLE
+/* make periodics pending */
inline_size void
periodics_reify (EV_P)
{
}
}
+/* simply recalculate all periodics */
+/* TODO: maybe ensure that at leats one event happens when jumping forward? */
static void noinline
periodics_reschedule (EV_P)
{
}
#endif
+/* adjust all timers by a given offset */
static void noinline
timers_reschedule (EV_P_ ev_tstamp adjust)
{
}
}
+/* fetch new monotonic and realtime times from the kernel */
+/* also detetc if there was a timejump, and act accordingly */
inline_speed void
time_update (EV_P_ ev_tstamp max_block)
{
ev_now_update (EV_A);
timers_reschedule (EV_A_ mn_now - mn_prev);
#if EV_PERIODIC_ENABLE
+ /* TODO: really do this? */
periodics_reschedule (EV_A);
#endif
}
/*****************************************************************************/
+/* singly-linked list management, used when the expected list length is short */
inline_size void
wlist_add (WL *head, WL elem)
}
}
+/* internal, faster, version of ev_clear_pending */
inline_speed void
clear_pending (EV_P_ W w)
{
if (w->pending)
{
- pendings [ABSPRI (w)][w->pending - 1].w = 0;
+ pendings [ABSPRI (w)][w->pending - 1].w = (W)&pending_w;
w->pending = 0;
}
}
if (expect_true (pending))
{
ANPENDING *p = pendings [ABSPRI (w_)] + pending - 1;
+ p->w = (W)&pending_w;
w_->pending = 0;
- p->w = 0;
return p->events;
}
else
/*****************************************************************************/
-#if 0
+#if EV_WALK_ENABLE
void
ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w))
{
;
else
#endif
- if ((ev_io *)wl != &pipeev)
+ if ((ev_io *)wl != &pipe_w)
if (types & EV_IO)
cb (EV_A_ EV_IO, wl);
#define backend_fudge ((loop)->backend_fudge)
#define backend_modify ((loop)->backend_modify)
#define backend_poll ((loop)->backend_poll)
+#define anfds ((loop)->anfds)
+#define anfdmax ((loop)->anfdmax)
+#define pendings ((loop)->pendings)
+#define pendingmax ((loop)->pendingmax)
+#define pendingcnt ((loop)->pendingcnt)
+#define pending_w ((loop)->pending_w)
+#define rfeeds ((loop)->rfeeds)
+#define rfeedmax ((loop)->rfeedmax)
+#define rfeedcnt ((loop)->rfeedcnt)
#define evfd ((loop)->evfd)
#define evpipe ((loop)->evpipe)
-#define pipeev ((loop)->pipeev)
+#define pipe_w ((loop)->pipe_w)
#define curpid ((loop)->curpid)
#define postfork ((loop)->postfork)
#define vec_ri ((loop)->vec_ri)
#define kqueue_eventmax ((loop)->kqueue_eventmax)
#define port_events ((loop)->port_events)
#define port_eventmax ((loop)->port_eventmax)
-#define anfds ((loop)->anfds)
-#define anfdmax ((loop)->anfdmax)
-#define pendings ((loop)->pendings)
-#define pendingmax ((loop)->pendingmax)
-#define pendingcnt ((loop)->pendingcnt)
-#define rfeeds ((loop)->rfeeds)
-#define rfeedmax ((loop)->rfeedmax)
-#define rfeedcnt ((loop)->rfeedcnt)
#define fdchanges ((loop)->fdchanges)
#define fdchangemax ((loop)->fdchangemax)
#define fdchangecnt ((loop)->fdchangecnt)
#undef backend_fudge
#undef backend_modify
#undef backend_poll
+#undef anfds
+#undef anfdmax
+#undef pendings
+#undef pendingmax
+#undef pendingcnt
+#undef pending_w
+#undef rfeeds
+#undef rfeedmax
+#undef rfeedcnt
#undef evfd
#undef evpipe
-#undef pipeev
+#undef pipe_w
#undef curpid
#undef postfork
#undef vec_ri
#undef kqueue_eventmax
#undef port_events
#undef port_eventmax
-#undef anfds
-#undef anfdmax
-#undef pendings
-#undef pendingmax
-#undef pendingcnt
-#undef rfeeds
-#undef rfeedmax
-#undef rfeedcnt
#undef fdchanges
#undef fdchangemax
#undef fdchangecnt