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

# Content
1 #ifndef SCHMORP_PERL_H_
2 #define SCHMORP_PERL_H_
3
4 /* WARNING
5 * This header file is a shared resource between many modules.
6 */
7
8 #include <signal.h>
9
10 #ifndef _WIN32
11 # include <poll.h>
12 #endif
13
14 /* useful stuff, used by schmorp mostly */
15
16 #include "patchlevel.h"
17
18 #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 dTHX;
86 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 {
109 dTHX;
110 croak ("%s: invalid signal name or number", SvPV_nolen (sig));
111 }
112
113 return signum;
114 }
115
116 static int
117 s_fileno (SV *fh, int wr)
118 {
119 dTHX;
120 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 {
144 dTHX;
145 croak ("%s: illegal fh argument, either not an OS file or read/write mode mismatch", SvPV_nolen (fh));
146 }
147
148 return fd;
149 }
150
151 static SV *
152 s_get_cv (SV *cb_sv)
153 {
154 dTHX;
155 HV *st;
156 GV *gvp;
157
158 return (SV *)sv_2cv (cb_sv, &st, &gvp, 0);
159 }
160
161 static SV *
162 s_get_cv_croak (SV *cb_sv)
163 {
164 SV *cv = s_get_cv (cb_sv);
165
166 if (!cv)
167 {
168 dTHX;
169 croak ("%s: callback must be a CODE reference or another callable object", SvPV_nolen (cb_sv));
170 }
171
172 return cv;
173 }
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 /*****************************************************************************/
199 /* portable pipe/socketpair */
200
201 #ifdef USE_SOCKETS_AS_HANDLES
202 # define S_TO_HANDLE(x) ((HANDLE)win32_get_osfhandle (x))
203 #else
204 # define S_TO_HANDLE(x) ((HANDLE)x)
205 #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 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 #else
305
306 #define s_socketpair(domain,type,protocol,filedes) socketpair (domain, type, protocol, filedes)
307 #define s_pipe(filedes) pipe (filedes)
308
309 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 #endif
421
422 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 #endif
478