ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/EV/schmorp.h
(Generate patch)

Comparing EV/schmorp.h (file contents):
Revision 1.3 by root, Tue Jul 14 20:31:21 2009 UTC vs.
Revision 1.8 by root, Wed Apr 14 00:17:22 2010 UTC

2#define SCHMORP_PERL_H_ 2#define SCHMORP_PERL_H_
3 3
4/* WARNING 4/* WARNING
5 * This header file is a shared resource between many modules. 5 * This header file is a shared resource between many modules.
6 */ 6 */
7
8#include <signal.h>
9#include <errno.h>
10
11#ifndef _WIN32
12# include <poll.h>
13#endif
7 14
8/* useful stuff, used by schmorp mostly */ 15/* useful stuff, used by schmorp mostly */
9 16
10#include "patchlevel.h" 17#include "patchlevel.h"
11 18
13 (PERL_REVISION > (a) \ 20 (PERL_REVISION > (a) \
14 || (PERL_REVISION == (a) \ 21 || (PERL_REVISION == (a) \
15 && (PERL_VERSION > (b) \ 22 && (PERL_VERSION > (b) \
16 || (PERL_VERSION == (b) && PERL_SUBVERSION >= (c))))) 23 || (PERL_VERSION == (b) && PERL_SUBVERSION >= (c)))))
17 24
25#ifndef PERL_MAGIC_ext
26# define PERL_MAGIC_ext '~'
27#endif
28
18#if !PERL_VERSION_ATLEAST (5,6,0) 29#if !PERL_VERSION_ATLEAST (5,6,0)
19# ifndef PL_ppaddr 30# ifndef PL_ppaddr
20# define PL_ppaddr ppaddr 31# define PL_ppaddr ppaddr
21# endif 32# endif
22# ifndef call_sv 33# ifndef call_sv
187 S_GENSUB_ARG = arg; 198 S_GENSUB_ARG = arg;
188 199
189 return newRV_noinc ((SV *)cv); 200 return newRV_noinc ((SV *)cv);
190} 201}
191 202
203/*****************************************************************************/
192/** portable pipe/socketpair */ 204/* portable pipe/socketpair */
193 205
194#ifdef USE_SOCKETS_AS_HANDLES 206#ifdef USE_SOCKETS_AS_HANDLES
195# define S_TO_SOCKET(x) (win32_get_osfhandle (x)) 207# define S_TO_HANDLE(x) ((HANDLE)win32_get_osfhandle (x))
196#else 208#else
197# define S_TO_SOCKET(x) (x) 209# define S_TO_HANDLE(x) ((HANDLE)x)
198#endif 210#endif
199 211
200#ifdef _WIN32 212#ifdef _WIN32
201/* taken almost verbatim from libev's ev_win32.c */ 213/* taken almost verbatim from libev's ev_win32.c */
202/* oh, the humanity! */ 214/* oh, the humanity! */
203static int 215static int
204s_pipe (int filedes [2]) 216s_pipe (int filedes [2])
205{ 217{
218 dTHX;
219
206 struct sockaddr_in addr = { 0 }; 220 struct sockaddr_in addr = { 0 };
207 int addr_size = sizeof (addr); 221 int addr_size = sizeof (addr);
208 struct sockaddr_in adr2; 222 struct sockaddr_in adr2;
209 int adr2_size = sizeof (adr2); 223 int adr2_size = sizeof (adr2);
210 SOCKET listener; 224 SOCKET listener;
282 return -1; 296 return -1;
283} 297}
284 298
285#define s_socketpair(domain,type,protocol,filedes) s_pipe (filedes) 299#define s_socketpair(domain,type,protocol,filedes) s_pipe (filedes)
286 300
301static int
302s_fd_blocking (int fd, int blocking)
303{
304 u_long nonblocking = !blocking;
305
306 return ioctlsocket ((SOCKET)S_TO_HANDLE (fd), FIONBIO, &nonblocking);
307}
308
309#define s_fd_prepare(fd) s_fd_blocking (fd, 0)
310
287#else 311#else
288 312
289#define s_socketpair(domain,type,protocol,filedes) socketpair (domain, type, protocol, filedes) 313#define s_socketpair(domain,type,protocol,filedes) socketpair (domain, type, protocol, filedes)
290#define s_pipe(filedes) pipe (filedes) 314#define s_pipe(filedes) pipe (filedes)
291 315
316static int
317s_fd_blocking (int fd, int blocking)
318{
319 return fcntl (fd, F_SETFL, blocking ? 0 : O_NONBLOCK);
320}
321
322static int
323s_fd_prepare (int fd)
324{
325 return s_fd_blocking (fd, 0)
326 || fcntl (fd, F_SETFD, FD_CLOEXEC);
327}
328
329#endif
330
331#if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 7))
332/* our minimum requirement is glibc 2.7 which has the stub, but not the header */
333# include <stdint.h>
334# ifdef __cplusplus
335extern "C" {
292#endif 336# endif
293 337 int eventfd (unsigned int initval, int flags);
338# ifdef __cplusplus
339}
294#endif 340# endif
341#else
342# define eventfd(initval,flags) -1
343#endif
295 344
345typedef struct {
346 int fd[2]; /* read, write fd, might be equal */
347 int len; /* write length (1 pipe/socket, 8 eventfd) */
348} s_epipe;
349
350static int
351s_epipe_new (s_epipe *epp)
352{
353 s_epipe ep;
354
355 ep.fd [0] = ep.fd [1] = eventfd (0, 0);
356
357 if (ep.fd [0] >= 0)
358 {
359 s_fd_prepare (ep.fd [0]);
360 ep.len = 8;
361 }
362 else
363 {
364 if (s_pipe (ep.fd))
365 return -1;
366
367 if (s_fd_prepare (ep.fd [0])
368 || s_fd_prepare (ep.fd [1]))
369 {
370 dTHX;
371
372 close (ep.fd [0]);
373 close (ep.fd [1]);
374 return -1;
375 }
376
377 ep.len = 1;
378 }
379
380 *epp = ep;
381 return 0;
382}
383
384static void
385s_epipe_destroy (s_epipe *epp)
386{
387 dTHX;
388
389 close (epp->fd [0]);
390
391 if (epp->fd [1] != epp->fd [0])
392 close (epp->fd [1]);
393
394 epp->len = 0;
395}
396
397static void
398s_epipe_signal (s_epipe *epp)
399{
400#ifdef _WIN32
401 /* perl overrides send with a function that crashes in other threads.
402 * unfortunately, it overrides it with an argument-less macro, so
403 * there is no way to force usage of the real send function.
404 * incompetent windows programmers - is this redundant?
405 */
406 DWORD dummy;
407 WriteFile (S_TO_HANDLE (epp->fd [1]), (LPCVOID)&dummy, 1, &dummy, 0);
408#else
409 static uint64_t counter = 1;
410 /* some modules accept fd's from outside, support eventfd here */
411 if (write (epp->fd [1], &counter, epp->len) < 0
412 && errno == EINVAL
413 && epp->len != 8)
414 write (epp->fd [1], &counter, (epp->len = 8));
415#endif
416}
417
418static void
419s_epipe_drain (s_epipe *epp)
420{
421 dTHX;
422 char buf [9];
423
424#ifdef _WIN32
425 recv (epp->fd [0], buf, sizeof (buf), 0);
426#else
427 read (epp->fd [0], buf, sizeof (buf));
428#endif
429}
430
431/* like new, but dups over old */
432static int
433s_epipe_renew (s_epipe *epp)
434{
435 dTHX;
436 s_epipe epn;
437
438 if (epp->fd [1] != epp->fd [0])
439 close (epp->fd [1]);
440
441 if (s_epipe_new (&epn))
442 return -1;
443
444 if (epp->len)
445 {
446 if (dup2 (epn.fd [0], epp->fd [0]) < 0)
447 croak ("unable to dup over old event pipe"); /* should not croak */
448
449 close (epn.fd [0]);
450
451 if (epn.fd [0] == epn.fd [1])
452 epn.fd [1] = epp->fd [0];
453
454 epn.fd [0] = epp->fd [0];
455 }
456
457 *epp = epn;
458
459 return 0;
460}
461
462#define s_epipe_fd(epp) ((epp)->fd [0])
463
464static int
465s_epipe_wait (s_epipe *epp)
466{
467 dTHX;
468#ifdef _WIN32
469 fd_set rfd;
470 int fd = s_epipe_fd (epp);
471
472 FD_ZERO (&rfd);
473 FD_SET (fd, &rfd);
474
475 return PerlSock_select (fd + 1, &rfd, 0, 0, 0);
476#else
477 /* poll is preferable on posix systems */
478 struct pollfd pfd;
479
480 pfd.fd = s_epipe_fd (epp);
481 pfd.events = POLLIN;
482
483 return poll (&pfd, 1, -1);
484#endif
485}
486
487#endif
488

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines