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.16 by root, Tue Nov 19 13:08:54 2019 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# define sv_setval64(sv,i64) sv_setiv ((sv), (i64))
61#else
62typedef NV VAL64;
63# define SvVAL64(sv) SvNV (sv)
64# define newSVval64(i64) newSVnv (i64)
65# define sv_setval64(sv,i64) sv_setnv ((sv), (i64))
66#endif
67
68/* typemap for the above */
69/*
70VAL64 T_VAL64
71
72INPUT
73
74T_VAL64
75 $var = ($type)SvVAL64 ($arg);
76
77OUTPUT
78
79T_VAL64
80 $arg = newSVval64 ($var);
81*/
38 82
39/* 5.11 */ 83/* 5.11 */
40#ifndef CxHASARGS 84#ifndef CxHASARGS
41# define CxHASARGS(cx) (cx)->blk_sub.hasargs 85# define CxHASARGS(cx) (cx)->blk_sub.hasargs
42#endif 86#endif
146s_get_cv (SV *cb_sv) 190s_get_cv (SV *cb_sv)
147{ 191{
148 dTHX; 192 dTHX;
149 HV *st; 193 HV *st;
150 GV *gvp; 194 GV *gvp;
151 195
152 return (SV *)sv_2cv (cb_sv, &st, &gvp, 0); 196 return (SV *)sv_2cv (cb_sv, &st, &gvp, 0);
153} 197}
154 198
155static SV * 199static SV *
156s_get_cv_croak (SV *cb_sv) 200s_get_cv_croak (SV *cb_sv)
187 S_GENSUB_ARG = arg; 231 S_GENSUB_ARG = arg;
188 232
189 return newRV_noinc ((SV *)cv); 233 return newRV_noinc ((SV *)cv);
190} 234}
191 235
236/*****************************************************************************/
192/** portable pipe/socketpair */ 237/* portable pipe/socketpair */
193 238
194#ifdef USE_SOCKETS_AS_HANDLES 239#if defined(USE_SOCKETS_AS_HANDLES) || PERL_VERSION_ATLEAST(5,18,0)
195# define S_TO_SOCKET(x) (win32_get_osfhandle (x)) 240# define S_TO_HANDLE(x) ((HANDLE)win32_get_osfhandle (x))
196#else 241#else
197# define S_TO_SOCKET(x) (x) 242# define S_TO_HANDLE(x) ((HANDLE)x)
198#endif 243#endif
199 244
200#ifdef _WIN32 245#ifdef _WIN32
201/* taken almost verbatim from libev's ev_win32.c */ 246/* taken almost verbatim from libev's ev_win32.c */
202/* oh, the humanity! */ 247/* oh, the humanity! */
203static int 248static int
204s_pipe (int filedes [2]) 249s_pipe (int filedes [2])
205{ 250{
251 dTHX;
252
206 struct sockaddr_in addr = { 0 }; 253 struct sockaddr_in addr = { 0 };
207 int addr_size = sizeof (addr); 254 int addr_size = sizeof (addr);
208 struct sockaddr_in adr2; 255 struct sockaddr_in adr2;
209 int adr2_size = sizeof (adr2); 256 int adr2_size = sizeof (adr2);
210 SOCKET listener; 257 SOCKET listener;
211 SOCKET sock [2] = { -1, -1 }; 258 SOCKET sock [2] = { -1, -1 };
212 259
213 if ((listener = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) 260 if ((listener = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
214 return -1; 261 return -1;
215 262
216 addr.sin_family = AF_INET; 263 addr.sin_family = AF_INET;
217 addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); 264 addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
218 addr.sin_port = 0; 265 addr.sin_port = 0;
224 goto fail; 271 goto fail;
225 272
226 if (listen (listener, 1)) 273 if (listen (listener, 1))
227 goto fail; 274 goto fail;
228 275
229 if ((sock [0] = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) 276 if ((sock [0] = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
230 goto fail; 277 goto fail;
231 278
232 if (connect (sock [0], (struct sockaddr *)&addr, addr_size)) 279 if (connect (sock [0], (struct sockaddr *)&addr, addr_size))
233 goto fail; 280 goto fail;
234 281
259 || addr.sin_port != adr2.sin_port) 306 || addr.sin_port != adr2.sin_port)
260 goto fail; 307 goto fail;
261 308
262 closesocket (listener); 309 closesocket (listener);
263 310
264#ifdef USE_SOCKETS_AS_HANDLES 311#if defined(USE_SOCKETS_AS_HANDLES) || PERL_VERSION_ATLEAST(5,18,0)
265 /* when select isn't winsocket, we also expect socket, connect, accept etc. 312 /* when select isn't winsocket, we also expect socket, connect, accept etc.
266 * to work on fds */ 313 * to work on fds */
267 filedes [0] = sock [0]; 314 filedes [0] = sock [0];
268 filedes [1] = sock [1]; 315 filedes [1] = sock [1];
269#else 316#else
282 return -1; 329 return -1;
283} 330}
284 331
285#define s_socketpair(domain,type,protocol,filedes) s_pipe (filedes) 332#define s_socketpair(domain,type,protocol,filedes) s_pipe (filedes)
286 333
334static int
335s_fd_blocking (int fd, int blocking)
336{
337 u_long nonblocking = !blocking;
338
339 return ioctlsocket ((SOCKET)S_TO_HANDLE (fd), FIONBIO, &nonblocking);
340}
341
342#define s_fd_prepare(fd) s_fd_blocking (fd, 0)
343
287#else 344#else
288 345
289#define s_socketpair(domain,type,protocol,filedes) socketpair (domain, type, protocol, filedes) 346#define s_socketpair(domain,type,protocol,filedes) socketpair (domain, type, protocol, filedes)
290#define s_pipe(filedes) pipe (filedes) 347#define s_pipe(filedes) pipe (filedes)
291 348
349static int
350s_fd_blocking (int fd, int blocking)
351{
352 return fcntl (fd, F_SETFL, blocking ? 0 : O_NONBLOCK);
353}
354
355static int
356s_fd_prepare (int fd)
357{
358 return s_fd_blocking (fd, 0)
359 || fcntl (fd, F_SETFD, FD_CLOEXEC);
360}
361
362#endif
363
364#if HAVE_EVENTFD
365# include <sys/eventfd.h>
366#else
367# if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 7))
368# define SCHMORP_H_HAVE_EVENTFD 1
369/* our minimum requirement is glibc 2.7 which has the stub, but not the header */
370# include <stdint.h>
371# ifdef __cplusplus
372extern "C" {
373# endif
374 int eventfd (unsigned int initval, int flags);
375# ifdef __cplusplus
376}
377# endif
378# else
379# define eventfd(initval,flags) -1
292#endif 380# endif
293
294#endif 381#endif
295 382
383typedef struct {
384 int fd[2]; /* read, write fd, might be equal */
385 int len; /* write length (1 pipe/socket, 8 eventfd) */
386} s_epipe;
387
388static int
389s_epipe_new (s_epipe *epp)
390{
391 s_epipe ep;
392
393 ep.fd [0] = ep.fd [1] = eventfd (0, 0);
394
395 if (ep.fd [0] >= 0)
396 {
397 s_fd_prepare (ep.fd [0]);
398 ep.len = 8;
399 }
400 else
401 {
402 if (s_pipe (ep.fd))
403 return -1;
404
405 if (s_fd_prepare (ep.fd [0])
406 || s_fd_prepare (ep.fd [1]))
407 {
408 dTHX;
409
410 close (ep.fd [0]);
411 close (ep.fd [1]);
412 return -1;
413 }
414
415 ep.len = 1;
416 }
417
418 *epp = ep;
419 return 0;
420}
421
422static void
423s_epipe_destroy (s_epipe *epp)
424{
425 dTHX;
426
427 close (epp->fd [0]);
428
429 if (epp->fd [1] != epp->fd [0])
430 close (epp->fd [1]);
431
432 epp->len = 0;
433}
434
435static void
436s_epipe_signal (s_epipe *epp)
437{
438#ifdef _WIN32
439 /* perl overrides send with a function that crashes in other threads.
440 * unfortunately, it overrides it with an argument-less macro, so
441 * there is no way to force usage of the real send function.
442 * incompetent windows programmers - is this redundant?
443 */
444 DWORD dummy;
445 WriteFile (S_TO_HANDLE (epp->fd [1]), (LPCVOID)&dummy, 1, &dummy, 0);
446#else
447 static uint64_t counter = 1;
448 /* some modules accept fd's from outside, support eventfd here */
449 if (write (epp->fd [1], &counter, epp->len) < 0
450 && errno == EINVAL
451 && epp->len != 8)
452 write (epp->fd [1], &counter, (epp->len = 8));
453#endif
454}
455
456static void
457s_epipe_drain (s_epipe *epp)
458{
459 dTHX;
460 char buf [9];
461
462#ifdef _WIN32
463 recv (epp->fd [0], buf, sizeof (buf), 0);
464#else
465 read (epp->fd [0], buf, sizeof (buf));
466#endif
467}
468
469/* like new, but dups over old */
470static int
471s_epipe_renew (s_epipe *epp)
472{
473 dTHX;
474 s_epipe epn;
475
476 if (epp->fd [1] != epp->fd [0])
477 close (epp->fd [1]);
478
479 if (s_epipe_new (&epn))
480 return -1;
481
482 if (epp->len)
483 {
484 if (dup2 (epn.fd [0], epp->fd [0]) < 0)
485 croak ("unable to dup over old event pipe"); /* should not croak */
486
487 close (epn.fd [0]);
488
489 if (epn.fd [0] == epn.fd [1])
490 epn.fd [1] = epp->fd [0];
491
492 epn.fd [0] = epp->fd [0];
493 }
494
495 *epp = epn;
496
497 return 0;
498}
499
500#define s_epipe_fd(epp) ((epp)->fd [0])
501
502static int
503s_epipe_wait (s_epipe *epp)
504{
505 dTHX;
506#if SCHMORP_H_PREFER_SELECT
507 fd_set rfd;
508 int fd = s_epipe_fd (epp);
509
510 FD_ZERO (&rfd);
511 FD_SET (fd, &rfd);
512
513 return PerlSock_select (fd + 1, &rfd, 0, 0, 0);
514#else
515 /* poll is preferable on posix systems */
516 struct pollfd pfd;
517
518 pfd.fd = s_epipe_fd (epp);
519 pfd.events = POLLIN;
520
521 return poll (&pfd, 1, -1);
522#endif
523}
524
525#endif
526

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines