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

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines