ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/EV/schmorp.h
Revision: 1.4
Committed: Wed Jul 15 16:58:53 2009 UTC (14 years, 10 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.3: +186 -3 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    
10     #ifndef _WIN32
11     # include <poll.h>
12     #endif
13    
14 root 1.1 /* useful stuff, used by schmorp mostly */
15    
16 root 1.2 #include "patchlevel.h"
17    
18 root 1.1 #define PERL_VERSION_ATLEAST(a,b,c) \
19     (PERL_REVISION > (a) \
20     || (PERL_REVISION == (a) \
21     && (PERL_VERSION > (b) \
22     || (PERL_VERSION == (b) && PERL_SUBVERSION >= (c)))))
23    
24     #if !PERL_VERSION_ATLEAST (5,6,0)
25     # ifndef PL_ppaddr
26     # define PL_ppaddr ppaddr
27     # endif
28     # ifndef call_sv
29     # define call_sv perl_call_sv
30     # endif
31     # ifndef get_sv
32     # define get_sv perl_get_sv
33     # endif
34     # ifndef get_cv
35     # define get_cv perl_get_cv
36     # endif
37     # ifndef IS_PADGV
38     # define IS_PADGV(v) 0
39     # endif
40     # ifndef IS_PADCONST
41     # define IS_PADCONST(v) 0
42     # endif
43     #endif
44    
45     /* 5.11 */
46     #ifndef CxHASARGS
47     # define CxHASARGS(cx) (cx)->blk_sub.hasargs
48     #endif
49    
50     /* 5.10.0 */
51     #ifndef SvREFCNT_inc_NN
52     # define SvREFCNT_inc_NN(sv) SvREFCNT_inc (sv)
53     #endif
54    
55     /* 5.8.8 */
56     #ifndef GV_NOTQUAL
57     # define GV_NOTQUAL 0
58     #endif
59     #ifndef newSV
60     # define newSV(l) NEWSV(0,l)
61     #endif
62     #ifndef CvISXSUB_on
63     # define CvISXSUB_on(cv) (void)cv
64     #endif
65     #ifndef CvISXSUB
66     # define CvISXSUB(cv) (CvXSUB (cv) ? TRUE : FALSE)
67     #endif
68     #ifndef Newx
69     # define Newx(ptr,nitems,type) New (0,ptr,nitems,type)
70     #endif
71    
72     /* 5.8.7 */
73     #ifndef SvRV_set
74     # define SvRV_set(s,v) SvRV(s) = (v)
75     #endif
76    
77     static int
78     s_signum (SV *sig)
79     {
80     #ifndef SIG_SIZE
81     /* kudos to Slaven Rezic for the idea */
82     static char sig_size [] = { SIG_NUM };
83     # define SIG_SIZE (sizeof (sig_size) + 1)
84     #endif
85 root 1.2 dTHX;
86 root 1.1 int signum;
87    
88     SvGETMAGIC (sig);
89    
90     for (signum = 1; signum < SIG_SIZE; ++signum)
91     if (strEQ (SvPV_nolen (sig), PL_sig_name [signum]))
92     return signum;
93    
94     signum = SvIV (sig);
95    
96     if (signum > 0 && signum < SIG_SIZE)
97     return signum;
98    
99     return -1;
100     }
101    
102     static int
103     s_signum_croak (SV *sig)
104     {
105     int signum = s_signum (sig);
106    
107     if (signum < 0)
108 root 1.2 {
109     dTHX;
110     croak ("%s: invalid signal name or number", SvPV_nolen (sig));
111     }
112 root 1.1
113     return signum;
114     }
115    
116     static int
117     s_fileno (SV *fh, int wr)
118     {
119 root 1.2 dTHX;
120 root 1.1 SvGETMAGIC (fh);
121    
122     if (SvROK (fh))
123     {
124     fh = SvRV (fh);
125     SvGETMAGIC (fh);
126     }
127    
128     if (SvTYPE (fh) == SVt_PVGV)
129     return PerlIO_fileno (wr ? IoOFP (sv_2io (fh)) : IoIFP (sv_2io (fh)));
130    
131     if (SvOK (fh) && (SvIV (fh) >= 0) && (SvIV (fh) < 0x7fffffffL))
132     return SvIV (fh);
133    
134     return -1;
135     }
136    
137     static int
138     s_fileno_croak (SV *fh, int wr)
139     {
140     int fd = s_fileno (fh, wr);
141    
142     if (fd < 0)
143 root 1.2 {
144     dTHX;
145     croak ("%s: illegal fh argument, either not an OS file or read/write mode mismatch", SvPV_nolen (fh));
146     }
147 root 1.1
148     return fd;
149     }
150    
151     static SV *
152     s_get_cv (SV *cb_sv)
153     {
154 root 1.2 dTHX;
155 root 1.1 HV *st;
156     GV *gvp;
157    
158 root 1.2 return (SV *)sv_2cv (cb_sv, &st, &gvp, 0);
159 root 1.1 }
160    
161     static SV *
162     s_get_cv_croak (SV *cb_sv)
163     {
164 root 1.2 SV *cv = s_get_cv (cb_sv);
165 root 1.1
166 root 1.2 if (!cv)
167     {
168     dTHX;
169     croak ("%s: callback must be a CODE reference or another callable object", SvPV_nolen (cb_sv));
170     }
171 root 1.1
172 root 1.2 return cv;
173 root 1.1 }
174    
175     /*****************************************************************************/
176     /* gensub: simple closure generation utility */
177    
178     #define S_GENSUB_ARG CvXSUBANY (cv).any_ptr
179    
180     /* create a closure from XS, returns a code reference */
181     /* the arg can be accessed via GENSUB_ARG from the callback */
182     /* the callback must use dXSARGS/XSRETURN */
183     static SV *
184     s_gensub (pTHX_ void (*xsub)(pTHX_ CV *), void *arg)
185     {
186     CV *cv = (CV *)newSV (0);
187    
188     sv_upgrade ((SV *)cv, SVt_PVCV);
189    
190     CvANON_on (cv);
191     CvISXSUB_on (cv);
192     CvXSUB (cv) = xsub;
193     S_GENSUB_ARG = arg;
194    
195     return newRV_noinc ((SV *)cv);
196     }
197    
198 root 1.4 /*****************************************************************************/
199     /* portable pipe/socketpair */
200 root 1.3
201     #ifdef USE_SOCKETS_AS_HANDLES
202 root 1.4 # define S_TO_HANDLE(x) ((HANDLE)win32_get_osfhandle (x))
203 root 1.3 #else
204 root 1.4 # define S_TO_HANDLE(x) ((HANDLE)x)
205 root 1.3 #endif
206    
207     #ifdef _WIN32
208     /* taken almost verbatim from libev's ev_win32.c */
209     /* oh, the humanity! */
210     static int
211     s_pipe (int filedes [2])
212     {
213     struct sockaddr_in addr = { 0 };
214     int addr_size = sizeof (addr);
215     struct sockaddr_in adr2;
216     int adr2_size = sizeof (adr2);
217     SOCKET listener;
218     SOCKET sock [2] = { -1, -1 };
219    
220     if ((listener = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
221     return -1;
222    
223     addr.sin_family = AF_INET;
224     addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
225     addr.sin_port = 0;
226    
227     if (bind (listener, (struct sockaddr *)&addr, addr_size))
228     goto fail;
229    
230     if (getsockname (listener, (struct sockaddr *)&addr, &addr_size))
231     goto fail;
232    
233     if (listen (listener, 1))
234     goto fail;
235    
236     if ((sock [0] = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
237     goto fail;
238    
239     if (connect (sock [0], (struct sockaddr *)&addr, addr_size))
240     goto fail;
241    
242     if ((sock [1] = accept (listener, 0, 0)) < 0)
243     goto fail;
244    
245     /* windows vista returns fantasy port numbers for getpeername.
246     * example for two interconnected tcp sockets:
247     *
248     * (Socket::unpack_sockaddr_in getsockname $sock0)[0] == 53364
249     * (Socket::unpack_sockaddr_in getpeername $sock0)[0] == 53363
250     * (Socket::unpack_sockaddr_in getsockname $sock1)[0] == 53363
251     * (Socket::unpack_sockaddr_in getpeername $sock1)[0] == 53365
252     *
253     * wow! tridirectional sockets!
254     *
255     * this way of checking ports seems to work:
256     */
257     if (getpeername (sock [0], (struct sockaddr *)&addr, &addr_size))
258     goto fail;
259    
260     if (getsockname (sock [1], (struct sockaddr *)&adr2, &adr2_size))
261     goto fail;
262    
263     errno = WSAEINVAL;
264     if (addr_size != adr2_size
265     || addr.sin_addr.s_addr != adr2.sin_addr.s_addr /* just to be sure, I mean, it's windows */
266     || addr.sin_port != adr2.sin_port)
267     goto fail;
268    
269     closesocket (listener);
270    
271     #ifdef USE_SOCKETS_AS_HANDLES
272     /* when select isn't winsocket, we also expect socket, connect, accept etc.
273     * to work on fds */
274     filedes [0] = sock [0];
275     filedes [1] = sock [1];
276     #else
277     filedes [0] = _open_osfhandle (sock [0], 0);
278     filedes [1] = _open_osfhandle (sock [1], 0);
279     #endif
280    
281     return 0;
282    
283     fail:
284     closesocket (listener);
285    
286     if (sock [0] != INVALID_SOCKET) closesocket (sock [0]);
287     if (sock [1] != INVALID_SOCKET) closesocket (sock [1]);
288    
289     return -1;
290     }
291    
292     #define s_socketpair(domain,type,protocol,filedes) s_pipe (filedes)
293    
294 root 1.4 static int
295     s_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    
304 root 1.3 #else
305    
306     #define s_socketpair(domain,type,protocol,filedes) socketpair (domain, type, protocol, filedes)
307     #define s_pipe(filedes) pipe (filedes)
308    
309 root 1.4 static int
310     s_fd_blocking (int fd, int blocking)
311     {
312     return fcntl (fd, F_SETFL, blocking ? 0 : O_NONBLOCK);
313     }
314    
315     static int
316     s_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
328     extern "C" {
329     # endif
330     int eventfd (unsigned int initval, int flags);
331     # ifdef __cplusplus
332     }
333     # endif
334     #else
335     # define eventfd(initval,flags) -1
336     #endif
337    
338     typedef 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    
344     static int
345     s_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    
377     static void
378     s_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    
388     static void
389     s_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    
411     static void
412     s_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 root 1.3 #endif
421    
422 root 1.4 epp->sent = 0;
423     }
424    
425     /* like new, but dups over old */
426     static int
427     s_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    
455     static int
456     s_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 root 1.1 #endif
478