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

Comparing IO-AIO/schmorp.h (file contents):
Revision 1.5 by root, Wed Jul 15 01:36:04 2009 UTC vs.
Revision 1.11 by root, Wed Aug 4 14:02:58 2010 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines