From 22b2a449105d7604f715c1afafeb4fe5ac473f1b Mon Sep 17 00:00:00 2001 From: root Date: Sun, 4 Nov 2007 23:14:11 +0000 Subject: [PATCH 01/16] - have to re-check potentially closed fds regularly for epoll. this hurts badly :( - still more than twice as fats as libevent. - many minor fixes --- ev.c | 7 ++----- ev.h | 4 ++-- ev_epoll.c | 4 +++- ev_poll.c | 4 ++++ ev_select.c | 3 +++ evdns.c | 4 ++-- event.c | 2 +- 7 files changed, 17 insertions(+), 11 deletions(-) diff --git a/ev.c b/ev.c index 5756bb7..2db968e 100644 --- a/ev.c +++ b/ev.c @@ -308,11 +308,8 @@ fd_reify (EV_P) anfd->reify = 0; - if (anfd->events != events) - { - method_modify (EV_A_ fd, anfd->events, events); - anfd->events = events; - } + method_modify (EV_A_ fd, anfd->events, events); + anfd->events = events; } fdchangecnt = 0; diff --git a/ev.h b/ev.h index ecca856..1b33bf2 100644 --- a/ev.h +++ b/ev.h @@ -268,7 +268,7 @@ void ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revent ((struct ev_watcher *)(ev))->active = \ ((struct ev_watcher *)(ev))->pending = \ ((struct ev_watcher *)(ev))->priority = 0; \ - ((struct ev_watcher *)(ev))->cb = (cb_); \ + (ev)->cb = (cb_); \ } while (0) #define ev_io_set(ev,fd_,events_) do { (ev)->fd = (fd_); (ev)->events = (events_); } while (0) @@ -293,7 +293,7 @@ void ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revent #define ev_is_active(ev) (0 + ((struct ev_watcher *)(ev))->active) /* ro, true when the watcher has been started */ #define ev_priority(ev) ((struct ev_watcher *)(ev))->priority /* rw */ -#define ev_cb(ev) ((struct ev_watcher *)(ev))->cb /* rw */ +#define ev_cb(ev) (ev)->cb /* rw */ #define ev_set_priority(ev,pri) ev_priority (ev) = (pri) #define ev_set_cb(ev,cb_) ev_cb (ev) = (cb_) diff --git a/ev_epoll.c b/ev_epoll.c index ffb1f05..4689f8d 100644 --- a/ev_epoll.c +++ b/ev_epoll.c @@ -43,7 +43,9 @@ epoll_modify (EV_P_ int fd, int oev, int nev) | (nev & EV_WRITE ? EPOLLOUT : 0); if (epoll_ctl (epoll_fd, mode, fd, &ev)) - fd_kill (EV_A_ fd); + if (errno != ENOENT /* on ENOENT the fd went away, so try to do the right thing */ + || (nev && epoll_ctl (epoll_fd, EPOLL_CTL_ADD, fd, &ev))) + fd_kill (EV_A_ fd); } static void diff --git a/ev_poll.c b/ev_poll.c index b858b45..b58ce82 100644 --- a/ev_poll.c +++ b/ev_poll.c @@ -42,6 +42,10 @@ static void poll_modify (EV_P_ int fd, int oev, int nev) { int idx; + + if (oev == nev) + return; + array_needsize (pollidxs, pollidxmax, fd + 1, pollidx_init); idx = pollidxs [fd]; diff --git a/ev_select.c b/ev_select.c index 327c313..9f81e55 100644 --- a/ev_select.c +++ b/ev_select.c @@ -48,6 +48,9 @@ select_modify (EV_P_ int fd, int oev, int nev) int offs = fd >> 3; int mask = 1 << (fd & 7); + if (oev == nev) + return; + if (vec_max < (fd >> 5) + 1) { int new_max = (fd >> 5) + 1; diff --git a/evdns.c b/evdns.c index e4e4e8f..3fd2a91 100644 --- a/evdns.c +++ b/evdns.c @@ -1,4 +1,4 @@ -/* $Id: evdns.c,v 1.11 2007-11-04 19:45:09 root Exp $ */ +/* $Id: evdns.c,v 1.12 2007-11-04 23:14:11 root Exp $ */ /* The original version of this module was written by Adam Langley; for * a history of modifications, check out the subversion logs. @@ -40,7 +40,7 @@ #endif #ifdef WIN32 -#ifndef EV_EMBED +#ifndef EV_STANDALONE #include "misc.h" #endif #endif diff --git a/event.c b/event.c index b34774c..cf7739c 100644 --- a/event.c +++ b/event.c @@ -91,7 +91,7 @@ void *event_init (void) #else assert (("multiple event bases not supported when not compiled with EV_MULTIPLICITY", !x_cur)); - x_cur = (struct event_base *)ev_default_loop (EVMETHOD_AUTO); + x_cur = (struct event_base *)(long)ev_default_loop (EVMETHOD_AUTO); #endif return x_cur; -- 2.43.0 From aa07e8dd0ad9aa9952a6eeba2ef2b15429c08831 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 4 Nov 2007 23:29:48 +0000 Subject: [PATCH 02/16] *** empty log message *** --- ev.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/ev.c b/ev.c index 2db968e..9ef3d13 100644 --- a/ev.c +++ b/ev.c @@ -234,6 +234,9 @@ ev_now (EV_P) cur = newcnt; \ } +#define array_free(stem, idx) \ + free (stem ## s idx); stem ## cnt idx = stem ## max idx = 0; + /*****************************************************************************/ static void @@ -636,6 +639,8 @@ loop_init (EV_P_ int methods) void loop_destroy (EV_P) { + int i; + #if EV_USE_WIN32 if (method == EVMETHOD_WIN32 ) win32_destroy (EV_A); #endif @@ -652,6 +657,16 @@ loop_destroy (EV_P) if (method == EVMETHOD_SELECT) select_destroy (EV_A); #endif + for (i = NUMPRI; i--; ) + array_free (pending, [i]); + + array_free (fdchange, ); + array_free (timer, ); + array_free (periodic, ); + array_free (idle, ); + array_free (prepare, ); + array_free (check, ); + method = 0; /*TODO*/ } @@ -796,7 +811,7 @@ call_pending (EV_P) { p->w->pending = 0; - (*(void (**)(EV_P_ W, int))&p->w->cb) (EV_A_ p->w, p->events); + ((void (*)(EV_P_ W, int))p->w->cb) (EV_A_ p->w, p->events); } } } -- 2.43.0 From e24bed5d59f88b90093005921b5338267ed65ea2 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 4 Nov 2007 23:29:48 +0000 Subject: [PATCH 03/16] *** empty log message *** --- ev.c | 3 +-- ev.h | 12 ++++++------ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/ev.c b/ev.c index 9ef3d13..255bb84 100644 --- a/ev.c +++ b/ev.c @@ -810,8 +810,7 @@ call_pending (EV_P) if (p->w) { p->w->pending = 0; - - ((void (*)(EV_P_ W, int))p->w->cb) (EV_A_ p->w, p->events); + p->w->cb (EV_A_ p->w, p->events); } } } diff --git a/ev.h b/ev.h index 1b33bf2..b563c3f 100644 --- a/ev.h +++ b/ev.h @@ -265,9 +265,9 @@ void ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revent /* these may evaluate ev multiple times, and the other arguments at most once */ /* either use ev_watcher_init + ev_TYPE_set, or the ev_TYPE_init macro, below, to first initialise a watcher */ #define ev_watcher_init(ev,cb_) do { \ - ((struct ev_watcher *)(ev))->active = \ - ((struct ev_watcher *)(ev))->pending = \ - ((struct ev_watcher *)(ev))->priority = 0; \ + ((struct ev_watcher *)(void *)(ev))->active = \ + ((struct ev_watcher *)(void *)(ev))->pending = \ + ((struct ev_watcher *)(void *)(ev))->priority = 0; \ (ev)->cb = (cb_); \ } while (0) @@ -289,10 +289,10 @@ void ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revent #define ev_check_init(ev,cb) do { ev_watcher_init ((ev), (cb)); ev_check_set ((ev)); } while (0) #define ev_child_init(ev,cb,pid) do { ev_watcher_init ((ev), (cb)); ev_child_set ((ev),(pid)); } while (0) -#define ev_is_pending(ev) (0 + ((struct ev_watcher *)(ev))->pending) /* ro, true when watcher is waiting for callback invocation */ -#define ev_is_active(ev) (0 + ((struct ev_watcher *)(ev))->active) /* ro, true when the watcher has been started */ +#define ev_is_pending(ev) (0 + ((struct ev_watcher *)(void *)(ev))->pending) /* ro, true when watcher is waiting for callback invocation */ +#define ev_is_active(ev) (0 + ((struct ev_watcher *)(void *)(ev))->active) /* ro, true when the watcher has been started */ -#define ev_priority(ev) ((struct ev_watcher *)(ev))->priority /* rw */ +#define ev_priority(ev) ((struct ev_watcher *)(void *)(ev))->priority /* rw */ #define ev_cb(ev) (ev)->cb /* rw */ #define ev_set_priority(ev,pri) ev_priority (ev) = (pri) #define ev_set_cb(ev,cb_) ev_cb (ev) = (cb_) -- 2.43.0 From 0f411518435b7edf24d4bddcc86e5958f7e3d23f Mon Sep 17 00:00:00 2001 From: root Date: Sun, 4 Nov 2007 23:51:02 +0000 Subject: [PATCH 04/16] *** empty log message *** --- ev.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/ev.h b/ev.h index b563c3f..1933285 100644 --- a/ev.h +++ b/ev.h @@ -199,6 +199,20 @@ struct ev_child int rstatus; /* rw, holds the exit status, use the macros from sys/wait.h */ }; +union ev_any_watcher +{ + struct ev_watcher w; + struct ev_watcher_list wl; + struct ev_io io; + struct ev_timer timer; + struct ev_periodic periodic; + struct ev_signal signal; + struct ev_idle idle; + struct ev_child child; + struct ev_prepare prepare; + struct ev_check check; +}; + #define EVMETHOD_AUTO 0 /* consults environment */ #define EVMETHOD_SELECT 1 #define EVMETHOD_POLL 2 -- 2.43.0 From 7adde6c7c7a709d21a4cacdf6a1b3bc9418245df Mon Sep 17 00:00:00 2001 From: root Date: Mon, 5 Nov 2007 16:42:15 +0000 Subject: [PATCH 05/16] *** empty log message *** --- evdns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evdns.c b/evdns.c index 3fd2a91..f61287b 100644 --- a/evdns.c +++ b/evdns.c @@ -1,4 +1,4 @@ -/* $Id: evdns.c,v 1.12 2007-11-04 23:14:11 root Exp $ */ +/* $Id: evdns.c,v 1.13 2007-11-05 16:42:15 root Exp $ */ /* The original version of this module was written by Adam Langley; for * a history of modifications, check out the subversion logs. -- 2.43.0 From edc31a9118d9252f091b336522858c4b3e36e2f8 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 5 Nov 2007 16:42:15 +0000 Subject: [PATCH 06/16] *** empty log message *** --- ev.c | 22 ++++++++++++++++++++++ evdns.c | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/ev.c b/ev.c index 255bb84..53491e1 100644 --- a/ev.c +++ b/ev.c @@ -147,6 +147,12 @@ typedef struct ev_watcher_time *WT; static int have_monotonic; /* did clock_gettime (CLOCK_MONOTONIC) work? */ +#if WIN32 +/* note: the comment below could not be substantiated, but what would I care */ +/* MSDN says this is required to handle SIGFPE */ +volatile double SIGFPE_REQ = 0.0f; +#endif + /*****************************************************************************/ typedef struct @@ -234,6 +240,14 @@ ev_now (EV_P) cur = newcnt; \ } +#define array_slim(stem) \ + if (stem ## max < array_roundsize (stem ## cnt >> 2)) \ + { \ + stem ## max = array_roundsize (stem ## cnt >> 1); \ + base = realloc (base, sizeof (*base) * (stem ## max)); \ + fprintf (stderr, "slimmed down " # stem " to %d\n", stem ## max);/*D*/\ + } + #define array_free(stem, idx) \ free (stem ## s idx); stem ## cnt idx = stem ## max idx = 0; @@ -458,6 +472,10 @@ signals_init (ANSIG *base, int count) static void sighandler (int signum) { +#if WIN32 + signal (signum, sighandler); +#endif + signals [signum - 1].gotsig = 1; if (!gotsig) @@ -1312,11 +1330,15 @@ ev_signal_start (EV_P_ struct ev_signal *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 } } diff --git a/evdns.c b/evdns.c index f61287b..ef4aa02 100644 --- a/evdns.c +++ b/evdns.c @@ -1,4 +1,4 @@ -/* $Id: evdns.c,v 1.13 2007-11-05 16:42:15 root Exp $ */ +/* $Id: evdns.c,v 1.14 2007-11-05 16:45:43 root Exp $ */ /* The original version of this module was written by Adam Langley; for * a history of modifications, check out the subversion logs. -- 2.43.0 From d5b686568688adf526735190000d81a260db6c36 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 5 Nov 2007 17:53:07 +0000 Subject: [PATCH 07/16] *** empty log message *** --- README.embed | 6 ++++ evdns.c | 2 +- import_libevent | 94 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 101 insertions(+), 1 deletion(-) create mode 100755 import_libevent diff --git a/README.embed b/README.embed index b6322d9..1d04427 100644 --- a/README.embed +++ b/README.embed @@ -27,6 +27,12 @@ FILESETS ev.c ev_vars.h ev_wrap.h + ev_select.c only when select backend is enabled (which is by default) + ev_poll.c only when poll backend is enabled (disabled by default) + ev_epoll.c only when the epoll backend is enabled (disabled by default) + ev_kqueue.c only when the kqueue backend is enabled (disabled by default) + + "ev.c" includes the backend files directly when enabled. To include the libevent compatibility API, also include: diff --git a/evdns.c b/evdns.c index ef4aa02..ced6e0c 100644 --- a/evdns.c +++ b/evdns.c @@ -1,4 +1,4 @@ -/* $Id: evdns.c,v 1.14 2007-11-05 16:45:43 root Exp $ */ +/* $Id: evdns.c,v 1.15 2007-11-05 17:57:54 root Exp $ */ /* The original version of this module was written by Adam Langley; for * a history of modifications, check out the subversion logs. diff --git a/import_libevent b/import_libevent new file mode 100755 index 0000000..2765cae --- /dev/null +++ b/import_libevent @@ -0,0 +1,94 @@ +#!/bin/sh + +LE=../libevent-1.3e + +cp $LE/evdns.h . + +perl -ne ' + s/\s+char buf\[64\];/\tchar buf[96];/; + if (/#include "event.h"/) { + print "#ifndef EV_STANDALONE\n$_#endif\n"; + next; + } + if (/#include "misc.h"/) { + print "#ifndef EV_STANDALONE\n$_#endif\n"; + next; + } + next if /#include "log.h"/; + + print; +' <$LE/evdns.c >evdns.c + +cp $LE/epoll_sub.c . +cp $LE/evbuffer.c . +cp $LE/buffer.c . +cp $LE/evhttp.h . +cp $LE/http.c . +cp $LE/event_tagging.c . +cp $LE/http-internal.h . +cp $LE/strlcpy-internal.h . +cp $LE/log.c . +cp $LE/log.h . +cp $LE/strlcpy.c . +rsync -a $LE/WIN32* $LE/sample $LE/test $LE/compat . --del +rename 's/libevent/libev/' WIN32-Prj/lib* +cp $LE/aclocal.m4 . +cp $LE/acconfig.h . +cp $LE/config.h.in . +cp $LE/event_rpcgen.py . +cp $LE/*.3 . + +perl -i -pe 's/libevent/libev/g' sample/Makefile.am +perl -i -pe 's/libevent/libev/g' test/Makefile.am + +perl -i -pe 's/#include $/#include "event.h"/' test/*.c + +perl -i -ne ' + next if /"event-internal.h"/; + s/base\d?->sig.ev_signal_added/0/; + s/base\d?->sig.ev_signal_pair\[0\]/-1/; + next if /test_signal_(dealloc|pipeloss|switchbase)\(\)/; + next if /test_priorities\(\d\)/; + print; +' test/regress.c + +perl -ne ' + s/\bsignal.c\b//g; + s/\bevport.c\b//g; + s/\bkqueue.c\b//g; + s/\bdevpoll.c\b//g; + s/\brtsig.c\b//g; + s/\bselect.c\b//g; + s/\bpoll.c\b//g; + s/\bepoll.c\b//g; + s/\bepoll_sub.c\b//g; + s/\bevent-internal.h\b//g; + s/\bevsignal.h\b//g; + s/^(EXTRA_DIST\s*=\s*)/$1 ev.h ev_vars.h ev_wrap.h event_compat.h ev_epoll.c ev_select.c ev_poll.c ev_kqueue.c /; + s/^(include_HEADERS\s*=\s*)/$1 ev.h event_compat.h /; + s/^(libevent_la_SOURCES\s*=\s*)/$1 ev.c /; + s/^(libevent_la_LIBADD\s*=\s*)/$1 -lm /; + s/libevent/libev/g; + print; +' <$LE/Makefile.am >Makefile.am + +perl -ne ' + s/libevent/libev/g; + s/AC_LIBOBJ\(select\)/: ;/g; + s/AC_LIBOBJ\(poll\)/: ;/g; + s/AC_LIBOBJ\(kqueue\)/: ;/g; + s/AC_LIBOBJ\(epoll\)/: ;/g; + s/AC_LIBOBJ\(devpoll\)/: ;/g; + s/AC_LIBOBJ\(evport\)/: ;/g; + s/AC_LIBOBJ\(signal\)/: ;/g; + s/AC_LIBOBJ\(rtsig\)/: ;/g; + print; +' <$LE/configure.in >configure.in + +aclocal-1.7 +automake-1.7 --add-missing +autoconf +libtoolize +CC="ccache gcc" ./configure --prefix=/opt/libev --disable-shared "$@" + + -- 2.43.0 From 22c618bcb055597260be9be3a5815e08a4cea996 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 5 Nov 2007 20:19:00 +0000 Subject: [PATCH 08/16] *** empty log message *** --- ev.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ev.c b/ev.c index 53491e1..7c312af 100644 --- a/ev.c +++ b/ev.c @@ -157,7 +157,7 @@ volatile double SIGFPE_REQ = 0.0f; typedef struct { - struct ev_watcher_list *head; + WL head; unsigned char events; unsigned char reify; } ANFD; @@ -378,7 +378,6 @@ fd_enomem (EV_P) for (fd = anfdmax; fd--; ) if (anfds [fd].events) { - close (fd); fd_kill (EV_A_ fd); return; } @@ -446,7 +445,7 @@ downheap (WT *heap, int N, int k) typedef struct { - struct ev_watcher_list *head; + WL head; sig_atomic_t volatile gotsig; } ANSIG; @@ -490,7 +489,7 @@ sighandler (int signum) static void sigcb (EV_P_ struct ev_io *iow, int revents) { - struct ev_watcher_list *w; + WL w; int signum; read (sigpipe [0], &revents, 1); -- 2.43.0 From deff62d26ff4c1324816c04c0c6db1e4db435870 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 6 Nov 2007 00:10:04 +0000 Subject: [PATCH 09/16] better error handling --- ev.c | 85 +++++++++++++++++++++++++++++++++++++++++------------ ev.h | 14 +++++++++ ev_epoll.c | 17 +++++++---- ev_kqueue.c | 17 +++++++---- ev_poll.c | 33 +++++++++++---------- ev_select.c | 75 +++++++++++++++++++++++----------------------- 6 files changed, 157 insertions(+), 84 deletions(-) diff --git a/ev.c b/ev.c index 7c312af..c12037c 100644 --- a/ev.c +++ b/ev.c @@ -155,6 +155,51 @@ volatile double SIGFPE_REQ = 0.0f; /*****************************************************************************/ +static void (*syserr_cb)(void); + +void ev_set_syserr_cb (void (*cb)(void)) +{ + syserr_cb = cb; +} + +static void +syserr (void) +{ + if (syserr_cb) + syserr_cb (); + else + { + perror ("libev"); + abort (); + } +} + +static void *(*alloc)(void *ptr, long size); + +void ev_set_allocator (void *(*cb)(void *ptr, long size)) +{ + alloc = cb; +} + +static void * +ev_realloc (void *ptr, long size) +{ + ptr = alloc ? alloc (ptr, size) : realloc (ptr, size); + + if (!ptr && size) + { + fprintf (stderr, "libev: cannot allocate %ld bytes, aborting.", size); + abort (); + } + + return ptr; +} + +#define ev_malloc(size) ev_realloc (0, (size)) +#define ev_free(ptr) ev_realloc ((ptr), 0) + +/*****************************************************************************/ + typedef struct { WL head; @@ -225,31 +270,31 @@ ev_now (EV_P) #define array_roundsize(base,n) ((n) | 4 & ~3) -#define array_needsize(base,cur,cnt,init) \ - if (expect_false ((cnt) > cur)) \ - { \ - int newcnt = cur; \ - do \ - { \ - newcnt = array_roundsize (base, newcnt << 1); \ - } \ - while ((cnt) > newcnt); \ - \ - base = realloc (base, sizeof (*base) * (newcnt)); \ - init (base + cur, newcnt - cur); \ - cur = newcnt; \ +#define array_needsize(base,cur,cnt,init) \ + if (expect_false ((cnt) > cur)) \ + { \ + int newcnt = cur; \ + do \ + { \ + newcnt = array_roundsize (base, newcnt << 1); \ + } \ + while ((cnt) > newcnt); \ + \ + base = ev_realloc (base, sizeof (*base) * (newcnt)); \ + init (base + cur, newcnt - cur); \ + cur = newcnt; \ } #define array_slim(stem) \ if (stem ## max < array_roundsize (stem ## cnt >> 2)) \ { \ stem ## max = array_roundsize (stem ## cnt >> 1); \ - base = realloc (base, sizeof (*base) * (stem ## max)); \ + base = ev_realloc (base, sizeof (*base) * (stem ## max)); \ fprintf (stderr, "slimmed down " # stem " to %d\n", stem ## max);/*D*/\ } #define array_free(stem, idx) \ - free (stem ## s idx); stem ## cnt idx = stem ## max idx = 0; + ev_free (stem ## s idx); stem ## cnt idx = stem ## max idx = 0; /*****************************************************************************/ @@ -704,7 +749,9 @@ loop_fork (EV_P) struct ev_loop * ev_loop_new (int methods) { - struct ev_loop *loop = (struct ev_loop *)calloc (1, sizeof (struct ev_loop)); + struct ev_loop *loop = (struct ev_loop *)ev_malloc (sizeof (struct ev_loop)); + + memset (loop, 0, sizeof (struct ev_loop)); loop_init (EV_A_ methods); @@ -718,7 +765,7 @@ void ev_loop_destroy (EV_P) { loop_destroy (EV_A); - free (loop); + ev_free (loop); } void @@ -1397,7 +1444,7 @@ once_cb (EV_P_ struct ev_once *once, int revents) ev_io_stop (EV_A_ &once->io); ev_timer_stop (EV_A_ &once->to); - free (once); + ev_free (once); cb (revents, arg); } @@ -1417,7 +1464,7 @@ once_cb_to (EV_P_ struct ev_timer *w, int revents) void ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg) { - struct ev_once *once = malloc (sizeof (struct ev_once)); + struct ev_once *once = ev_malloc (sizeof (struct ev_once)); if (!once) cb (EV_ERROR | EV_READ | EV_WRITE | EV_TIMEOUT, arg); diff --git a/ev.h b/ev.h index 1933285..08b5963 100644 --- a/ev.h +++ b/ev.h @@ -229,6 +229,20 @@ int ev_version_minor (void); ev_tstamp ev_time (void); +/* Sets the allocation function to use, works like realloc. + * It is used to allocate and free memory. + * If it returns zero when memory needs to be allocated, the library might abort + * or take some potentially destructive action. + * The default is your system realloc function. + */ +void ev_set_allocator (void *(*cb)(void *ptr, long size)); + +/* set the callback function to call on a + * retryable syscall error + * (such as failed select, poll, epoll_wait) + */ +void ev_set_syserr_cb (void (*cb)(void)); + # if EV_MULTIPLICITY /* the default loop is the only one that handles signals and child watchers */ /* you can call this as often as you like */ diff --git a/ev_epoll.c b/ev_epoll.c index 4689f8d..6bb41bc 100644 --- a/ev_epoll.c +++ b/ev_epoll.c @@ -51,11 +51,16 @@ epoll_modify (EV_P_ int fd, int oev, int nev) static void epoll_poll (EV_P_ ev_tstamp timeout) { - int eventcnt = epoll_wait (epoll_fd, epoll_events, epoll_eventmax, ceil (timeout * 1000.)); int i; + int eventcnt = epoll_wait (epoll_fd, epoll_events, epoll_eventmax, ceil (timeout * 1000.)); if (eventcnt < 0) - return; + { + if (errno != EINTR) + syserr (); + + return; + } for (i = 0; i < eventcnt; ++i) fd_event ( @@ -68,9 +73,9 @@ epoll_poll (EV_P_ ev_tstamp timeout) /* if the receive array was full, increase its size */ if (expect_false (eventcnt == epoll_eventmax)) { - free (epoll_events); + ev_free (epoll_events); epoll_eventmax = array_roundsize (epoll_events, epoll_eventmax << 1); - epoll_events = malloc (sizeof (struct epoll_event) * epoll_eventmax); + epoll_events = ev_malloc (sizeof (struct epoll_event) * epoll_eventmax); } } @@ -89,7 +94,7 @@ epoll_init (EV_P_ int flags) method_poll = epoll_poll; epoll_eventmax = 64; /* intiial number of events receivable per poll */ - epoll_events = malloc (sizeof (struct epoll_event) * epoll_eventmax); + epoll_events = ev_malloc (sizeof (struct epoll_event) * epoll_eventmax); return EVMETHOD_EPOLL; } @@ -99,7 +104,7 @@ epoll_destroy (EV_P) { close (epoll_fd); - free (epoll_events); + ev_free (epoll_events); } static void diff --git a/ev_kqueue.c b/ev_kqueue.c index 24c3015..4fefcee 100644 --- a/ev_kqueue.c +++ b/ev_kqueue.c @@ -85,7 +85,12 @@ kqueue_poll (EV_P_ ev_tstamp timeout) kqueue_changecnt = 0; if (res < 0) - return; + { + if (errno != EINTR) + syserr (); + + return; + } for (i = 0; i < res; ++i) { @@ -118,9 +123,9 @@ kqueue_poll (EV_P_ ev_tstamp timeout) if (expect_false (res == kqueue_eventmax)) { - free (kqueue_events); + ev_free (kqueue_events); kqueue_eventmax = array_roundsize (kqueue_events, kqueue_eventmax << 1); - kqueue_events = malloc (sizeof (struct kevent) * kqueue_eventmax); + kqueue_events = ev_malloc (sizeof (struct kevent) * kqueue_eventmax); } } @@ -159,7 +164,7 @@ kqueue_init (EV_P_ int flags) method_poll = kqueue_poll; kqueue_eventmax = 64; /* intiial number of events receivable per poll */ - kqueue_events = malloc (sizeof (struct kevent) * kqueue_eventmax); + kqueue_events = ev_malloc (sizeof (struct kevent) * kqueue_eventmax); kqueue_changes = 0; kqueue_changemax = 0; @@ -173,8 +178,8 @@ kqueue_destroy (EV_P) { close (kqueue_fd); - free (kqueue_events); - free (kqueue_changes); + ev_free (kqueue_events); + ev_free (kqueue_changes); } static void diff --git a/ev_poll.c b/ev_poll.c index b58ce82..e809ddd 100644 --- a/ev_poll.c +++ b/ev_poll.c @@ -75,27 +75,28 @@ poll_modify (EV_P_ int fd, int oev, int nev) static void poll_poll (EV_P_ ev_tstamp timeout) { + int i; int res = poll (polls, pollcnt, ceil (timeout * 1000.)); - if (res > 0) - { - int i; - - for (i = 0; i < pollcnt; ++i) - fd_event ( - EV_A_ - polls [i].fd, - (polls [i].revents & (POLLOUT | POLLERR | POLLHUP) ? EV_WRITE : 0) - | (polls [i].revents & (POLLIN | POLLERR | POLLHUP) ? EV_READ : 0) - ); - } - else if (res < 0) + if (res < 0) { if (errno == EBADF) fd_ebadf (EV_A); - else if (errno == ENOMEM) + else if (errno == ENOMEM && !syserr_cb) fd_enomem (EV_A); + else if (errno != EINTR) + syserr (); + + return; } + + for (i = 0; i < pollcnt; ++i) + fd_event ( + EV_A_ + polls [i].fd, + (polls [i].revents & (POLLOUT | POLLERR | POLLHUP) ? EV_WRITE : 0) + | (polls [i].revents & (POLLIN | POLLERR | POLLHUP) ? EV_READ : 0) + ); } static int @@ -114,6 +115,6 @@ poll_init (EV_P_ int flags) static void poll_destroy (EV_P) { - free (pollidxs); - free (polls); + ev_free (pollidxs); + ev_free (polls); } diff --git a/ev_select.c b/ev_select.c index 9f81e55..5f75e37 100644 --- a/ev_select.c +++ b/ev_select.c @@ -55,10 +55,10 @@ select_modify (EV_P_ int fd, int oev, int nev) { int new_max = (fd >> 5) + 1; - vec_ri = (unsigned char *)realloc (vec_ri, new_max * 4); - vec_ro = (unsigned char *)realloc (vec_ro, new_max * 4); /* could free/malloc */ - vec_wi = (unsigned char *)realloc (vec_wi, new_max * 4); - vec_wo = (unsigned char *)realloc (vec_wo, new_max * 4); /* could free/malloc */ + vec_ri = (unsigned char *)ev_realloc (vec_ri, new_max * 4); + vec_ro = (unsigned char *)ev_realloc (vec_ro, new_max * 4); /* could free/malloc */ + vec_wi = (unsigned char *)ev_realloc (vec_wi, new_max * 4); + vec_wo = (unsigned char *)ev_realloc (vec_wo, new_max * 4); /* could free/malloc */ for (; vec_max < new_max; ++vec_max) ((uint32_t *)vec_ri)[vec_max] = @@ -77,6 +77,7 @@ select_modify (EV_P_ int fd, int oev, int nev) static void select_poll (EV_P_ ev_tstamp timeout) { + int word, offs; struct timeval tv; int res; @@ -88,39 +89,39 @@ select_poll (EV_P_ ev_tstamp timeout) res = select (vec_max * 32, (fd_set *)vec_ro, (fd_set *)vec_wo, 0, &tv); - if (res > 0) - { - int word, offs; - - for (word = vec_max; word--; ) - { - if (((uint32_t *)vec_ro) [word] | ((uint32_t *)vec_wo) [word]) - for (offs = 4; offs--; ) - { - int idx = word * 4 + offs; - unsigned char byte_r = vec_ro [idx]; - unsigned char byte_w = vec_wo [idx]; - int bit; - - if (byte_r | byte_w) - for (bit = 8; bit--; ) - { - int events = 0; - events |= byte_r & (1 << bit) ? EV_READ : 0; - events |= byte_w & (1 << bit) ? EV_WRITE : 0; - - if (events) - fd_event (EV_A_ idx * 8 + bit, events); - } - } - } - } - else if (res < 0) + if (res < 0) { if (errno == EBADF) fd_ebadf (EV_A); - else if (errno == ENOMEM) + else if (errno == ENOMEM && !syserr_cb) fd_enomem (EV_A); + else if (errno != EINTR) + syserr (); + + return; + } + + for (word = vec_max; word--; ) + { + if (((uint32_t *)vec_ro) [word] | ((uint32_t *)vec_wo) [word]) + for (offs = 4; offs--; ) + { + int idx = word * 4 + offs; + unsigned char byte_r = vec_ro [idx]; + unsigned char byte_w = vec_wo [idx]; + int bit; + + if (byte_r | byte_w) + for (bit = 8; bit--; ) + { + int events = 0; + events |= byte_r & (1 << bit) ? EV_READ : 0; + events |= byte_w & (1 << bit) ? EV_WRITE : 0; + + if (events) + fd_event (EV_A_ idx * 8 + bit, events); + } + } } } @@ -143,10 +144,10 @@ select_init (EV_P_ int flags) static void select_destroy (EV_P) { - free (vec_ri); - free (vec_ro); - free (vec_wi); - free (vec_wo); + ev_free (vec_ri); + ev_free (vec_ro); + ev_free (vec_wi); + ev_free (vec_wo); } -- 2.43.0 From 499c7e995433fedd0a2333ec6d9bc3768e6224f4 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 6 Nov 2007 00:52:32 +0000 Subject: [PATCH 10/16] better fork --- ev.c | 60 +++++++++++++++++++++++++++++++++-------------------- ev.h | 2 +- ev_epoll.c | 13 ++++++++++-- ev_kqueue.c | 13 ++++++++++-- ev_poll.c | 2 +- ev_select.c | 2 +- ev_vars.h | 1 + 7 files changed, 64 insertions(+), 29 deletions(-) diff --git a/ev.c b/ev.c index c12037c..0457088 100644 --- a/ev.c +++ b/ev.c @@ -155,21 +155,24 @@ volatile double SIGFPE_REQ = 0.0f; /*****************************************************************************/ -static void (*syserr_cb)(void); +static void (*syserr_cb)(const char *msg); -void ev_set_syserr_cb (void (*cb)(void)) +void ev_set_syserr_cb (void (*cb)(const char *msg)) { syserr_cb = cb; } static void -syserr (void) +syserr (const char *msg) { + if (!msg) + msg = "(libev) system error"; + if (syserr_cb) - syserr_cb (); + syserr_cb (msg); else { - perror ("libev"); + perror (msg); abort (); } } @@ -380,7 +383,7 @@ fd_reify (EV_P) static void fd_change (EV_P_ int fd) { - if (anfds [fd].reify || fdchangecnt < 0) + if (anfds [fd].reify) return; anfds [fd].reify = 1; @@ -428,7 +431,7 @@ fd_enomem (EV_P) } } -/* susually called after fork if method needs to re-arm all fds from scratch */ +/* usually called after fork if method needs to re-arm all fds from scratch */ static void fd_rearm_all (EV_P) { @@ -695,6 +698,9 @@ loop_init (EV_P_ int methods) #if EV_USE_SELECT if (!method && (methods & EVMETHOD_SELECT)) method = select_init (EV_A_ methods); #endif + + ev_watcher_init (&sigev, sigcb); + ev_set_priority (&sigev, EV_MAXPRI); } } @@ -730,19 +736,34 @@ loop_destroy (EV_P) array_free (check, ); method = 0; - /*TODO*/ } -void +static void loop_fork (EV_P) { - /*TODO*/ #if EV_USE_EPOLL if (method == EVMETHOD_EPOLL ) epoll_fork (EV_A); #endif #if EV_USE_KQUEUE if (method == EVMETHOD_KQUEUE) kqueue_fork (EV_A); #endif + + if (ev_is_active (&sigev)) + { + /* default loop */ + + ev_ref (EV_A); + ev_io_stop (EV_A_ &sigev); + close (sigpipe [0]); + close (sigpipe [1]); + + while (pipe (sigpipe)) + syserr ("(libev) error creating pipe"); + + siginit (EV_A); + } + + postfork = 0; } #if EV_MULTIPLICITY @@ -771,7 +792,7 @@ ev_loop_destroy (EV_P) void ev_loop_fork (EV_P) { - loop_fork (EV_A); + postfork = 1; } #endif @@ -804,8 +825,6 @@ ev_default_loop (int methods) if (ev_method (EV_A)) { - ev_watcher_init (&sigev, sigcb); - ev_set_priority (&sigev, EV_MAXPRI); siginit (EV_A); #ifndef WIN32 @@ -848,15 +867,8 @@ ev_default_fork (void) struct ev_loop *loop = default_loop; #endif - loop_fork (EV_A); - - ev_io_stop (EV_A_ &sigev); - close (sigpipe [0]); - close (sigpipe [1]); - pipe (sigpipe); - - ev_ref (EV_A); /* signal watcher */ - siginit (EV_A); + if (method) + postfork = 1; } /*****************************************************************************/ @@ -1044,6 +1056,10 @@ ev_loop (EV_P_ int flags) call_pending (EV_A); } + /* we might have forked, so reify kernel state if necessary */ + if (expect_false (postfork)) + loop_fork (EV_A); + /* update fd-related kernel structures */ fd_reify (EV_A); diff --git a/ev.h b/ev.h index 08b5963..83cda6f 100644 --- a/ev.h +++ b/ev.h @@ -241,7 +241,7 @@ void ev_set_allocator (void *(*cb)(void *ptr, long size)); * retryable syscall error * (such as failed select, poll, epoll_wait) */ -void ev_set_syserr_cb (void (*cb)(void)); +void ev_set_syserr_cb (void (*cb)(const char *msg)); # if EV_MULTIPLICITY /* the default loop is the only one that handles signals and child watchers */ diff --git a/ev_epoll.c b/ev_epoll.c index 6bb41bc..2040103 100644 --- a/ev_epoll.c +++ b/ev_epoll.c @@ -57,7 +57,7 @@ epoll_poll (EV_P_ ev_tstamp timeout) if (eventcnt < 0) { if (errno != EINTR) - syserr (); + syserr ("(libev) epoll_wait"); return; } @@ -110,7 +110,16 @@ epoll_destroy (EV_P) static void epoll_fork (EV_P) { - epoll_fd = epoll_create (256); + for (;;) + { + epoll_fd = epoll_create (256); + + if (epoll_fd >= 0) + break; + + syserr ("(libev) epoll_create"); + } + fcntl (epoll_fd, F_SETFD, FD_CLOEXEC); fd_rearm_all (EV_A); diff --git a/ev_kqueue.c b/ev_kqueue.c index 4fefcee..07d16e4 100644 --- a/ev_kqueue.c +++ b/ev_kqueue.c @@ -87,7 +87,7 @@ kqueue_poll (EV_P_ ev_tstamp timeout) if (res < 0) { if (errno != EINTR) - syserr (); + syserr ("(libev) kevent"); return; } @@ -185,7 +185,16 @@ kqueue_destroy (EV_P) static void kqueue_fork (EV_P) { - kqueue_fd = kqueue (); + for (;;) + { + kqueue_fd = kqueue (); + + if (kqueue_fd >= 0) + break; + + syserr ("(libev) kqueue"); + } + fcntl (kqueue_fd, F_SETFD, FD_CLOEXEC); /* re-register interest in fds */ diff --git a/ev_poll.c b/ev_poll.c index e809ddd..1ce41c6 100644 --- a/ev_poll.c +++ b/ev_poll.c @@ -85,7 +85,7 @@ poll_poll (EV_P_ ev_tstamp timeout) else if (errno == ENOMEM && !syserr_cb) fd_enomem (EV_A); else if (errno != EINTR) - syserr (); + syserr ("(libev) poll"); return; } diff --git a/ev_select.c b/ev_select.c index 5f75e37..e3e79ca 100644 --- a/ev_select.c +++ b/ev_select.c @@ -96,7 +96,7 @@ select_poll (EV_P_ ev_tstamp timeout) else if (errno == ENOMEM && !syserr_cb) fd_enomem (EV_A); else if (errno != EINTR) - syserr (); + syserr ("(libev) select"); return; } diff --git a/ev_vars.h b/ev_vars.h index 98029ed..c506944 100644 --- a/ev_vars.h +++ b/ev_vars.h @@ -10,6 +10,7 @@ VARx(ev_tstamp, method_fudge) /* assumed typical timer resolution */ VAR (method_modify, void (*method_modify)(EV_P_ int fd, int oev, int nev)) VAR (method_poll , void (*method_poll)(EV_P_ ev_tstamp timeout)) +VARx(int, postfork) /* true if we need to recreate kernel state after fork */ VARx(int, activecnt) /* number of active events */ #if EV_USE_SELECT || EV_GENWRAP -- 2.43.0 From 692ca25945e1a987acf66bd845ce70a61aa7b160 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 6 Nov 2007 00:57:02 +0000 Subject: [PATCH 11/16] *** empty log message *** --- ev_wrap.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ev_wrap.h b/ev_wrap.h index b5320c7..b0f55c1 100644 --- a/ev_wrap.h +++ b/ev_wrap.h @@ -7,6 +7,7 @@ #define method_fudge ((loop)->method_fudge) #define method_modify ((loop)->method_modify) #define method_poll ((loop)->method_poll) +#define postfork ((loop)->postfork) #define activecnt ((loop)->activecnt) #define vec_ri ((loop)->vec_ri) #define vec_ro ((loop)->vec_ro) -- 2.43.0 From bdffebc95dd4e027a45853749b06f140d6f97ebc Mon Sep 17 00:00:00 2001 From: root Date: Tue, 6 Nov 2007 01:17:16 +0000 Subject: [PATCH 12/16] better fork --- ev_epoll.c | 11 +++-------- ev_kqueue.c | 11 +++-------- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/ev_epoll.c b/ev_epoll.c index 2040103..9f5bd25 100644 --- a/ev_epoll.c +++ b/ev_epoll.c @@ -110,15 +110,10 @@ epoll_destroy (EV_P) static void epoll_fork (EV_P) { - for (;;) - { - epoll_fd = epoll_create (256); - - if (epoll_fd >= 0) - break; + close (epoll_fd); - syserr ("(libev) epoll_create"); - } + while ((epoll_fd = epoll_create (256)) < 0) + syserr ("(libev) epoll_create"); fcntl (epoll_fd, F_SETFD, FD_CLOEXEC); diff --git a/ev_kqueue.c b/ev_kqueue.c index 07d16e4..8d5021f 100644 --- a/ev_kqueue.c +++ b/ev_kqueue.c @@ -185,15 +185,10 @@ kqueue_destroy (EV_P) static void kqueue_fork (EV_P) { - for (;;) - { - kqueue_fd = kqueue (); - - if (kqueue_fd >= 0) - break; + close (kqueue_fd); - syserr ("(libev) kqueue"); - } + while ((kqueue_fd = kqueue ()) < 0) + syserr ("(libev) kqueue"); fcntl (kqueue_fd, F_SETFD, FD_CLOEXEC); -- 2.43.0 From 06eac6f8c010d4bd41a19feca9db3ac13d3cafb3 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 6 Nov 2007 01:24:30 +0000 Subject: [PATCH 13/16] *** empty log message *** --- LICENSE | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/LICENSE b/LICENSE index 21ef21a..e440058 100644 --- a/LICENSE +++ b/LICENSE @@ -10,6 +10,10 @@ met: disclaimer in the documentation and/or other materials provided with the distribution. + * The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -22,8 +26,9 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -NOTE: some parts of this library are under a different license, namely the -3-clause BSD style license, which is compatible with this one, but carries -the additional restriction that you must not use the name of the author(s) -of those parts to endorse any product. +NOTE: the core parts of this library are under the so-called 2-clause +BSD style license, which is compatible with this one, but lacks the +restriction that you must not use the name of the author(s) of those parts +to endorse any product. So feel free to use the authors name and any +others that helped write the core parts :) -- 2.43.0 From 4ee0973144c5b6c7cf136b1256e7ce9cb802e682 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 6 Nov 2007 13:17:55 +0000 Subject: [PATCH 14/16] now port to microsofts goddamn broken pseudo-c-we-do-it-different-to-spite-you so-called c compiler --- ev.c | 66 ++++++++++++++++++++++++++++++++++++----------------- ev.h | 2 +- ev_select.c | 11 ++++----- event.c | 11 +++++---- 4 files changed, 57 insertions(+), 33 deletions(-) diff --git a/ev.c b/ev.c index 0457088..0976897 100644 --- a/ev.c +++ b/ev.c @@ -56,9 +56,7 @@ #include #include -#include #include -#include #include #include @@ -66,12 +64,17 @@ #include #include #include +#include + +#ifndef PERL +# include +#endif + #ifndef WIN32 +# include +# include # include #endif -#include -#include - /**/ #ifndef EV_USE_MONOTONIC @@ -96,7 +99,9 @@ #ifndef EV_USE_WIN32 # ifdef WIN32 -# define EV_USE_WIN32 1 +# define EV_USE_WIN32 0 /* it does not exist, use select */ +# undef EV_USE_SELECT +# define EV_USE_SELECT 1 # else # define EV_USE_WIN32 0 # endif @@ -296,6 +301,11 @@ ev_now (EV_P) fprintf (stderr, "slimmed down " # stem " to %d\n", stem ## max);/*D*/\ } +/* microsoft's pseudo-c is quite far from C as the rest of the world and the standard knows it */ +/* bringing us everlasting joy in form of stupid extra macros that are not required in C */ +#define array_free_microshit(stem) \ + ev_free (stem ## s); stem ## cnt = stem ## max = 0; + #define array_free(stem, idx) \ ev_free (stem ## s idx); stem ## cnt idx = stem ## max idx = 0; @@ -324,7 +334,7 @@ event (EV_P_ W w, int events) } w->pending = ++pendingcnt [ABSPRI (w)]; - array_needsize (pendings [ABSPRI (w)], pendingmax [ABSPRI (w)], pendingcnt [ABSPRI (w)], ); + array_needsize (pendings [ABSPRI (w)], pendingmax [ABSPRI (w)], pendingcnt [ABSPRI (w)], (void)); pendings [ABSPRI (w)][w->pending - 1].w = w; pendings [ABSPRI (w)][w->pending - 1].events = events; } @@ -389,7 +399,7 @@ fd_change (EV_P_ int fd) anfds [fd].reify = 1; ++fdchangecnt; - array_needsize (fdchanges, fdchangemax, fdchangecnt, ); + array_needsize (fdchanges, fdchangemax, fdchangecnt, (void)); fdchanges [fdchangecnt - 1] = fd; } @@ -405,6 +415,16 @@ fd_kill (EV_P_ int fd) } } +static int +fd_valid (int fd) +{ +#ifdef WIN32 + return !!win32_get_osfhandle (fd); +#else + return fcntl (fd, F_GETFD) != -1; +#endif +} + /* called on EBADF to verify fds */ static void fd_ebadf (EV_P) @@ -413,7 +433,7 @@ fd_ebadf (EV_P) for (fd = 0; fd < anfdmax; ++fd) if (anfds [fd].events) - if (fcntl (fd, F_GETFD) == -1 && errno == EBADF) + if (!fd_valid (fd) == -1 && errno == EBADF) fd_kill (EV_A_ fd); } @@ -572,9 +592,10 @@ siginit (EV_P) /*****************************************************************************/ +static struct ev_child *childs [PID_HASHSIZE]; + #ifndef WIN32 -static struct ev_child *childs [PID_HASHSIZE]; static struct ev_signal childev; #ifndef WCONTINUED @@ -728,12 +749,13 @@ loop_destroy (EV_P) for (i = NUMPRI; i--; ) array_free (pending, [i]); - array_free (fdchange, ); - array_free (timer, ); - array_free (periodic, ); - array_free (idle, ); - array_free (prepare, ); - array_free (check, ); + /* have to use the microsoft-never-gets-it-right macro */ + array_free_microshit (fdchange); + array_free_microshit (timer); + array_free_microshit (periodic); + array_free_microshit (idle); + array_free_microshit (prepare); + array_free_microshit (check); method = 0; } @@ -848,8 +870,10 @@ ev_default_destroy (void) struct ev_loop *loop = default_loop; #endif +#ifndef WIN32 ev_ref (EV_A); /* child watcher */ ev_signal_stop (EV_A_ &childev); +#endif ev_ref (EV_A); /* signal watcher */ ev_io_stop (EV_A_ &sigev); @@ -1223,7 +1247,7 @@ ev_timer_start (EV_P_ struct ev_timer *w) assert (("ev_timer_start called with negative timer repeat value", w->repeat >= 0.)); ev_start (EV_A_ (W)w, ++timercnt); - array_needsize (timers, timermax, timercnt, ); + array_needsize (timers, timermax, timercnt, (void)); timers [timercnt - 1] = w; upheap ((WT *)timers, timercnt - 1); @@ -1280,7 +1304,7 @@ ev_periodic_start (EV_P_ struct ev_periodic *w) ((WT)w)->at += ceil ((rt_now - ((WT)w)->at) / w->interval) * w->interval; ev_start (EV_A_ (W)w, ++periodiccnt); - array_needsize (periodics, periodicmax, periodiccnt, ); + array_needsize (periodics, periodicmax, periodiccnt, (void)); periodics [periodiccnt - 1] = w; upheap ((WT *)periodics, periodiccnt - 1); @@ -1312,7 +1336,7 @@ ev_idle_start (EV_P_ struct ev_idle *w) return; ev_start (EV_A_ (W)w, ++idlecnt); - array_needsize (idles, idlemax, idlecnt, ); + array_needsize (idles, idlemax, idlecnt, (void)); idles [idlecnt - 1] = w; } @@ -1334,7 +1358,7 @@ ev_prepare_start (EV_P_ struct ev_prepare *w) return; ev_start (EV_A_ (W)w, ++preparecnt); - array_needsize (prepares, preparemax, preparecnt, ); + array_needsize (prepares, preparemax, preparecnt, (void)); prepares [preparecnt - 1] = w; } @@ -1356,7 +1380,7 @@ ev_check_start (EV_P_ struct ev_check *w) return; ev_start (EV_A_ (W)w, ++checkcnt); - array_needsize (checks, checkmax, checkcnt, ); + array_needsize (checks, checkmax, checkcnt, (void)); checks [checkcnt - 1] = w; } diff --git a/ev.h b/ev.h index 83cda6f..e7386f2 100644 --- a/ev.h +++ b/ev.h @@ -100,7 +100,7 @@ struct ev_loop; int pending; /* private */ \ int priority; /* private */ \ EV_COMMON; /* rw */ \ - void (*cb)(EV_P_ struct type *, int revents); /* private */ /* gets invoked with an eventmask */ + void (*cb)(EV_P_ struct type *, int revents) /* private */ /* gets invoked with an eventmask */ #define EV_WATCHER_LIST(type) \ EV_WATCHER (type); \ diff --git a/ev_select.c b/ev_select.c index e3e79ca..60cc084 100644 --- a/ev_select.c +++ b/ev_select.c @@ -29,18 +29,15 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* for broken bsd's */ -#include -#include -#include - /* for unix systems */ -#ifndef WIN32 +#ifdef WIN32 +typedef unsigned int uint32_t; +#else # include +# include #endif #include -#include static void select_modify (EV_P_ int fd, int oev, int nev) diff --git a/event.c b/event.c index cf7739c..0fc6850 100644 --- a/event.c +++ b/event.c @@ -31,9 +31,12 @@ #include #include -#include #include +#ifndef WIN32 +# include +#endif + #include "ev.h" #include "event.h" @@ -240,9 +243,9 @@ int event_del (struct event *ev) int event_pending (struct event *ev, short events, struct timeval *tv) { + short revents = 0; dLOOPev; - short revents = 0; if (ev->ev_events & EV_SIGNAL) { @@ -311,8 +314,8 @@ x_loopexit_cb (int revents, void *base) int event_base_loopexit (struct event_base *base, struct timeval *tv) { - dLOOPbase; ev_tstamp after = tv_get (tv); + dLOOPbase; ev_once (EV_A_ -1, 0, after >= 0. ? after : 0., x_loopexit_cb, (void *)base); @@ -337,8 +340,8 @@ x_once_cb (int revents, void *arg) int event_base_once (struct event_base *base, int fd, short events, void (*cb)(int, short, void *), void *arg, struct timeval *tv) { - dLOOPbase; struct x_once *once = malloc (sizeof (struct x_once)); + dLOOPbase; if (!once) return -1; -- 2.43.0 From 36718ee47b617f9eeb411c70d1dd87bc33389db3 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 6 Nov 2007 16:09:37 +0000 Subject: [PATCH 15/16] big win32 check-in --- ev.c | 61 ++++++++++++++++++++++++++++++--- ev_select.c | 91 ++++++++++++++++++++++++++++++++++++------------- evdns.c | 4 +-- import_libevent | 4 +++ 4 files changed, 129 insertions(+), 31 deletions(-) diff --git a/ev.c b/ev.c index 0976897..79b3786 100644 --- a/ev.c +++ b/ev.c @@ -66,9 +66,7 @@ #include #include -#ifndef PERL -# include -#endif +#include #ifndef WIN32 # include @@ -156,6 +154,59 @@ static int have_monotonic; /* did clock_gettime (CLOCK_MONOTONIC) work? */ /* note: the comment below could not be substantiated, but what would I care */ /* MSDN says this is required to handle SIGFPE */ volatile double SIGFPE_REQ = 0.0f; + +static int +ev_socketpair_tcp (int filedes [2]) +{ + struct sockaddr_in addr = { 0 }; + int addr_size = sizeof (addr); + SOCKET listener; + SOCKET sock [2] = { -1, -1 }; + + if ((listener = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) + return -1; + + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); + addr.sin_port = 0; + + if (bind (listener, (struct sockaddr *)&addr, addr_size)) + goto fail; + + if (getsockname(listener, (struct sockaddr *)&addr, &addr_size)) + goto fail; + + if (listen (listener, 1)) + goto fail; + + if ((sock [0] = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) + goto fail; + + if (connect (sock[0], (struct sockaddr *)&addr, addr_size)) + goto fail; + + if ((sock[1] = accept (listener, 0, 0)) < 0) + goto fail; + + closesocket (listener); + + filedes [0] = sock [0]; + filedes [1] = sock [1]; + + return 0; + +fail: + closesocket (listener); + + if (sock [0] != INVALID_SOCKET) closesocket (sock [0]); + if (sock [1] != INVALID_SOCKET) closesocket (sock [1]); + + return -1; +} + +# define ev_pipe(filedes) ev_socketpair_tcp (filedes) +#else +# define ev_pipe(filedes) pipe (filedes) #endif /*****************************************************************************/ @@ -779,7 +830,7 @@ loop_fork (EV_P) close (sigpipe [0]); close (sigpipe [1]); - while (pipe (sigpipe)) + while (ev_pipe (sigpipe)) syserr ("(libev) error creating pipe"); siginit (EV_A); @@ -832,7 +883,7 @@ int ev_default_loop (int methods) { if (sigpipe [0] == sigpipe [1]) - if (pipe (sigpipe)) + if (ev_pipe (sigpipe)) return 0; if (!default_loop) diff --git a/ev_select.c b/ev_select.c index 60cc084..d9fdf92 100644 --- a/ev_select.c +++ b/ev_select.c @@ -32,6 +32,7 @@ /* for unix systems */ #ifdef WIN32 typedef unsigned int uint32_t; +# define EV_SELECT_USE_FD_SET 1 #else # include # include @@ -42,33 +43,47 @@ typedef unsigned int uint32_t; static void select_modify (EV_P_ int fd, int oev, int nev) { - int offs = fd >> 3; - int mask = 1 << (fd & 7); - if (oev == nev) return; - if (vec_max < (fd >> 5) + 1) - { - int new_max = (fd >> 5) + 1; - - vec_ri = (unsigned char *)ev_realloc (vec_ri, new_max * 4); - vec_ro = (unsigned char *)ev_realloc (vec_ro, new_max * 4); /* could free/malloc */ - vec_wi = (unsigned char *)ev_realloc (vec_wi, new_max * 4); - vec_wo = (unsigned char *)ev_realloc (vec_wo, new_max * 4); /* could free/malloc */ - - for (; vec_max < new_max; ++vec_max) - ((uint32_t *)vec_ri)[vec_max] = - ((uint32_t *)vec_wi)[vec_max] = 0; - } - - vec_ri [offs] |= mask; - if (!(nev & EV_READ)) - vec_ri [offs] &= ~mask; +#if EV_SELECT_USE_FD_SET + if (nev & EV_READ) + FD_SET (fd, (struct fd_set *)vec_ri); + else + FD_CLR (fd, (struct fd_set *)vec_ri); - vec_wi [offs] |= mask; - if (!(nev & EV_WRITE)) - vec_wi [offs] &= ~mask; + if (nev & EV_WRITE) + FD_SET (fd, (struct fd_set *)vec_wi); + else + FD_CLR (fd, (struct fd_set *)vec_wi); +#else + { + int offs = fd >> 3; + int mask = 1 << (fd & 7); + + if (vec_max < (fd >> 5) + 1) + { + int new_max = (fd >> 5) + 1; + + vec_ri = (unsigned char *)ev_realloc (vec_ri, new_max * 4); + vec_ro = (unsigned char *)ev_realloc (vec_ro, new_max * 4); /* could free/malloc */ + vec_wi = (unsigned char *)ev_realloc (vec_wi, new_max * 4); + vec_wo = (unsigned char *)ev_realloc (vec_wo, new_max * 4); /* could free/malloc */ + + for (; vec_max < new_max; ++vec_max) + ((uint32_t *)vec_ri)[vec_max] = + ((uint32_t *)vec_wi)[vec_max] = 0; + } + + vec_ri [offs] |= mask; + if (!(nev & EV_READ)) + vec_ri [offs] &= ~mask; + + vec_wi [offs] |= mask; + if (!(nev & EV_WRITE)) + vec_wi [offs] &= ~mask; + } +#endif } static void @@ -78,8 +93,13 @@ select_poll (EV_P_ ev_tstamp timeout) struct timeval tv; int res; +#if EV_SELECT_USE_FD_SET + memcpy (vec_ro, vec_ri, sizeof (struct fd_set)); + memcpy (vec_wo, vec_wi, sizeof (struct fd_set)); +#else memcpy (vec_ro, vec_ri, vec_max * 4); memcpy (vec_wo, vec_wi, vec_max * 4); +#endif tv.tv_sec = (long)timeout; tv.tv_usec = (long)((timeout - (ev_tstamp)tv.tv_sec) * 1e6); @@ -88,6 +108,11 @@ select_poll (EV_P_ ev_tstamp timeout) if (res < 0) { +#ifdef WIN32 + if (errno == WSAEINTR ) errno = EINTR; + if (errno == WSAENOTSOCK) errno = EBADF; +#endif + if (errno == EBADF) fd_ebadf (EV_A); else if (errno == ENOMEM && !syserr_cb) @@ -98,6 +123,17 @@ select_poll (EV_P_ ev_tstamp timeout) return; } +#if EV_SELECT_USE_FD_SET + for (word = 0; word < FD_SETSIZE; ++word) + { + int events = 0; + if (FD_ISSET (word, (struct fd_set *)vec_ro)) events |= EV_READ; + if (FD_ISSET (word, (struct fd_set *)vec_wo)) events |= EV_WRITE; + + if (events) + fd_event (EV_A_ word, events); + } +#else for (word = vec_max; word--; ) { if (((uint32_t *)vec_ro) [word] | ((uint32_t *)vec_wo) [word]) @@ -120,6 +156,7 @@ select_poll (EV_P_ ev_tstamp timeout) } } } +#endif } static int @@ -129,11 +166,19 @@ select_init (EV_P_ int flags) method_modify = select_modify; method_poll = select_poll; +#if EV_SELECT_USE_FD_SET + vec_max = FD_SETSIZE / 32; + vec_ri = ev_malloc (sizeof (struct fd_set)); FD_ZERO ((struct fd_set *)vec_ri); + vec_ro = ev_malloc (sizeof (struct fd_set)); + vec_wi = ev_malloc (sizeof (struct fd_set)); FD_ZERO ((struct fd_set *)vec_wi); + vec_wo = ev_malloc (sizeof (struct fd_set)); +#else vec_max = 0; vec_ri = 0; vec_ri = 0; vec_wo = 0; vec_wo = 0; +#endif return EVMETHOD_SELECT; } diff --git a/evdns.c b/evdns.c index ced6e0c..c12b4f6 100644 --- a/evdns.c +++ b/evdns.c @@ -1,4 +1,4 @@ -/* $Id: evdns.c,v 1.15 2007-11-05 17:57:54 root Exp $ */ +/* $Id: evdns.c,v 1.16 2007-11-06 16:09:37 root Exp $ */ /* The original version of this module was written by Adam Langley; for * a history of modifications, check out the subversion logs. @@ -80,7 +80,6 @@ #include #include -#include #ifdef HAVE_STDINT_H #include #endif @@ -88,7 +87,6 @@ #include #include #include -#include #include #include #include diff --git a/import_libevent b/import_libevent index 2765cae..6b0b8cd 100755 --- a/import_libevent +++ b/import_libevent @@ -14,6 +14,10 @@ perl -ne ' print "#ifndef EV_STANDALONE\n$_#endif\n"; next; } + if (/#include "(unistd.h|sys/time.h)"/) { + print "#ifndef WIN32\n$_#endif\n"; + next; + } next if /#include "log.h"/; print; -- 2.43.0 From e7d1fc1a4bbd47e0d2f7d59d1ce4ccaa4fa0ab10 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 6 Nov 2007 16:27:10 +0000 Subject: [PATCH 16/16] big win32 check-in --- README.embed | 2 + ev.c | 63 ++--------------------------- ev_win32.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 114 insertions(+), 60 deletions(-) create mode 100644 ev_win32.c diff --git a/README.embed b/README.embed index 1d04427..0ab2878 100644 --- a/README.embed +++ b/README.embed @@ -27,6 +27,8 @@ FILESETS ev.c ev_vars.h ev_wrap.h + ev_win32.c + ev_select.c only when select backend is enabled (which is by default) ev_poll.c only when poll backend is enabled (disabled by default) ev_epoll.c only when the epoll backend is enabled (disabled by default) diff --git a/ev.c b/ev.c index 79b3786..630a6db 100644 --- a/ev.c +++ b/ev.c @@ -150,64 +150,7 @@ typedef struct ev_watcher_time *WT; static int have_monotonic; /* did clock_gettime (CLOCK_MONOTONIC) work? */ -#if WIN32 -/* note: the comment below could not be substantiated, but what would I care */ -/* MSDN says this is required to handle SIGFPE */ -volatile double SIGFPE_REQ = 0.0f; - -static int -ev_socketpair_tcp (int filedes [2]) -{ - struct sockaddr_in addr = { 0 }; - int addr_size = sizeof (addr); - SOCKET listener; - SOCKET sock [2] = { -1, -1 }; - - if ((listener = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) - return -1; - - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); - addr.sin_port = 0; - - if (bind (listener, (struct sockaddr *)&addr, addr_size)) - goto fail; - - if (getsockname(listener, (struct sockaddr *)&addr, &addr_size)) - goto fail; - - if (listen (listener, 1)) - goto fail; - - if ((sock [0] = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) - goto fail; - - if (connect (sock[0], (struct sockaddr *)&addr, addr_size)) - goto fail; - - if ((sock[1] = accept (listener, 0, 0)) < 0) - goto fail; - - closesocket (listener); - - filedes [0] = sock [0]; - filedes [1] = sock [1]; - - return 0; - -fail: - closesocket (listener); - - if (sock [0] != INVALID_SOCKET) closesocket (sock [0]); - if (sock [1] != INVALID_SOCKET) closesocket (sock [1]); - - return -1; -} - -# define ev_pipe(filedes) ev_socketpair_tcp (filedes) -#else -# define ev_pipe(filedes) pipe (filedes) -#endif +#include "ev_win32.c" /*****************************************************************************/ @@ -830,7 +773,7 @@ loop_fork (EV_P) close (sigpipe [0]); close (sigpipe [1]); - while (ev_pipe (sigpipe)) + while (pipe (sigpipe)) syserr ("(libev) error creating pipe"); siginit (EV_A); @@ -883,7 +826,7 @@ int ev_default_loop (int methods) { if (sigpipe [0] == sigpipe [1]) - if (ev_pipe (sigpipe)) + if (pipe (sigpipe)) return 0; if (!default_loop) diff --git a/ev_win32.c b/ev_win32.c new file mode 100644 index 0000000..5821128 --- /dev/null +++ b/ev_win32.c @@ -0,0 +1,109 @@ +/* + * libev win32 compatibility cruft + * + * Copyright (c) 2007 Marc Alexander Lehmann + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef WIN32 + +#include + +/* note: the comment below could not be substantiated, but what would I care */ +/* MSDN says this is required to handle SIGFPE */ +volatile double SIGFPE_REQ = 0.0f; + +/* oh, the humanity! */ +static int +ev_pipe (int filedes [2]) +{ + struct sockaddr_in addr = { 0 }; + int addr_size = sizeof (addr); + SOCKET listener; + SOCKET sock [2] = { -1, -1 }; + + if ((listener = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) + return -1; + + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); + addr.sin_port = 0; + + if (bind (listener, (struct sockaddr *)&addr, addr_size)) + goto fail; + + if (getsockname(listener, (struct sockaddr *)&addr, &addr_size)) + goto fail; + + if (listen (listener, 1)) + goto fail; + + if ((sock [0] = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) + goto fail; + + if (connect (sock[0], (struct sockaddr *)&addr, addr_size)) + goto fail; + + if ((sock[1] = accept (listener, 0, 0)) < 0) + goto fail; + + closesocket (listener); + + filedes [0] = sock [0]; + filedes [1] = sock [1]; + + return 0; + +fail: + closesocket (listener); + + if (sock [0] != INVALID_SOCKET) closesocket (sock [0]); + if (sock [1] != INVALID_SOCKET) closesocket (sock [1]); + + return -1; +} + +#undef pipe +#define pipe(filedes) ev_pipe (filedes) + +static int +ev_gettimeofday (struct timeval *tv, struct timezone *tz) +{ + struct _timeb tb; + + _ftime (&tb); + + tv->tv_sec = (long)tb.time; + tv->tv_usec = ((long)tb.millitm) * 1000; + + return 0; +} + +#undef gettimeofday +#define gettimeofdy(tv,tz) ev_gettimeofday (tv, tz) + +#endif -- 2.43.0