--- IO-AIO/schmorp.h 2009/07/15 01:36:04 1.5 +++ IO-AIO/schmorp.h 2013/04/14 09:43:18 1.13 @@ -3,11 +3,17 @@ /* WARNING * This header file is a shared resource between many modules. + * perl header files MUST already be included. */ #include +#include -#ifndef _WIN32 +#if defined(WIN32 ) || defined(_MINIX) +# define SCHMORP_H_PREFER_SELECT 1 +#endif + +#if !SCHMORP_H_PREFER_SELECT # include #endif @@ -21,6 +27,10 @@ && (PERL_VERSION > (b) \ || (PERL_VERSION == (b) && PERL_SUBVERSION >= (c))))) +#ifndef PERL_MAGIC_ext +# define PERL_MAGIC_ext '~' +#endif + #if !PERL_VERSION_ATLEAST (5,6,0) # ifndef PL_ppaddr # define PL_ppaddr ppaddr @@ -42,6 +52,32 @@ # endif #endif +/* use NV for 32 bit perls as it allows larger offsets */ +#if IVSIZE >= 8 +typedef IV VAL64; +# define SvVAL64(sv) SvIV (sv) +# define newSVval64(i64) newSViv (i64) +#else +typedef NV VAL64; +# define SvVAL64(sv) SvNV (sv) +# define newSVval64(i64) newSVnv (i64) +#endif + +/* typemap for the above */ +/* +VAL64 T_VAL64 + +INPUT + +T_VAL64 + $var = ($type)SvVAL64 ($arg); + +OUTPUT + +T_VAL64 + $arg = newSVval64 ($var); +*/ + /* 5.11 */ #ifndef CxHASARGS # define CxHASARGS(cx) (cx)->blk_sub.hasargs @@ -154,7 +190,7 @@ dTHX; HV *st; GV *gvp; - + return (SV *)sv_2cv (cb_sv, &st, &gvp, 0); } @@ -195,12 +231,13 @@ return newRV_noinc ((SV *)cv); } -/** portable pipe/socketpair */ +/*****************************************************************************/ +/* portable pipe/socketpair */ #ifdef USE_SOCKETS_AS_HANDLES -# define S_TO_SOCKET(x) (win32_get_osfhandle (x)) +# define S_TO_HANDLE(x) ((HANDLE)win32_get_osfhandle (x)) #else -# define S_TO_SOCKET(x) (x) +# define S_TO_HANDLE(x) ((HANDLE)x) #endif #ifdef _WIN32 @@ -209,6 +246,8 @@ static int s_pipe (int filedes [2]) { + dTHX; + struct sockaddr_in addr = { 0 }; int addr_size = sizeof (addr); struct sockaddr_in adr2; @@ -293,9 +332,9 @@ static int s_fd_blocking (int fd, int blocking) { - blocking = !blocking; + u_long nonblocking = !blocking; - return ioctlsocket (S_TO_SOCKET (fd), FIONBIO, &blocking); + return ioctlsocket ((SOCKET)S_TO_HANDLE (fd), FIONBIO, &nonblocking); } #define s_fd_prepare(fd) s_fd_blocking (fd, 0) @@ -321,6 +360,7 @@ #endif #if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 7)) +# define SCHMORP_H_HAVE_EVENTFD 1 /* our minimum requirement is glibc 2.7 which has the stub, but not the header */ # include # ifdef __cplusplus @@ -337,7 +377,6 @@ typedef struct { int fd[2]; /* read, write fd, might be equal */ int len; /* write length (1 pipe/socket, 8 eventfd) */ - volatile sig_atomic_t sent; } s_epipe; static int @@ -360,6 +399,8 @@ if (s_fd_prepare (ep.fd [0]) || s_fd_prepare (ep.fd [1])) { + dTHX; + close (ep.fd [0]); close (ep.fd [1]); return -1; @@ -368,7 +409,6 @@ ep.len = 1; } - ep.sent = 0; *epp = ep; return 0; } @@ -376,6 +416,8 @@ static void s_epipe_destroy (s_epipe *epp) { + dTHX; + close (epp->fd [0]); if (epp->fd [1] != epp->fd [0]) @@ -387,36 +429,46 @@ static void s_epipe_signal (s_epipe *epp) { - if (epp->sent) - return; - - epp->sent = 1; #ifdef _WIN32 - send (epp->fd [1], epp, 1); + /* perl overrides send with a function that crashes in other threads. + * unfortunately, it overrides it with an argument-less macro, so + * there is no way to force usage of the real send function. + * incompetent windows programmers - is this redundant? + */ + DWORD dummy; + WriteFile (S_TO_HANDLE (epp->fd [1]), (LPCVOID)&dummy, 1, &dummy, 0); #else +# if SCHMORP_H_HAVE_EVENTFD static uint64_t counter = 1; - write (epp->fd [1], &counter, epp->len); +# else + static char counter [8]; +# endif + /* some modules accept fd's from outside, support eventfd here */ + if (write (epp->fd [1], &counter, epp->len) < 0 + && errno == EINVAL + && epp->len != 8) + write (epp->fd [1], &counter, (epp->len = 8)); #endif } static void s_epipe_drain (s_epipe *epp) { + dTHX; char buf [9]; #ifdef _WIN32 - PerlSock_recv (epp->fd [0], buf, sizeof (buf), 0); + recv (epp->fd [0], buf, sizeof (buf), 0); #else read (epp->fd [0], buf, sizeof (buf)); #endif - - epp->sent = 0; } /* like new, but dups over old */ static int s_epipe_renew (s_epipe *epp) { + dTHX; s_epipe epn; if (epp->fd [1] != epp->fd [0]) @@ -427,11 +479,13 @@ if (epp->len) { - if (dup2 (S_TO_SOCKET (epn.fd [0]), S_TO_SOCKET (epp->fd [0])) < 0) + if (dup2 (epn.fd [0], epp->fd [0]) < 0) croak ("unable to dup over old event pipe"); /* should not croak */ - if (epp->fd [1] != epp->fd [0]) - close (epn.fd [0]); + close (epn.fd [0]); + + if (epn.fd [0] == epn.fd [1]) + epn.fd [1] = epp->fd [0]; epn.fd [0] = epp->fd [0]; } @@ -446,13 +500,15 @@ static int s_epipe_wait (s_epipe *epp) { -#ifdef _WIN32 + dTHX; +#if SCHMORP_H_PREFER_SELECT fd_set rfd; + int fd = s_epipe_fd (epp); FD_ZERO (&rfd); - FD_SET (s_epipe_fd (epp), &rfd); + FD_SET (fd, &rfd); - return PerlSock_select (s_epipe_fd (epp) + 1, &rfd, 0, 0, 0); + return PerlSock_select (fd + 1, &rfd, 0, 0, 0); #else /* poll is preferable on posix systems */ struct pollfd pfd; @@ -460,7 +516,7 @@ pfd.fd = s_epipe_fd (epp); pfd.events = POLLIN; - return poll (&pfd, 1, 0); + return poll (&pfd, 1, -1); #endif }