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.4 by root, Fri Jul 17 21:04:45 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} s_epipe;
343
344static int
345s_epipe_new (s_epipe *epp)
346{
347 s_epipe ep;
348
349 ep.fd [0] = ep.fd [1] = eventfd (0, 0);
350
351 if (ep.fd [0] >= 0)
352 {
353 s_fd_prepare (ep.fd [0]);
354 ep.len = 8;
355 }
356 else
357 {
358 if (s_pipe (ep.fd))
359 return -1;
360
361 if (s_fd_prepare (ep.fd [0])
362 || s_fd_prepare (ep.fd [1]))
363 {
364 close (ep.fd [0]);
365 close (ep.fd [1]);
366 return -1;
367 }
368
369 ep.len = 1;
370 }
371
372 *epp = ep;
373 return 0;
374}
375
376static void
377s_epipe_destroy (s_epipe *epp)
378{
379 close (epp->fd [0]);
380
381 if (epp->fd [1] != epp->fd [0])
382 close (epp->fd [1]);
383
384 epp->len = 0;
385}
386
387static void
388s_epipe_signal (s_epipe *epp)
389{
390#ifdef _WIN32
391 /* perl overrides send with a function that crashes in other threads.
392 * unfortunately, it overrides it with an argument-less macro, so
393 * there is no way to force usage of the real send function.
394 * incompetent windows programmers - is this redundant?
395 */
396 DWORD dummy;
397 WriteFile (S_TO_HANDLE (epp->fd [1]), (LPCVOID)&dummy, 1, &dummy, 0);
398#else
399 static uint64_t counter = 1;
400 /* some modules accept fd's from outside, support eventfd here */
401 if (write (epp->fd [1], &counter, epp->len) < 0
402 && errno == EINVAL
403 && epp->len != 8)
404 write (epp->fd [1], &counter, (epp->len = 8));
405#endif
406}
407
408static void
409s_epipe_drain (s_epipe *epp)
410{
411 char buf [9];
412
413#ifdef _WIN32
414 recv (epp->fd [0], buf, sizeof (buf), 0);
415#else
416 read (epp->fd [0], buf, sizeof (buf));
417#endif
418}
419
420/* like new, but dups over old */
421static int
422s_epipe_renew (s_epipe *epp)
423{
424 s_epipe epn;
425
426 if (epp->fd [1] != epp->fd [0])
427 close (epp->fd [1]);
428
429 if (s_epipe_new (&epn))
430 return -1;
431
432 if (epp->len)
433 {
434 if (dup2 (epn.fd [0], epp->fd [0]) < 0)
435 croak ("unable to dup over old event pipe"); /* should not croak */
436
437 if (epp->fd [1] != epp->fd [0])
438 close (epn.fd [0]);
439
440 epn.fd [0] = epp->fd [0];
441 }
442
443 *epp = epn;
444
445 return 0;
446}
447
448#define s_epipe_fd(epp) ((epp)->fd [0])
449
450static int
451s_epipe_wait (s_epipe *epp)
452{
453#ifdef _WIN32
454 fd_set rfd;
455 int fd = s_epipe_fd (epp);
456
457 FD_ZERO (&rfd);
458 FD_SET (fd, &rfd);
459
460 return PerlSock_select (fd + 1, &rfd, 0, 0, 0);
461#else
462 /* poll is preferable on posix systems */
463 struct pollfd pfd;
464
465 pfd.fd = s_epipe_fd (epp);
466 pfd.events = POLLIN;
467
468 return poll (&pfd, 1, 0);
469#endif
470}
471
472#endif
473

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines