rewrite seletc backend, port again to msvc

This commit is contained in:
Marc Alexander Lehmann 2007-11-12 00:31:08 +00:00
parent 3946a5f77a
commit e0a4b97e57
6 changed files with 187 additions and 177 deletions

108
ev.c
View File

@ -77,11 +77,18 @@ extern "C" {
#include <signal.h>
#ifndef WIN32
#ifndef _WIN32
# include <unistd.h>
# include <sys/time.h>
# include <sys/wait.h>
#else
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# ifndef EV_SELECT_IS_WINSOCKET
# define EV_SELECT_IS_WINSOCKET 1
# endif
#endif
/**/
#ifndef EV_USE_MONOTONIC
@ -104,16 +111,6 @@ extern "C" {
# define EV_USE_KQUEUE 0
#endif
#ifndef EV_USE_WIN32
# ifdef WIN32
# 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
#endif
#ifndef EV_USE_REALTIME
# define EV_USE_REALTIME 1
#endif
@ -130,6 +127,10 @@ extern "C" {
# define EV_USE_REALTIME 0
#endif
#if EV_SELECT_IS_WINSOCKET
# include <winsock.h>
#endif
/**/
#define MIN_TIMEJUMP 1. /* minimum timejump that gets detected (if monotonic clock available) */
@ -157,13 +158,15 @@ extern "C" {
#define NUMPRI (EV_MAXPRI - EV_MINPRI + 1)
#define ABSPRI(w) ((w)->priority - EV_MINPRI)
#define EMPTY /* required for microsofts broken pseudo-c compiler */
typedef struct ev_watcher *W;
typedef struct ev_watcher_list *WL;
typedef struct ev_watcher_time *WT;
static int have_monotonic; /* did clock_gettime (CLOCK_MONOTONIC) work? */
#ifdef WIN32
#ifdef _WIN32
# include "ev_win32.c"
#endif
@ -222,6 +225,9 @@ typedef struct
WL head;
unsigned char events;
unsigned char reify;
#if EV_SELECT_IS_WINSOCKET
SOCKET handle;
#endif
} ANFD;
typedef struct
@ -320,11 +326,6 @@ 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;
@ -408,6 +409,15 @@ fd_reify (EV_P)
for (w = (struct ev_io *)anfd->head; w; w = (struct ev_io *)((WL)w)->next)
events |= w->events;
#if EV_SELECT_IS_WINSOCKET
if (events)
{
unsigned long argp;
anfd->handle = _get_osfhandle (fd);
assert (("libev only supports socket fds in this configuration", ioctlsocket (anfd->handle, FIONREAD, &argp) == 0));
}
#endif
anfd->reify = 0;
method_modify (EV_A_ fd, anfd->events, events);
@ -445,8 +455,8 @@ fd_kill (EV_P_ int fd)
static int
fd_valid (int fd)
{
#ifdef WIN32
return !!win32_get_osfhandle (fd);
#ifdef _WIN32
return _get_osfhandle (fd) != -1;
#else
return fcntl (fd, F_GETFD) != -1;
#endif
@ -573,7 +583,7 @@ signals_init (ANSIG *base, int count)
static void
sighandler (int signum)
{
#if WIN32
#if _WIN32
signal (signum, sighandler);
#endif
@ -583,11 +593,7 @@ sighandler (int signum)
{
int old_errno = errno;
gotsig = 1;
#ifdef WIN32
send (sigpipe [1], &signum, 1, MSG_DONTWAIT);
#else
write (sigpipe [1], &signum, 1);
#endif
errno = old_errno;
}
}
@ -617,11 +623,7 @@ sigcb (EV_P_ struct ev_io *iow, int revents)
{
int signum;
#ifdef WIN32
recv (sigpipe [0], &revents, 1, MSG_DONTWAIT);
#else
read (sigpipe [0], &revents, 1);
#endif
gotsig = 0;
for (signum = signalmax; signum--; )
@ -629,17 +631,23 @@ sigcb (EV_P_ struct ev_io *iow, int revents)
ev_feed_signal_event (EV_A_ signum + 1);
}
inline void
fd_intern (int fd)
{
#ifdef _WIN32
int arg = 1;
ioctlsocket (_get_osfhandle (fd), FIONBIO, &arg);
#else
fcntl (fd, F_SETFD, FD_CLOEXEC);
fcntl (fd, F_SETFL, O_NONBLOCK);
#endif
}
static void
siginit (EV_P)
{
#ifndef WIN32
fcntl (sigpipe [0], F_SETFD, FD_CLOEXEC);
fcntl (sigpipe [1], F_SETFD, FD_CLOEXEC);
/* rather than sort out wether we really need nb, set it */
fcntl (sigpipe [0], F_SETFL, O_NONBLOCK);
fcntl (sigpipe [1], F_SETFL, O_NONBLOCK);
#endif
fd_intern (sigpipe [0]);
fd_intern (sigpipe [1]);
ev_io_set (&sigev, sigpipe [0], EV_READ);
ev_io_start (EV_A_ &sigev);
@ -650,7 +658,7 @@ siginit (EV_P)
static struct ev_child *childs [PID_HASHSIZE];
#ifndef WIN32
#ifndef _WIN32
static struct ev_signal childev;
@ -721,7 +729,7 @@ ev_version_minor (void)
static int
enable_secure (void)
{
#ifdef WIN32
#ifdef _WIN32
return 0;
#else
return getuid () != geteuid ()
@ -760,9 +768,6 @@ loop_init (EV_P_ int methods)
methods = EVMETHOD_ANY;
method = 0;
#if EV_USE_WIN32
if (!method && (methods & EVMETHOD_WIN32 )) method = win32_init (EV_A_ methods);
#endif
#if EV_USE_KQUEUE
if (!method && (methods & EVMETHOD_KQUEUE)) method = kqueue_init (EV_A_ methods);
#endif
@ -786,9 +791,6 @@ loop_destroy (EV_P)
{
int i;
#if EV_USE_WIN32
if (method == EVMETHOD_WIN32 ) win32_destroy (EV_A);
#endif
#if EV_USE_KQUEUE
if (method == EVMETHOD_KQUEUE) kqueue_destroy (EV_A);
#endif
@ -806,14 +808,14 @@ loop_destroy (EV_P)
array_free (pending, [i]);
/* have to use the microsoft-never-gets-it-right macro */
array_free_microshit (fdchange);
array_free_microshit (timer);
array_free (fdchange, EMPTY);
array_free (timer, EMPTY);
#if EV_PERIODICS
array_free_microshit (periodic);
array_free (periodic, EMPTY);
#endif
array_free_microshit (idle);
array_free_microshit (prepare);
array_free_microshit (check);
array_free (idle, EMPTY);
array_free (prepare, EMPTY);
array_free (check, EMPTY);
method = 0;
}
@ -902,7 +904,7 @@ ev_default_loop (int methods)
{
siginit (EV_A);
#ifndef WIN32
#ifndef _WIN32
ev_signal_init (&childev, childcb, SIGCHLD);
ev_set_priority (&childev, EV_MAXPRI);
ev_signal_start (EV_A_ &childev);
@ -923,7 +925,7 @@ ev_default_destroy (void)
struct ev_loop *loop = default_loop;
#endif
#ifndef WIN32
#ifndef _WIN32
ev_ref (EV_A); /* child watcher */
ev_signal_stop (EV_A_ &childev);
#endif
@ -1513,7 +1515,7 @@ ev_signal_start (EV_P_ struct ev_signal *w)
if (!((WL)w)->next)
{
#if WIN32
#if _WIN32
signal (w->signum, sighandler);
#else
struct sigaction sa;

36
ev.h
View File

@ -86,7 +86,7 @@ struct ev_loop;
/* can be used to add custom fields to all watchers, while losing binary compatibility */
#ifndef EV_COMMON
# define EV_COMMON void *data
# define EV_COMMON void *data;
#endif
#ifndef EV_PROTOTYPES
# define EV_PROTOTYPES 1
@ -114,40 +114,40 @@ struct ev_loop;
int active; /* private */ \
int pending; /* private */ \
int priority; /* private */ \
EV_COMMON; /* rw */ \
EV_COMMON /* rw */ \
EV_CB_DECLARE (type) /* private */
#define EV_WATCHER_LIST(type) \
EV_WATCHER (type); \
struct ev_watcher_list *next /* private */
EV_WATCHER (type) \
struct ev_watcher_list *next; /* private */
#define EV_WATCHER_TIME(type) \
EV_WATCHER (type); \
ev_tstamp at /* private */
EV_WATCHER (type) \
ev_tstamp at; /* private */
/* base class, nothing to see here unless you subclass */
struct ev_watcher
{
EV_WATCHER (ev_watcher);
EV_WATCHER (ev_watcher)
};
/* base class, nothing to see here unless you subclass */
struct ev_watcher_list
{
EV_WATCHER_LIST (ev_watcher_list);
EV_WATCHER_LIST (ev_watcher_list)
};
/* base class, nothing to see here unless you subclass */
struct ev_watcher_time
{
EV_WATCHER_TIME (ev_watcher_time);
EV_WATCHER_TIME (ev_watcher_time)
};
/* invoked after a specific time, repeatable (based on monotonic clock) */
/* revent EV_TIMEOUT */
struct ev_timer
{
EV_WATCHER_TIME (ev_timer);
EV_WATCHER_TIME (ev_timer)
ev_tstamp repeat; /* rw */
};
@ -156,7 +156,7 @@ struct ev_timer
/* revent EV_PERIODIC */
struct ev_periodic
{
EV_WATCHER_TIME (ev_periodic);
EV_WATCHER_TIME (ev_periodic)
ev_tstamp interval; /* rw */
ev_tstamp (*reschedule_cb)(struct ev_periodic *w, ev_tstamp now); /* rw */
@ -166,7 +166,7 @@ struct ev_periodic
/* revent EV_READ, EV_WRITE */
struct ev_io
{
EV_WATCHER_LIST (ev_io);
EV_WATCHER_LIST (ev_io)
int fd; /* ro */
int events; /* ro */
@ -176,7 +176,7 @@ struct ev_io
/* revent EV_SIGNAL */
struct ev_signal
{
EV_WATCHER_LIST (ev_signal);
EV_WATCHER_LIST (ev_signal)
int signum; /* ro */
};
@ -185,7 +185,7 @@ struct ev_signal
/* revent EV_IDLE */
struct ev_idle
{
EV_WATCHER (ev_idle);
EV_WATCHER (ev_idle)
};
/* invoked for each run of the mainloop, just before the blocking call */
@ -193,14 +193,14 @@ struct ev_idle
/* revent EV_PREPARE */
struct ev_prepare
{
EV_WATCHER (ev_prepare);
EV_WATCHER (ev_prepare)
};
/* invoked for each run of the mainloop, just after the blocking call */
/* revent EV_CHECK */
struct ev_check
{
EV_WATCHER (ev_check);
EV_WATCHER (ev_check)
};
/* invoked when sigchld is received and waitpid indicates the givne pid */
@ -208,7 +208,7 @@ struct ev_check
/* does not support priorities */
struct ev_child
{
EV_WATCHER_LIST (ev_child);
EV_WATCHER_LIST (ev_child)
int pid; /* ro */
int rpid; /* rw, holds the received pid */
@ -278,7 +278,7 @@ ev_tstamp ev_now (EV_P); /* time w.r.t. timers and the eventloop, updated after
int ev_default_loop (int methods); /* returns true when successful */
static ev_tstamp
ev_now ()
ev_now (void)
{
extern ev_tstamp ev_rt_now;

View File

@ -29,20 +29,33 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _WIN32
/* for unix systems */
#if WIN32
typedef unsigned int uint32_t;
# ifndef EV_SELECT_USE_FD_SET
# define EV_SELECT_USE_FD_SET 1
# endif
#else
# include <sys/select.h>
# include <inttypes.h>
#endif
#if EV_SELECT_USE_WIN32_HANDLES
#ifndef EV_SELECT_USE_FD_SET
# ifdef NFDBITS
# define EV_SELECT_USE_FD_SET 0
# else
# define EV_SELECT_USE_FD_SET 1
# endif
#endif
#if EV_SELECT_IS_WINSOCKET
# undef EV_SELECT_USE_FD_SET
# define EV_SELECT_USE_FD_SET 1
# undef EINTR
# define EINTR WSAEINTR
# undef EBADF
# define EBADF WSAENOTSOCK
# undef ENOMEM
# define ENOMEM (errno + 1)
#endif
#if !EV_SELECT_USE_FD_SET
# define NFDBYTES (NFDBITS / 8)
#endif
#include <string.h>
@ -53,78 +66,79 @@ select_modify (EV_P_ int fd, int oev, int nev)
if (oev == nev)
return;
#if EV_SELECT_USE_FD_SET
# if EV_SELECT_USE_WIN32_HANDLES
fd = _get_osfhandle (fd);
if (fd < 0)
return;
# endif
if (nev & EV_READ)
FD_SET (fd, (struct fd_set *)vec_ri);
else
FD_CLR (fd, (struct fd_set *)vec_ri);
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 EV_SELECT_USE_FD_SET
if (vec_max < (fd >> 5) + 1)
#if EV_SELECT_IS_WINSOCKET
SOCKET handle = anfds [fd].handle;
#else
int handle = fd;
#endif
if (nev & EV_READ)
FD_SET (handle, (fd_set *)vec_ri);
else
FD_CLR (handle, (fd_set *)vec_ri);
if (nev & EV_WRITE)
FD_SET (handle, (fd_set *)vec_wi);
else
FD_CLR (handle, (fd_set *)vec_wi);
#else
int word = fd / NFDBITS;
int mask = 1UL << (fd % NFDBITS);
if (vec_max < word + 1)
{
int new_max = (fd >> 5) + 1;
int new_max = word + 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 */
vec_ri = ev_realloc (vec_ri, new_max * NFDBYTES);
vec_ro = ev_realloc (vec_ro, new_max * NFDBYTES); /* could free/malloc */
vec_wi = ev_realloc (vec_wi, new_max * NFDBYTES);
vec_wo = ev_realloc (vec_wo, new_max * NFDBYTES); /* could free/malloc */
for (; vec_max < new_max; ++vec_max)
((uint32_t *)vec_ri)[vec_max] =
((uint32_t *)vec_wi)[vec_max] = 0;
((fd_mask *)vec_ri)[vec_max] =
((fd_mask *)vec_wi)[vec_max] = 0;
}
vec_ri [offs] |= mask;
((fd_mask *)vec_ri) [word] |= mask;
if (!(nev & EV_READ))
vec_ri [offs] &= ~mask;
((fd_mask *)vec_ri) [word] &= ~mask;
vec_wi [offs] |= mask;
((fd_mask *)vec_wi) [word] |= mask;
if (!(nev & EV_WRITE))
vec_wi [offs] &= ~mask;
}
((fd_mask *)vec_wi) [word] &= ~mask;
#endif
}
}
static void
select_poll (EV_P_ ev_tstamp timeout)
{
int word, offs;
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));
memcpy (vec_ro, vec_ri, sizeof (fd_set));
memcpy (vec_wo, vec_wi, sizeof (fd_set));
#else
memcpy (vec_ro, vec_ri, vec_max * 4);
memcpy (vec_wo, vec_wi, vec_max * 4);
memcpy (vec_ro, vec_ri, vec_max * NFDBYTES);
memcpy (vec_wo, vec_wi, vec_max * NFDBYTES);
#endif
tv.tv_sec = (long)timeout;
tv.tv_usec = (long)((timeout - (ev_tstamp)tv.tv_sec) * 1e6);
res = select (vec_max * 32, (fd_set *)vec_ro, (fd_set *)vec_wo, 0, &tv);
res = select (vec_max * NFDBITS, (fd_set *)vec_ro, (fd_set *)vec_wo, 0, &tv);
if (res < 0)
{
#ifdef WIN32
if (errno == WSAEINTR ) errno = EINTR;
if (errno == WSAENOTSOCK) errno = EBADF;
#endif
#if EV_SELECT_IS_WINSOCKET
errno = WSAGetLastError ();
#endif
if (errno == EBADF)
fd_ebadf (EV_A);
@ -137,59 +151,52 @@ select_poll (EV_P_ ev_tstamp timeout)
}
#if EV_SELECT_USE_FD_SET
# if EV_SELECT_USE_WIN32_HANDLES
for (word = 0; word < anfdmax; ++word)
{
if (!anfd [word].events)
{
int fd = _get_osfhandle (word);
if (fd >= 0)
{
int fd;
for (fd = 0; fd < anfdmax; ++fd)
if (anfds [fd].events)
{
int events = 0;
#if EV_SELECT_IS_WINSOCKET
SOCKET handle = anfds [fd].handle;
#else
int handle = fd;
#endif
if (FD_ISSET (handle, (fd_set *)vec_ro)) events |= EV_READ;
if (FD_ISSET (handle, (fd_set *)vec_wo)) events |= EV_WRITE;
if (events)
fd_event (EV_A_ fd, events);
}
}
#else
{
int word, bit;
for (word = vec_max; word--; )
{
fd_mask word_r = ((fd_mask *)vec_ro) [word];
fd_mask word_w = ((fd_mask *)vec_wo) [word];
if (word_r || word_w)
for (bit = NFDBITS; bit--; )
{
fd_mask mask = 1UL << bit;
int events = 0;
if (FD_ISSET (fd, (struct fd_set *)vec_ro)) events |= EV_READ;
if (FD_ISSET (fd, (struct fd_set *)vec_wo)) events |= EV_WRITE;
events |= word_r & mask ? EV_READ : 0;
events |= word_w & mask ? EV_WRITE : 0;
if (events)
fd_event (EV_A_ word, events);
fd_event (EV_A_ word * NFDBITS + bit, events);
}
}
}
# else
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);
}
# endif
#else
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);
}
}
}
#endif
}
@ -202,10 +209,10 @@ select_init (EV_P_ int flags)
#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));
vec_ri = ev_malloc (sizeof (fd_set)); FD_ZERO ((fd_set *)vec_ri);
vec_ro = ev_malloc (sizeof (fd_set));
vec_wi = ev_malloc (sizeof (fd_set)); FD_ZERO ((fd_set *)vec_wi);
vec_wo = ev_malloc (sizeof (fd_set));
#else
vec_max = 0;
vec_ri = 0;

View File

@ -13,10 +13,10 @@ 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
VARx(unsigned char *, vec_ri)
VARx(unsigned char *, vec_ro)
VARx(unsigned char *, vec_wi)
VARx(unsigned char *, vec_wo)
VARx(void *, vec_ri)
VARx(void *, vec_ro)
VARx(void *, vec_wi)
VARx(void *, vec_wo)
VARx(int, vec_max)
#endif

View File

@ -29,7 +29,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef WIN32
#ifdef _WIN32
#include <sys/timeb.h>
@ -104,6 +104,7 @@ ev_gettimeofday (struct timeval *tv, struct timezone *tz)
}
#undef gettimeofday
#define gettimeofdy(tv,tz) ev_gettimeofday (tv, tz)
#define gettimeofday(tv,tz) ev_gettimeofday (tv, tz)
#endif

View File

@ -141,7 +141,7 @@ x_cb (struct event *ev, int revents)
revents &= EV_READ | EV_WRITE | EV_TIMEOUT | EV_SIGNAL;
ev->ev_res = revents;
ev->ev_callback (ev->ev_fd, revents, ev->ev_arg);
ev->ev_callback (ev->ev_fd, (short)revents, ev->ev_arg);
}
static void
@ -358,7 +358,7 @@ x_once_cb (int revents, void *arg)
{
struct x_once *once = (struct x_once *)arg;
once->cb (once->fd, revents, once->arg);
once->cb (once->fd, (short)revents, once->arg);
free (once);
}