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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines