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

Comparing EV/schmorp.h (file contents):
Revision 1.4 by root, Wed Jul 15 16:58:53 2009 UTC vs.
Revision 1.15 by root, Tue Apr 17 17:52:31 2018 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 */
7 8
8#include <signal.h> 9#include <signal.h>
10#include <errno.h>
9 11
10#ifndef _WIN32 12#if defined(WIN32 ) || defined(_MINIX)
13# define SCHMORP_H_PREFER_SELECT 1
14#endif
15
16#if !SCHMORP_H_PREFER_SELECT
11# include <poll.h> 17# include <poll.h>
12#endif 18#endif
13 19
14/* useful stuff, used by schmorp mostly */ 20/* useful stuff, used by schmorp mostly */
15 21
19 (PERL_REVISION > (a) \ 25 (PERL_REVISION > (a) \
20 || (PERL_REVISION == (a) \ 26 || (PERL_REVISION == (a) \
21 && (PERL_VERSION > (b) \ 27 && (PERL_VERSION > (b) \
22 || (PERL_VERSION == (b) && PERL_SUBVERSION >= (c))))) 28 || (PERL_VERSION == (b) && PERL_SUBVERSION >= (c)))))
23 29
30#ifndef PERL_MAGIC_ext
31# define PERL_MAGIC_ext '~'
32#endif
33
24#if !PERL_VERSION_ATLEAST (5,6,0) 34#if !PERL_VERSION_ATLEAST (5,6,0)
25# ifndef PL_ppaddr 35# ifndef PL_ppaddr
26# define PL_ppaddr ppaddr 36# define PL_ppaddr ppaddr
27# endif 37# endif
28# ifndef call_sv 38# ifndef call_sv
39# endif 49# endif
40# ifndef IS_PADCONST 50# ifndef IS_PADCONST
41# define IS_PADCONST(v) 0 51# define IS_PADCONST(v) 0
42# endif 52# endif
43#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*/
44 80
45/* 5.11 */ 81/* 5.11 */
46#ifndef CxHASARGS 82#ifndef CxHASARGS
47# define CxHASARGS(cx) (cx)->blk_sub.hasargs 83# define CxHASARGS(cx) (cx)->blk_sub.hasargs
48#endif 84#endif
152s_get_cv (SV *cb_sv) 188s_get_cv (SV *cb_sv)
153{ 189{
154 dTHX; 190 dTHX;
155 HV *st; 191 HV *st;
156 GV *gvp; 192 GV *gvp;
157 193
158 return (SV *)sv_2cv (cb_sv, &st, &gvp, 0); 194 return (SV *)sv_2cv (cb_sv, &st, &gvp, 0);
159} 195}
160 196
161static SV * 197static SV *
162s_get_cv_croak (SV *cb_sv) 198s_get_cv_croak (SV *cb_sv)
196} 232}
197 233
198/*****************************************************************************/ 234/*****************************************************************************/
199/* portable pipe/socketpair */ 235/* portable pipe/socketpair */
200 236
201#ifdef USE_SOCKETS_AS_HANDLES 237#if defined(USE_SOCKETS_AS_HANDLES) || PERL_VERSION_ATLEAST(5,18,0)
202# define S_TO_HANDLE(x) ((HANDLE)win32_get_osfhandle (x)) 238# define S_TO_HANDLE(x) ((HANDLE)win32_get_osfhandle (x))
203#else 239#else
204# define S_TO_HANDLE(x) ((HANDLE)x) 240# define S_TO_HANDLE(x) ((HANDLE)x)
205#endif 241#endif
206 242
208/* taken almost verbatim from libev's ev_win32.c */ 244/* taken almost verbatim from libev's ev_win32.c */
209/* oh, the humanity! */ 245/* oh, the humanity! */
210static int 246static int
211s_pipe (int filedes [2]) 247s_pipe (int filedes [2])
212{ 248{
249 dTHX;
250
213 struct sockaddr_in addr = { 0 }; 251 struct sockaddr_in addr = { 0 };
214 int addr_size = sizeof (addr); 252 int addr_size = sizeof (addr);
215 struct sockaddr_in adr2; 253 struct sockaddr_in adr2;
216 int adr2_size = sizeof (adr2); 254 int adr2_size = sizeof (adr2);
217 SOCKET listener; 255 SOCKET listener;
218 SOCKET sock [2] = { -1, -1 }; 256 SOCKET sock [2] = { -1, -1 };
219 257
220 if ((listener = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) 258 if ((listener = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
221 return -1; 259 return -1;
222 260
223 addr.sin_family = AF_INET; 261 addr.sin_family = AF_INET;
224 addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); 262 addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
225 addr.sin_port = 0; 263 addr.sin_port = 0;
231 goto fail; 269 goto fail;
232 270
233 if (listen (listener, 1)) 271 if (listen (listener, 1))
234 goto fail; 272 goto fail;
235 273
236 if ((sock [0] = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) 274 if ((sock [0] = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
237 goto fail; 275 goto fail;
238 276
239 if (connect (sock [0], (struct sockaddr *)&addr, addr_size)) 277 if (connect (sock [0], (struct sockaddr *)&addr, addr_size))
240 goto fail; 278 goto fail;
241 279
266 || addr.sin_port != adr2.sin_port) 304 || addr.sin_port != adr2.sin_port)
267 goto fail; 305 goto fail;
268 306
269 closesocket (listener); 307 closesocket (listener);
270 308
271#ifdef USE_SOCKETS_AS_HANDLES 309#if defined(USE_SOCKETS_AS_HANDLES) || PERL_VERSION_ATLEAST(5,18,0)
272 /* when select isn't winsocket, we also expect socket, connect, accept etc. 310 /* when select isn't winsocket, we also expect socket, connect, accept etc.
273 * to work on fds */ 311 * to work on fds */
274 filedes [0] = sock [0]; 312 filedes [0] = sock [0];
275 filedes [1] = sock [1]; 313 filedes [1] = sock [1];
276#else 314#else
319 || fcntl (fd, F_SETFD, FD_CLOEXEC); 357 || fcntl (fd, F_SETFD, FD_CLOEXEC);
320} 358}
321 359
322#endif 360#endif
323 361
362#if HAVE_EVENTFD
363# include <sys/eventfd.h>
364#else
324#if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 7)) 365# if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 7))
366# define SCHMORP_H_HAVE_EVENTFD 1
325/* our minimum requirement is glibc 2.7 which has the stub, but not the header */ 367/* our minimum requirement is glibc 2.7 which has the stub, but not the header */
326# include <stdint.h> 368# include <stdint.h>
327# ifdef __cplusplus 369# ifdef __cplusplus
328extern "C" { 370extern "C" {
329# endif 371# endif
330 int eventfd (unsigned int initval, int flags); 372 int eventfd (unsigned int initval, int flags);
331# ifdef __cplusplus 373# ifdef __cplusplus
332} 374}
333# endif 375# endif
334#else 376# else
335# define eventfd(initval,flags) -1 377# define eventfd(initval,flags) -1
378# endif
336#endif 379#endif
337 380
338typedef struct { 381typedef struct {
339 int fd[2]; /* read, write fd, might be equal */ 382 int fd[2]; /* read, write fd, might be equal */
340 int len; /* write length (1 pipe/socket, 8 eventfd) */ 383 int len; /* write length (1 pipe/socket, 8 eventfd) */
341 volatile sig_atomic_t sent;
342} s_epipe; 384} s_epipe;
343 385
344static int 386static int
345s_epipe_new (s_epipe *epp) 387s_epipe_new (s_epipe *epp)
346{ 388{
359 return -1; 401 return -1;
360 402
361 if (s_fd_prepare (ep.fd [0]) 403 if (s_fd_prepare (ep.fd [0])
362 || s_fd_prepare (ep.fd [1])) 404 || s_fd_prepare (ep.fd [1]))
363 { 405 {
406 dTHX;
407
364 close (ep.fd [0]); 408 close (ep.fd [0]);
365 close (ep.fd [1]); 409 close (ep.fd [1]);
366 return -1; 410 return -1;
367 } 411 }
368 412
369 ep.len = 1; 413 ep.len = 1;
370 } 414 }
371 415
372 ep.sent = 0;
373 *epp = ep; 416 *epp = ep;
374 return 0; 417 return 0;
375} 418}
376 419
377static void 420static void
378s_epipe_destroy (s_epipe *epp) 421s_epipe_destroy (s_epipe *epp)
379{ 422{
423 dTHX;
424
380 close (epp->fd [0]); 425 close (epp->fd [0]);
381 426
382 if (epp->fd [1] != epp->fd [0]) 427 if (epp->fd [1] != epp->fd [0])
383 close (epp->fd [1]); 428 close (epp->fd [1]);
384 429
386} 431}
387 432
388static void 433static void
389s_epipe_signal (s_epipe *epp) 434s_epipe_signal (s_epipe *epp)
390{ 435{
391 if (epp->sent)
392 return;
393
394 epp->sent = 1;
395 {
396#ifdef _WIN32 436#ifdef _WIN32
397 /* perl overrides send with a function that crashes in other threads. 437 /* perl overrides send with a function that crashes in other threads.
398 * unfortunately, it overrides it with an argument-less macro, so 438 * unfortunately, it overrides it with an argument-less macro, so
399 * there is no way to force usage of the real send function. 439 * there is no way to force usage of the real send function.
400 * incompetent windows programmers - is this redundant? 440 * incompetent windows programmers - is this redundant?
401 */ 441 */
402 DWORD dummy; 442 DWORD dummy;
403 WriteFile (S_TO_HANDLE (epp->fd [1]), (LPCVOID)&dummy, 1, &dummy, 0); 443 WriteFile (S_TO_HANDLE (epp->fd [1]), (LPCVOID)&dummy, 1, &dummy, 0);
404#else 444#else
405 static uint64_t counter = 1; 445 static uint64_t counter = 1;
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)
406 write (epp->fd [1], &counter, epp->len); 450 write (epp->fd [1], &counter, (epp->len = 8));
407#endif 451#endif
408 }
409} 452}
410 453
411static void 454static void
412s_epipe_drain (s_epipe *epp) 455s_epipe_drain (s_epipe *epp)
413{ 456{
457 dTHX;
414 char buf [9]; 458 char buf [9];
415 459
416#ifdef _WIN32 460#ifdef _WIN32
417 recv (epp->fd [0], buf, sizeof (buf), 0); 461 recv (epp->fd [0], buf, sizeof (buf), 0);
418#else 462#else
419 read (epp->fd [0], buf, sizeof (buf)); 463 read (epp->fd [0], buf, sizeof (buf));
420#endif 464#endif
421
422 epp->sent = 0;
423} 465}
424 466
425/* like new, but dups over old */ 467/* like new, but dups over old */
426static int 468static int
427s_epipe_renew (s_epipe *epp) 469s_epipe_renew (s_epipe *epp)
428{ 470{
471 dTHX;
429 s_epipe epn; 472 s_epipe epn;
430 473
431 if (epp->fd [1] != epp->fd [0]) 474 if (epp->fd [1] != epp->fd [0])
432 close (epp->fd [1]); 475 close (epp->fd [1]);
433 476
437 if (epp->len) 480 if (epp->len)
438 { 481 {
439 if (dup2 (epn.fd [0], epp->fd [0]) < 0) 482 if (dup2 (epn.fd [0], epp->fd [0]) < 0)
440 croak ("unable to dup over old event pipe"); /* should not croak */ 483 croak ("unable to dup over old event pipe"); /* should not croak */
441 484
442 if (epp->fd [1] != epp->fd [0])
443 close (epn.fd [0]); 485 close (epn.fd [0]);
486
487 if (epn.fd [0] == epn.fd [1])
488 epn.fd [1] = epp->fd [0];
444 489
445 epn.fd [0] = epp->fd [0]; 490 epn.fd [0] = epp->fd [0];
446 } 491 }
447 492
448 *epp = epn; 493 *epp = epn;
453#define s_epipe_fd(epp) ((epp)->fd [0]) 498#define s_epipe_fd(epp) ((epp)->fd [0])
454 499
455static int 500static int
456s_epipe_wait (s_epipe *epp) 501s_epipe_wait (s_epipe *epp)
457{ 502{
458#ifdef _WIN32 503 dTHX;
504#if SCHMORP_H_PREFER_SELECT
459 fd_set rfd; 505 fd_set rfd;
460 int fd = s_epipe_fd (epp); 506 int fd = s_epipe_fd (epp);
461 507
462 FD_ZERO (&rfd); 508 FD_ZERO (&rfd);
463 FD_SET (fd, &rfd); 509 FD_SET (fd, &rfd);
468 struct pollfd pfd; 514 struct pollfd pfd;
469 515
470 pfd.fd = s_epipe_fd (epp); 516 pfd.fd = s_epipe_fd (epp);
471 pfd.events = POLLIN; 517 pfd.events = POLLIN;
472 518
473 return poll (&pfd, 1, 0); 519 return poll (&pfd, 1, -1);
474#endif 520#endif
475} 521}
476 522
477#endif 523#endif
478 524

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines