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.12 by root, Sat Apr 6 00:05:45 2013 UTC

1#ifndef SCHMORP_PERL_H_ 1#ifndef SCHMORP_PERL_H_
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 * perl header files MUST already be included.
6 */ 7 */
8
9#include <signal.h>
10#include <errno.h>
11
12#if defined(WIN32 ) || defined(_MINIX)
13# define SCHMORP_H_PREFER_SELECT 1
14#endif
15
16#if !SCHMORP_H_PREFER_SELECT
17# include <poll.h>
18#endif
7 19
8/* useful stuff, used by schmorp mostly */ 20/* useful stuff, used by schmorp mostly */
9 21
10#include "patchlevel.h" 22#include "patchlevel.h"
11 23
13 (PERL_REVISION > (a) \ 25 (PERL_REVISION > (a) \
14 || (PERL_REVISION == (a) \ 26 || (PERL_REVISION == (a) \
15 && (PERL_VERSION > (b) \ 27 && (PERL_VERSION > (b) \
16 || (PERL_VERSION == (b) && PERL_SUBVERSION >= (c))))) 28 || (PERL_VERSION == (b) && PERL_SUBVERSION >= (c)))))
17 29
30#ifndef PERL_MAGIC_ext
31# define PERL_MAGIC_ext '~'
32#endif
33
18#if !PERL_VERSION_ATLEAST (5,6,0) 34#if !PERL_VERSION_ATLEAST (5,6,0)
19# ifndef PL_ppaddr 35# ifndef PL_ppaddr
20# define PL_ppaddr ppaddr 36# define PL_ppaddr ppaddr
21# endif 37# endif
22# ifndef call_sv 38# ifndef call_sv
33# endif 49# endif
34# ifndef IS_PADCONST 50# ifndef IS_PADCONST
35# define IS_PADCONST(v) 0 51# define IS_PADCONST(v) 0
36# endif 52# endif
37#endif 53#endif
54
55/* use NV for 32 bit perls as it allows larger offsets */
56#if IVSIZE >= 8
57typedef IV VAL64;
58# define SvVAL64(sv) SvIV (sv)
59# define newSVval64(i64) newSViv (i64)
60#else
61typedef NV VAL64;
62# define SvVAL64(sv) SvNV (sv)
63# define newSVval64(i64) newSVnv (i64)
64#endif
65
66/* typemap for the above */
67/*
68VAL64 T_VAL64
69
70INPUT
71
72T_VAL64
73 $var = ($type)SvVAL64 ($arg);
74
75OUTPUT
76
77T_VAL64
78 $arg = newSVval64 ($var);
79*/
38 80
39/* 5.11 */ 81/* 5.11 */
40#ifndef CxHASARGS 82#ifndef CxHASARGS
41# define CxHASARGS(cx) (cx)->blk_sub.hasargs 83# define CxHASARGS(cx) (cx)->blk_sub.hasargs
42#endif 84#endif
187 S_GENSUB_ARG = arg; 229 S_GENSUB_ARG = arg;
188 230
189 return newRV_noinc ((SV *)cv); 231 return newRV_noinc ((SV *)cv);
190} 232}
191 233
234/*****************************************************************************/
192/** portable pipe/socketpair */ 235/* portable pipe/socketpair */
193 236
194#ifdef USE_SOCKETS_AS_HANDLES 237#ifdef USE_SOCKETS_AS_HANDLES
195# define S_TO_SOCKET(x) (win32_get_osfhandle (x)) 238# define S_TO_HANDLE(x) ((HANDLE)win32_get_osfhandle (x))
196#else 239#else
197# define S_TO_SOCKET(x) (x) 240# define S_TO_HANDLE(x) ((HANDLE)x)
198#endif 241#endif
199 242
200#ifdef _WIN32 243#ifdef _WIN32
201/* taken almost verbatim from libev's ev_win32.c */ 244/* taken almost verbatim from libev's ev_win32.c */
202/* oh, the humanity! */ 245/* oh, the humanity! */
203static int 246static int
204s_pipe (int filedes [2]) 247s_pipe (int filedes [2])
205{ 248{
249 dTHX;
250
206 struct sockaddr_in addr = { 0 }; 251 struct sockaddr_in addr = { 0 };
207 int addr_size = sizeof (addr); 252 int addr_size = sizeof (addr);
208 struct sockaddr_in adr2; 253 struct sockaddr_in adr2;
209 int adr2_size = sizeof (adr2); 254 int adr2_size = sizeof (adr2);
210 SOCKET listener; 255 SOCKET listener;
282 return -1; 327 return -1;
283} 328}
284 329
285#define s_socketpair(domain,type,protocol,filedes) s_pipe (filedes) 330#define s_socketpair(domain,type,protocol,filedes) s_pipe (filedes)
286 331
332static int
333s_fd_blocking (int fd, int blocking)
334{
335 u_long nonblocking = !blocking;
336
337 return ioctlsocket ((SOCKET)S_TO_HANDLE (fd), FIONBIO, &nonblocking);
338}
339
340#define s_fd_prepare(fd) s_fd_blocking (fd, 0)
341
287#else 342#else
288 343
289#define s_socketpair(domain,type,protocol,filedes) socketpair (domain, type, protocol, filedes) 344#define s_socketpair(domain,type,protocol,filedes) socketpair (domain, type, protocol, filedes)
290#define s_pipe(filedes) pipe (filedes) 345#define s_pipe(filedes) pipe (filedes)
291 346
347static int
348s_fd_blocking (int fd, int blocking)
349{
350 return fcntl (fd, F_SETFL, blocking ? 0 : O_NONBLOCK);
351}
352
353static int
354s_fd_prepare (int fd)
355{
356 return s_fd_blocking (fd, 0)
357 || fcntl (fd, F_SETFD, FD_CLOEXEC);
358}
359
360#endif
361
362#if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 7))
363# define SCHMORP_H_HAVE_EVENTFD 1
364/* our minimum requirement is glibc 2.7 which has the stub, but not the header */
365# include <stdint.h>
366# ifdef __cplusplus
367extern "C" {
292#endif 368# endif
293 369 int eventfd (unsigned int initval, int flags);
370# ifdef __cplusplus
371}
294#endif 372# endif
373#else
374# define eventfd(initval,flags) -1
375#endif
295 376
377typedef struct {
378 int fd[2]; /* read, write fd, might be equal */
379 int len; /* write length (1 pipe/socket, 8 eventfd) */
380} s_epipe;
381
382static int
383s_epipe_new (s_epipe *epp)
384{
385 s_epipe ep;
386
387 ep.fd [0] = ep.fd [1] = eventfd (0, 0);
388
389 if (ep.fd [0] >= 0)
390 {
391 s_fd_prepare (ep.fd [0]);
392 ep.len = 8;
393 }
394 else
395 {
396 if (s_pipe (ep.fd))
397 return -1;
398
399 if (s_fd_prepare (ep.fd [0])
400 || s_fd_prepare (ep.fd [1]))
401 {
402 dTHX;
403
404 close (ep.fd [0]);
405 close (ep.fd [1]);
406 return -1;
407 }
408
409 ep.len = 1;
410 }
411
412 *epp = ep;
413 return 0;
414}
415
416static void
417s_epipe_destroy (s_epipe *epp)
418{
419 dTHX;
420
421 close (epp->fd [0]);
422
423 if (epp->fd [1] != epp->fd [0])
424 close (epp->fd [1]);
425
426 epp->len = 0;
427}
428
429static void
430s_epipe_signal (s_epipe *epp)
431{
432#ifdef _WIN32
433 /* perl overrides send with a function that crashes in other threads.
434 * unfortunately, it overrides it with an argument-less macro, so
435 * there is no way to force usage of the real send function.
436 * incompetent windows programmers - is this redundant?
437 */
438 DWORD dummy;
439 WriteFile (S_TO_HANDLE (epp->fd [1]), (LPCVOID)&dummy, 1, &dummy, 0);
440#else
441# if SCHMORP_H_HAVE_EVENTFD
442 static uint64_t counter = 1;
443# else
444 static char counter [8];
445# endif
446 /* some modules accept fd's from outside, support eventfd here */
447 if (write (epp->fd [1], &counter, epp->len) < 0
448 && errno == EINVAL
449 && epp->len != 8)
450 write (epp->fd [1], &counter, (epp->len = 8));
451#endif
452}
453
454static void
455s_epipe_drain (s_epipe *epp)
456{
457 dTHX;
458 char buf [9];
459
460#ifdef _WIN32
461 recv (epp->fd [0], buf, sizeof (buf), 0);
462#else
463 read (epp->fd [0], buf, sizeof (buf));
464#endif
465}
466
467/* like new, but dups over old */
468static int
469s_epipe_renew (s_epipe *epp)
470{
471 dTHX;
472 s_epipe epn;
473
474 if (epp->fd [1] != epp->fd [0])
475 close (epp->fd [1]);
476
477 if (s_epipe_new (&epn))
478 return -1;
479
480 if (epp->len)
481 {
482 if (dup2 (epn.fd [0], epp->fd [0]) < 0)
483 croak ("unable to dup over old event pipe"); /* should not croak */
484
485 close (epn.fd [0]);
486
487 if (epn.fd [0] == epn.fd [1])
488 epn.fd [1] = epp->fd [0];
489
490 epn.fd [0] = epp->fd [0];
491 }
492
493 *epp = epn;
494
495 return 0;
496}
497
498#define s_epipe_fd(epp) ((epp)->fd [0])
499
500static int
501s_epipe_wait (s_epipe *epp)
502{
503 dTHX;
504#if SCHMORP_H_PREFER_SELECT
505 fd_set rfd;
506 int fd = s_epipe_fd (epp);
507
508 FD_ZERO (&rfd);
509 FD_SET (fd, &rfd);
510
511 return PerlSock_select (fd + 1, &rfd, 0, 0, 0);
512#else
513 /* poll is preferable on posix systems */
514 struct pollfd pfd;
515
516 pfd.fd = s_epipe_fd (epp);
517 pfd.events = POLLIN;
518
519 return poll (&pfd, 1, -1);
520#endif
521}
522
523#endif
524

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines