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

# 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 #include <errno.h>
10
11 #if defined(WIN32 ) || defined(_MINIX)
12 # define SCHMORP_H_PREFER_SELECT 1
13 #endif
14
15 #if !SCHMORP_H_PREFER_SELECT
16 # include <poll.h>
17 #endif
18
19 /* useful stuff, used by schmorp mostly */
20
21 #include "patchlevel.h"
22
23 #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 #ifndef PERL_MAGIC_ext
30 # define PERL_MAGIC_ext '~'
31 #endif
32
33 #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 dTHX;
95 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 {
118 dTHX;
119 croak ("%s: invalid signal name or number", SvPV_nolen (sig));
120 }
121
122 return signum;
123 }
124
125 static int
126 s_fileno (SV *fh, int wr)
127 {
128 dTHX;
129 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 {
153 dTHX;
154 croak ("%s: illegal fh argument, either not an OS file or read/write mode mismatch", SvPV_nolen (fh));
155 }
156
157 return fd;
158 }
159
160 static SV *
161 s_get_cv (SV *cb_sv)
162 {
163 dTHX;
164 HV *st;
165 GV *gvp;
166
167 return (SV *)sv_2cv (cb_sv, &st, &gvp, 0);
168 }
169
170 static SV *
171 s_get_cv_croak (SV *cb_sv)
172 {
173 SV *cv = s_get_cv (cb_sv);
174
175 if (!cv)
176 {
177 dTHX;
178 croak ("%s: callback must be a CODE reference or another callable object", SvPV_nolen (cb_sv));
179 }
180
181 return cv;
182 }
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 /*****************************************************************************/
208 /* portable pipe/socketpair */
209
210 #ifdef USE_SOCKETS_AS_HANDLES
211 # define S_TO_HANDLE(x) ((HANDLE)win32_get_osfhandle (x))
212 #else
213 # define S_TO_HANDLE(x) ((HANDLE)x)
214 #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 dTHX;
223
224 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 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 #else
316
317 #define s_socketpair(domain,type,protocol,filedes) socketpair (domain, type, protocol, filedes)
318 #define s_pipe(filedes) pipe (filedes)
319
320 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 # define SCHMORP_H_HAVE_EVENTFD 1
337 /* 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 dTHX;
376
377 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 dTHX;
393
394 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 /* 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 #else
414 # if SCHMORP_H_HAVE_EVENTFD
415 static uint64_t counter = 1;
416 # else
417 static char counter [8];
418 # endif
419 /* 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 #endif
425 }
426
427 static void
428 s_epipe_drain (s_epipe *epp)
429 {
430 dTHX;
431 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 #endif
438 }
439
440 /* like new, but dups over old */
441 static int
442 s_epipe_renew (s_epipe *epp)
443 {
444 dTHX;
445 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 close (epn.fd [0]);
459
460 if (epn.fd [0] == epn.fd [1])
461 epn.fd [1] = epp->fd [0];
462
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 dTHX;
477 #if SCHMORP_H_PREFER_SELECT
478 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 return poll (&pfd, 1, -1);
493 #endif
494 }
495
496 #endif
497