ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/EV/schmorp.h
Revision: 1.9
Committed: Thu Jul 8 00:45:03 2010 UTC (13 years, 10 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-4_01, rel-4_00, rel-4_03, rel-4_02, EV_rel-4_11, EV_rel-4_10
Changes since 1.8: +11 -2 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 #ifndef SCHMORP_PERL_H_
2     #define SCHMORP_PERL_H_
3    
4 root 1.2 /* WARNING
5     * This header file is a shared resource between many modules.
6     */
7    
8 root 1.4 #include <signal.h>
9 root 1.5 #include <errno.h>
10 root 1.4
11 root 1.9 #if defined(WIN32 ) || defined(_MINIX)
12     # define SCHMORP_H_PREFER_SELECT 1
13     #endif
14    
15     #if !SCHMORP_H_PREFER_SELECT
16 root 1.4 # include <poll.h>
17     #endif
18    
19 root 1.1 /* useful stuff, used by schmorp mostly */
20    
21 root 1.2 #include "patchlevel.h"
22    
23 root 1.1 #define PERL_VERSION_ATLEAST(a,b,c) \
24     (PERL_REVISION > (a) \
25     || (PERL_REVISION == (a) \
26     && (PERL_VERSION > (b) \
27     || (PERL_VERSION == (b) && PERL_SUBVERSION >= (c)))))
28    
29 root 1.7 #ifndef PERL_MAGIC_ext
30     # define PERL_MAGIC_ext '~'
31     #endif
32    
33 root 1.1 #if !PERL_VERSION_ATLEAST (5,6,0)
34     # ifndef PL_ppaddr
35     # define PL_ppaddr ppaddr
36     # endif
37     # ifndef call_sv
38     # define call_sv perl_call_sv
39     # endif
40     # ifndef get_sv
41     # define get_sv perl_get_sv
42     # endif
43     # ifndef get_cv
44     # define get_cv perl_get_cv
45     # endif
46     # ifndef IS_PADGV
47     # define IS_PADGV(v) 0
48     # endif
49     # ifndef IS_PADCONST
50     # define IS_PADCONST(v) 0
51     # endif
52     #endif
53    
54     /* 5.11 */
55     #ifndef CxHASARGS
56     # define CxHASARGS(cx) (cx)->blk_sub.hasargs
57     #endif
58    
59     /* 5.10.0 */
60     #ifndef SvREFCNT_inc_NN
61     # define SvREFCNT_inc_NN(sv) SvREFCNT_inc (sv)
62     #endif
63    
64     /* 5.8.8 */
65     #ifndef GV_NOTQUAL
66     # define GV_NOTQUAL 0
67     #endif
68     #ifndef newSV
69     # define newSV(l) NEWSV(0,l)
70     #endif
71     #ifndef CvISXSUB_on
72     # define CvISXSUB_on(cv) (void)cv
73     #endif
74     #ifndef CvISXSUB
75     # define CvISXSUB(cv) (CvXSUB (cv) ? TRUE : FALSE)
76     #endif
77     #ifndef Newx
78     # define Newx(ptr,nitems,type) New (0,ptr,nitems,type)
79     #endif
80    
81     /* 5.8.7 */
82     #ifndef SvRV_set
83     # define SvRV_set(s,v) SvRV(s) = (v)
84     #endif
85    
86     static int
87     s_signum (SV *sig)
88     {
89     #ifndef SIG_SIZE
90     /* kudos to Slaven Rezic for the idea */
91     static char sig_size [] = { SIG_NUM };
92     # define SIG_SIZE (sizeof (sig_size) + 1)
93     #endif
94 root 1.2 dTHX;
95 root 1.1 int signum;
96    
97     SvGETMAGIC (sig);
98    
99     for (signum = 1; signum < SIG_SIZE; ++signum)
100     if (strEQ (SvPV_nolen (sig), PL_sig_name [signum]))
101     return signum;
102    
103     signum = SvIV (sig);
104    
105     if (signum > 0 && signum < SIG_SIZE)
106     return signum;
107    
108     return -1;
109     }
110    
111     static int
112     s_signum_croak (SV *sig)
113     {
114     int signum = s_signum (sig);
115    
116     if (signum < 0)
117 root 1.2 {
118     dTHX;
119     croak ("%s: invalid signal name or number", SvPV_nolen (sig));
120     }
121 root 1.1
122     return signum;
123     }
124    
125     static int
126     s_fileno (SV *fh, int wr)
127     {
128 root 1.2 dTHX;
129 root 1.1 SvGETMAGIC (fh);
130    
131     if (SvROK (fh))
132     {
133     fh = SvRV (fh);
134     SvGETMAGIC (fh);
135     }
136    
137     if (SvTYPE (fh) == SVt_PVGV)
138     return PerlIO_fileno (wr ? IoOFP (sv_2io (fh)) : IoIFP (sv_2io (fh)));
139    
140     if (SvOK (fh) && (SvIV (fh) >= 0) && (SvIV (fh) < 0x7fffffffL))
141     return SvIV (fh);
142    
143     return -1;
144     }
145    
146     static int
147     s_fileno_croak (SV *fh, int wr)
148     {
149     int fd = s_fileno (fh, wr);
150    
151     if (fd < 0)
152 root 1.2 {
153     dTHX;
154     croak ("%s: illegal fh argument, either not an OS file or read/write mode mismatch", SvPV_nolen (fh));
155     }
156 root 1.1
157     return fd;
158     }
159    
160     static SV *
161     s_get_cv (SV *cb_sv)
162     {
163 root 1.2 dTHX;
164 root 1.1 HV *st;
165     GV *gvp;
166    
167 root 1.2 return (SV *)sv_2cv (cb_sv, &st, &gvp, 0);
168 root 1.1 }
169    
170     static SV *
171     s_get_cv_croak (SV *cb_sv)
172     {
173 root 1.2 SV *cv = s_get_cv (cb_sv);
174 root 1.1
175 root 1.2 if (!cv)
176     {
177     dTHX;
178     croak ("%s: callback must be a CODE reference or another callable object", SvPV_nolen (cb_sv));
179     }
180 root 1.1
181 root 1.2 return cv;
182 root 1.1 }
183    
184     /*****************************************************************************/
185     /* gensub: simple closure generation utility */
186    
187     #define S_GENSUB_ARG CvXSUBANY (cv).any_ptr
188    
189     /* create a closure from XS, returns a code reference */
190     /* the arg can be accessed via GENSUB_ARG from the callback */
191     /* the callback must use dXSARGS/XSRETURN */
192     static SV *
193     s_gensub (pTHX_ void (*xsub)(pTHX_ CV *), void *arg)
194     {
195     CV *cv = (CV *)newSV (0);
196    
197     sv_upgrade ((SV *)cv, SVt_PVCV);
198    
199     CvANON_on (cv);
200     CvISXSUB_on (cv);
201     CvXSUB (cv) = xsub;
202     S_GENSUB_ARG = arg;
203    
204     return newRV_noinc ((SV *)cv);
205     }
206    
207 root 1.4 /*****************************************************************************/
208     /* portable pipe/socketpair */
209 root 1.3
210     #ifdef USE_SOCKETS_AS_HANDLES
211 root 1.4 # define S_TO_HANDLE(x) ((HANDLE)win32_get_osfhandle (x))
212 root 1.3 #else
213 root 1.4 # define S_TO_HANDLE(x) ((HANDLE)x)
214 root 1.3 #endif
215    
216     #ifdef _WIN32
217     /* taken almost verbatim from libev's ev_win32.c */
218     /* oh, the humanity! */
219     static int
220     s_pipe (int filedes [2])
221     {
222 root 1.6 dTHX;
223    
224 root 1.3 struct sockaddr_in addr = { 0 };
225     int addr_size = sizeof (addr);
226     struct sockaddr_in adr2;
227     int adr2_size = sizeof (adr2);
228     SOCKET listener;
229     SOCKET sock [2] = { -1, -1 };
230    
231     if ((listener = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
232     return -1;
233    
234     addr.sin_family = AF_INET;
235     addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
236     addr.sin_port = 0;
237    
238     if (bind (listener, (struct sockaddr *)&addr, addr_size))
239     goto fail;
240    
241     if (getsockname (listener, (struct sockaddr *)&addr, &addr_size))
242     goto fail;
243    
244     if (listen (listener, 1))
245     goto fail;
246    
247     if ((sock [0] = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
248     goto fail;
249    
250     if (connect (sock [0], (struct sockaddr *)&addr, addr_size))
251     goto fail;
252    
253     if ((sock [1] = accept (listener, 0, 0)) < 0)
254     goto fail;
255    
256     /* windows vista returns fantasy port numbers for getpeername.
257     * example for two interconnected tcp sockets:
258     *
259     * (Socket::unpack_sockaddr_in getsockname $sock0)[0] == 53364
260     * (Socket::unpack_sockaddr_in getpeername $sock0)[0] == 53363
261     * (Socket::unpack_sockaddr_in getsockname $sock1)[0] == 53363
262     * (Socket::unpack_sockaddr_in getpeername $sock1)[0] == 53365
263     *
264     * wow! tridirectional sockets!
265     *
266     * this way of checking ports seems to work:
267     */
268     if (getpeername (sock [0], (struct sockaddr *)&addr, &addr_size))
269     goto fail;
270    
271     if (getsockname (sock [1], (struct sockaddr *)&adr2, &adr2_size))
272     goto fail;
273    
274     errno = WSAEINVAL;
275     if (addr_size != adr2_size
276     || addr.sin_addr.s_addr != adr2.sin_addr.s_addr /* just to be sure, I mean, it's windows */
277     || addr.sin_port != adr2.sin_port)
278     goto fail;
279    
280     closesocket (listener);
281    
282     #ifdef USE_SOCKETS_AS_HANDLES
283     /* when select isn't winsocket, we also expect socket, connect, accept etc.
284     * to work on fds */
285     filedes [0] = sock [0];
286     filedes [1] = sock [1];
287     #else
288     filedes [0] = _open_osfhandle (sock [0], 0);
289     filedes [1] = _open_osfhandle (sock [1], 0);
290     #endif
291    
292     return 0;
293    
294     fail:
295     closesocket (listener);
296    
297     if (sock [0] != INVALID_SOCKET) closesocket (sock [0]);
298     if (sock [1] != INVALID_SOCKET) closesocket (sock [1]);
299    
300     return -1;
301     }
302    
303     #define s_socketpair(domain,type,protocol,filedes) s_pipe (filedes)
304    
305 root 1.4 static int
306     s_fd_blocking (int fd, int blocking)
307     {
308     u_long nonblocking = !blocking;
309    
310     return ioctlsocket ((SOCKET)S_TO_HANDLE (fd), FIONBIO, &nonblocking);
311     }
312    
313     #define s_fd_prepare(fd) s_fd_blocking (fd, 0)
314    
315 root 1.3 #else
316    
317     #define s_socketpair(domain,type,protocol,filedes) socketpair (domain, type, protocol, filedes)
318     #define s_pipe(filedes) pipe (filedes)
319    
320 root 1.4 static int
321     s_fd_blocking (int fd, int blocking)
322     {
323     return fcntl (fd, F_SETFL, blocking ? 0 : O_NONBLOCK);
324     }
325    
326     static int
327     s_fd_prepare (int fd)
328     {
329     return s_fd_blocking (fd, 0)
330     || fcntl (fd, F_SETFD, FD_CLOEXEC);
331     }
332    
333     #endif
334    
335     #if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 7))
336 root 1.9 # define SCHMORP_H_HAVE_EVENTFD 1
337 root 1.4 /* our minimum requirement is glibc 2.7 which has the stub, but not the header */
338     # include <stdint.h>
339     # ifdef __cplusplus
340     extern "C" {
341     # endif
342     int eventfd (unsigned int initval, int flags);
343     # ifdef __cplusplus
344     }
345     # endif
346     #else
347     # define eventfd(initval,flags) -1
348     #endif
349    
350     typedef struct {
351     int fd[2]; /* read, write fd, might be equal */
352     int len; /* write length (1 pipe/socket, 8 eventfd) */
353     } s_epipe;
354    
355     static int
356     s_epipe_new (s_epipe *epp)
357     {
358     s_epipe ep;
359    
360     ep.fd [0] = ep.fd [1] = eventfd (0, 0);
361    
362     if (ep.fd [0] >= 0)
363     {
364     s_fd_prepare (ep.fd [0]);
365     ep.len = 8;
366     }
367     else
368     {
369     if (s_pipe (ep.fd))
370     return -1;
371    
372     if (s_fd_prepare (ep.fd [0])
373     || s_fd_prepare (ep.fd [1]))
374     {
375 root 1.6 dTHX;
376    
377 root 1.4 close (ep.fd [0]);
378     close (ep.fd [1]);
379     return -1;
380     }
381    
382     ep.len = 1;
383     }
384    
385     *epp = ep;
386     return 0;
387     }
388    
389     static void
390     s_epipe_destroy (s_epipe *epp)
391     {
392 root 1.6 dTHX;
393    
394 root 1.4 close (epp->fd [0]);
395    
396     if (epp->fd [1] != epp->fd [0])
397     close (epp->fd [1]);
398    
399     epp->len = 0;
400     }
401    
402     static void
403     s_epipe_signal (s_epipe *epp)
404     {
405     #ifdef _WIN32
406 root 1.6 /* 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);
413 root 1.4 #else
414 root 1.9 # if SCHMORP_H_HAVE_EVENTFD
415 root 1.6 static uint64_t counter = 1;
416 root 1.9 # else
417     static char counter [8];
418     # endif
419 root 1.6 /* 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)
423     write (epp->fd [1], &counter, (epp->len = 8));
424 root 1.4 #endif
425     }
426    
427     static void
428     s_epipe_drain (s_epipe *epp)
429     {
430 root 1.6 dTHX;
431 root 1.4 char buf [9];
432    
433     #ifdef _WIN32
434     recv (epp->fd [0], buf, sizeof (buf), 0);
435     #else
436     read (epp->fd [0], buf, sizeof (buf));
437 root 1.3 #endif
438 root 1.4 }
439    
440     /* like new, but dups over old */
441     static int
442     s_epipe_renew (s_epipe *epp)
443     {
444 root 1.6 dTHX;
445 root 1.4 s_epipe epn;
446    
447     if (epp->fd [1] != epp->fd [0])
448     close (epp->fd [1]);
449    
450     if (s_epipe_new (&epn))
451     return -1;
452    
453     if (epp->len)
454     {
455     if (dup2 (epn.fd [0], epp->fd [0]) < 0)
456     croak ("unable to dup over old event pipe"); /* should not croak */
457    
458 root 1.8 close (epn.fd [0]);
459    
460     if (epn.fd [0] == epn.fd [1])
461     epn.fd [1] = epp->fd [0];
462 root 1.4
463     epn.fd [0] = epp->fd [0];
464     }
465    
466     *epp = epn;
467    
468     return 0;
469     }
470    
471     #define s_epipe_fd(epp) ((epp)->fd [0])
472    
473     static int
474     s_epipe_wait (s_epipe *epp)
475     {
476 root 1.6 dTHX;
477 root 1.9 #if SCHMORP_H_PREFER_SELECT
478 root 1.4 fd_set rfd;
479     int fd = s_epipe_fd (epp);
480    
481     FD_ZERO (&rfd);
482     FD_SET (fd, &rfd);
483    
484     return PerlSock_select (fd + 1, &rfd, 0, 0, 0);
485     #else
486     /* poll is preferable on posix systems */
487     struct pollfd pfd;
488    
489     pfd.fd = s_epipe_fd (epp);
490     pfd.events = POLLIN;
491    
492 root 1.7 return poll (&pfd, 1, -1);
493 root 1.4 #endif
494     }
495    
496 root 1.1 #endif
497