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.6 by root, Sat Jul 18 00:59: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! */
203static int 211static int
204s_pipe (int filedes [2]) 212s_pipe (int filedes [2])
205{ 213{
214 dTHX;
215
206 struct sockaddr_in addr = { 0 }; 216 struct sockaddr_in addr = { 0 };
207 int addr_size = sizeof (addr); 217 int addr_size = sizeof (addr);
208 struct sockaddr_in adr2; 218 struct sockaddr_in adr2;
209 int adr2_size = sizeof (adr2); 219 int adr2_size = sizeof (adr2);
210 SOCKET listener; 220 SOCKET listener;
282 return -1; 292 return -1;
283} 293}
284 294
285#define s_socketpair(domain,type,protocol,filedes) s_pipe (filedes) 295#define s_socketpair(domain,type,protocol,filedes) s_pipe (filedes)
286 296
297static int
298s_fd_blocking (int fd, int blocking)
299{
300 u_long nonblocking = !blocking;
301
302 return ioctlsocket ((SOCKET)S_TO_HANDLE (fd), FIONBIO, &nonblocking);
303}
304
305#define s_fd_prepare(fd) s_fd_blocking (fd, 0)
306
287#else 307#else
288 308
289#define s_socketpair(domain,type,protocol,filedes) socketpair (domain, type, protocol, filedes) 309#define s_socketpair(domain,type,protocol,filedes) socketpair (domain, type, protocol, filedes)
290#define s_pipe(filedes) pipe (filedes) 310#define s_pipe(filedes) pipe (filedes)
291 311
312static int
313s_fd_blocking (int fd, int blocking)
314{
315 return fcntl (fd, F_SETFL, blocking ? 0 : O_NONBLOCK);
316}
317
318static int
319s_fd_prepare (int fd)
320{
321 return s_fd_blocking (fd, 0)
322 || fcntl (fd, F_SETFD, FD_CLOEXEC);
323}
324
325#endif
326
327#if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 7))
328/* our minimum requirement is glibc 2.7 which has the stub, but not the header */
329# include <stdint.h>
330# ifdef __cplusplus
331extern "C" {
292#endif 332# endif
293 333 int eventfd (unsigned int initval, int flags);
334# ifdef __cplusplus
335}
294#endif 336# endif
337#else
338# define eventfd(initval,flags) -1
339#endif
295 340
341typedef struct {
342 int fd[2]; /* read, write fd, might be equal */
343 int len; /* write length (1 pipe/socket, 8 eventfd) */
344} s_epipe;
345
346static int
347s_epipe_new (s_epipe *epp)
348{
349 s_epipe ep;
350
351 ep.fd [0] = ep.fd [1] = eventfd (0, 0);
352
353 if (ep.fd [0] >= 0)
354 {
355 s_fd_prepare (ep.fd [0]);
356 ep.len = 8;
357 }
358 else
359 {
360 if (s_pipe (ep.fd))
361 return -1;
362
363 if (s_fd_prepare (ep.fd [0])
364 || s_fd_prepare (ep.fd [1]))
365 {
366 dTHX;
367
368 close (ep.fd [0]);
369 close (ep.fd [1]);
370 return -1;
371 }
372
373 ep.len = 1;
374 }
375
376 *epp = ep;
377 return 0;
378}
379
380static void
381s_epipe_destroy (s_epipe *epp)
382{
383 dTHX;
384
385 close (epp->fd [0]);
386
387 if (epp->fd [1] != epp->fd [0])
388 close (epp->fd [1]);
389
390 epp->len = 0;
391}
392
393static void
394s_epipe_signal (s_epipe *epp)
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 /* some modules accept fd's from outside, support eventfd here */
407 if (write (epp->fd [1], &counter, epp->len) < 0
408 && errno == EINVAL
409 && epp->len != 8)
410 write (epp->fd [1], &counter, (epp->len = 8));
411#endif
412}
413
414static void
415s_epipe_drain (s_epipe *epp)
416{
417 dTHX;
418 char buf [9];
419
420#ifdef _WIN32
421 recv (epp->fd [0], buf, sizeof (buf), 0);
422#else
423 read (epp->fd [0], buf, sizeof (buf));
424#endif
425}
426
427/* like new, but dups over old */
428static int
429s_epipe_renew (s_epipe *epp)
430{
431 dTHX;
432 s_epipe epn;
433
434 if (epp->fd [1] != epp->fd [0])
435 close (epp->fd [1]);
436
437 if (s_epipe_new (&epn))
438 return -1;
439
440 if (epp->len)
441 {
442 if (dup2 (epn.fd [0], epp->fd [0]) < 0)
443 croak ("unable to dup over old event pipe"); /* should not croak */
444
445 if (epp->fd [1] != epp->fd [0])
446 close (epn.fd [0]);
447
448 epn.fd [0] = epp->fd [0];
449 }
450
451 *epp = epn;
452
453 return 0;
454}
455
456#define s_epipe_fd(epp) ((epp)->fd [0])
457
458static int
459s_epipe_wait (s_epipe *epp)
460{
461 dTHX;
462#ifdef _WIN32
463 fd_set rfd;
464 int fd = s_epipe_fd (epp);
465
466 FD_ZERO (&rfd);
467 FD_SET (fd, &rfd);
468
469 return PerlSock_select (fd + 1, &rfd, 0, 0, 0);
470#else
471 /* poll is preferable on posix systems */
472 struct pollfd pfd;
473
474 pfd.fd = s_epipe_fd (epp);
475 pfd.events = POLLIN;
476
477 return poll (&pfd, 1, 0);
478#endif
479}
480
481#endif
482

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines