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