ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/IO-AIO/AIO.xs
Revision: 1.176
Committed: Thu Dec 2 10:04:47 2010 UTC (13 years, 5 months ago) by root
Branch: MAIN
Changes since 1.175: +1 -0 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.115 #include "libeio/xthread.h"
2 root 1.63
3 root 1.19 #include <errno.h>
4    
5 root 1.15 #include "EXTERN.h"
6 root 1.1 #include "perl.h"
7     #include "XSUB.h"
8    
9 root 1.151 #include "schmorp.h"
10    
11 root 1.37 #include <stddef.h>
12 root 1.94 #include <stdlib.h>
13 root 1.41 #include <errno.h>
14 root 1.1 #include <sys/types.h>
15     #include <sys/stat.h>
16 root 1.159 #include <sys/statvfs.h>
17 root 1.37 #include <limits.h>
18 root 1.1 #include <fcntl.h>
19     #include <sched.h>
20 root 1.103
21 root 1.162 #if _POSIX_MEMLOCK || _POSIX_MAPPED_FILES
22 root 1.161 # include <sys/mman.h>
23     #endif
24    
25 root 1.118 /* perl namespace pollution */
26     #undef VERSION
27    
28 root 1.103 #ifdef _WIN32
29    
30 root 1.115 # define EIO_STRUCT_DIRENT Direntry_t
31     # undef malloc
32     # undef free
33 root 1.103
34     // perl overrides all those nice win32 functions
35     # undef open
36     # undef read
37     # undef write
38 root 1.104 # undef send
39     # undef recv
40 root 1.103 # undef stat
41     # undef fstat
42     # define lstat stat
43     # undef truncate
44     # undef ftruncate
45     # undef open
46     # undef close
47     # undef unlink
48     # undef rmdir
49     # undef rename
50     # undef lseek
51    
52     # define chown(a,b,c) (errno = ENOSYS, -1)
53     # define fchown(a,b,c) (errno = ENOSYS, -1)
54     # define fchmod(a,b) (errno = ENOSYS, -1)
55     # define symlink(a,b) (errno = ENOSYS, -1)
56     # define readlink(a,b,c) (errno = ENOSYS, -1)
57     # define mknod(a,b,c) (errno = ENOSYS, -1)
58     # define truncate(a,b) (errno = ENOSYS, -1)
59     # define ftruncate(fd,o) chsize ((fd), (o))
60     # define fsync(fd) _commit (fd)
61     # define opendir(fd) (errno = ENOSYS, 0)
62     # define readdir(fd) (errno = ENOSYS, -1)
63     # define closedir(fd) (errno = ENOSYS, -1)
64     # define mkdir(a,b) mkdir (a)
65    
66     #else
67    
68     # include <sys/time.h>
69     # include <sys/select.h>
70     # include <unistd.h>
71     # include <utime.h>
72     # include <signal.h>
73 root 1.115 # define EIO_STRUCT_DIRENT struct dirent
74 root 1.103
75     #endif
76 root 1.1
77 root 1.125 /* perl stupidly overrides readdir and maybe others */
78     /* with thread-unsafe versions, imagine that :( */
79     #undef readdir
80     #undef opendir
81     #undef closedir
82    
83 root 1.115 #define EIO_STRUCT_STAT Stat_t
84 root 1.65
85 root 1.101 /* use NV for 32 bit perls as it allows larger offsets */
86     #if IVSIZE >= 8
87 root 1.148 # define VAL64 IV
88 root 1.101 # define SvVAL64 SvIV
89 root 1.148 # define newSVval64 newSViv
90 root 1.101 #else
91 root 1.148 # define VAL64 NV
92 root 1.101 # define SvVAL64 SvNV
93 root 1.148 # define newSVval64 newSVnv
94 root 1.101 #endif
95    
96 root 1.127 /*****************************************************************************/
97    
98     #if __GNUC__ >= 3
99     # define expect(expr,value) __builtin_expect ((expr),(value))
100     #else
101     # define expect(expr,value) (expr)
102     #endif
103    
104     #define expect_false(expr) expect ((expr) != 0, 0)
105     #define expect_true(expr) expect ((expr) != 0, 1)
106    
107     /*****************************************************************************/
108    
109 root 1.90 typedef SV SV8; /* byte-sv, used for argument-checking */
110 root 1.148 typedef int aio_rfd; /* read file desriptor */
111     typedef int aio_wfd; /* write file descriptor */
112 root 1.90
113 root 1.156 static HV *aio_stash, *aio_req_stash, *aio_grp_stash;
114 root 1.43
115 root 1.121 #define EIO_REQ_MEMBERS \
116 root 1.115 SV *callback; \
117     SV *sv1, *sv2; \
118     STRLEN stroffset; \
119 root 1.121 SV *self;
120 root 1.115
121 root 1.122 #define EIO_NO_WRAPPERS 1
122    
123 root 1.176 #include "libeio/config.h"
124 root 1.115 #include "libeio/eio.h"
125    
126 root 1.148 #ifndef POSIX_FADV_NORMAL
127     # define POSIX_FADV_NORMAL 0
128     #endif
129     #ifndef POSIX_FADV_SEQUENTIAL
130     # define POSIX_FADV_SEQUENTIAL 0
131     #endif
132     #ifndef POSIX_FADV_RANDOM
133     # define POSIX_FADV_RANDOM 0
134     #endif
135     #ifndef POSIX_FADV_NOREUSE
136     # define POSIX_FADV_NOREUSE 0
137     #endif
138     #ifndef POSIX_FADV_WILLNEED
139     # define POSIX_FADV_WILLNEED 0
140     #endif
141     #ifndef POSIX_FADV_DONTNEED
142     # define POSIX_FADV_DONTNEED 0
143     #endif
144    
145 root 1.175 #if !HAVE_POSIX_FADVISE
146 root 1.170 # define posix_fadvise(a,b,c,d) errno = ENOSYS /* also return ENOSYS */
147     #endif
148    
149 root 1.169 #ifndef POSIX_MADV_NORMAL
150     # define POSIX_MADV_NORMAL 0
151     #endif
152     #ifndef POSIX_MADV_SEQUENTIAL
153     # define POSIX_MADV_SEQUENTIAL 0
154     #endif
155     #ifndef POSIX_MADV_RANDOM
156     # define POSIX_MADV_RANDOM 0
157     #endif
158     #ifndef POSIX_MADV_WILLNEED
159     # define POSIX_MADV_WILLNEED 0
160     #endif
161     #ifndef POSIX_MADV_DONTNEED
162     # define POSIX_MADV_DONTNEED 0
163     #endif
164    
165 root 1.175 #if !HAVE_POSIX_MADVISE
166 root 1.170 # define posix_madvise(a,b,c) errno = ENOSYS /* also return ENOSYS */
167     #endif
168    
169 root 1.171 #ifndef PROT_NONE
170     # define PROT_NONE 0
171     #endif
172     #ifndef PROT_READ
173     # define PROT_READ 0
174     #endif
175     #ifndef PROT_WRITE
176     # define PROT_READ 0
177     #endif
178     #ifndef PROT_EXEC
179     # define PROT_EXEC 0
180     #endif
181    
182 root 1.159 #ifndef ST_NODEV
183     # define ST_NODEV 0
184     #endif
185     #ifndef ST_NOEXEC
186     # define ST_NOEXEC 0
187     #endif
188     #ifndef ST_SYNCHRONOUS
189     # define ST_SYNCHRONOUS 0
190     #endif
191     #ifndef ST_MANDLOCK
192     # define ST_MANDLOCK 0
193     #endif
194     #ifndef ST_WRITE
195     # define ST_WRITE 0
196     #endif
197     #ifndef ST_APPEND
198     # define ST_APPEND 0
199     #endif
200     #ifndef ST_IMMUTABLE
201     # define ST_IMMUTABLE 0
202     #endif
203     #ifndef ST_NOATIME
204     # define ST_NOATIME 0
205     #endif
206     #ifndef ST_NODIRATIME
207     # define ST_NODIRATIME 0
208     #endif
209     #ifndef ST_RELATIME
210     # define ST_RELATIME 0
211     #endif
212    
213 root 1.162 #ifndef MAP_ANONYMOUS
214     # ifdef MAP_ANON
215     # define MAP_ANONYMOUS MAP_ANON
216     # else
217     # define MAP_ANONYMOUS MAP_FIXED /* and hope this fails */
218     # endif
219     #endif
220     #ifndef MAP_HUGETLB
221     # define MAP_HUGETLB 0
222     #endif
223     #ifndef MAP_LOCKED
224     # define MAP_LOCKED 0
225     #endif
226     #ifndef MAP_NORESERVE
227     # define MAP_NORESERVE 0
228     #endif
229     #ifndef MAP_POPULATE
230     # define MAP_POPULATE 0
231     #endif
232     #ifndef MAP_NONBLOCK
233     # define MAP_NONBLOCK 0
234     #endif
235    
236     #ifndef PAGESIZE
237     # define PAGESIZE sysconf (_SC_PAGESIZE)
238     #endif
239    
240 root 1.115 static int req_invoke (eio_req *req);
241     #define EIO_FINISH(req) req_invoke (req)
242     static void req_destroy (eio_req *grp);
243     #define EIO_DESTROY(req) req_destroy (req)
244 root 1.1
245 root 1.58 enum {
246 root 1.115 FLAG_SV2_RO_OFF = 0x40, /* data was set readonly */
247 root 1.58 };
248    
249 root 1.115 #include "libeio/eio.c"
250 root 1.1
251 root 1.115 typedef eio_req *aio_req;
252     typedef eio_req *aio_req_ornot;
253 root 1.60
254 root 1.117 static SV *on_next_submit;
255 root 1.121 static int next_pri = EIO_PRI_DEFAULT;
256 root 1.117 static int max_outstanding;
257 root 1.94
258 root 1.153 static s_epipe respipe;
259 root 1.80
260 root 1.115 static void req_destroy (aio_req req);
261     static void req_cancel (aio_req req);
262 root 1.80
263 root 1.115 static void want_poll (void)
264 root 1.80 {
265 root 1.115 /* write a dummy byte to the pipe so fh becomes ready */
266 root 1.153 s_epipe_signal (&respipe);
267 root 1.67 }
268    
269 root 1.115 static void done_poll (void)
270 root 1.67 {
271 root 1.115 /* read any signals sent by the worker threads */
272 root 1.153 s_epipe_drain (&respipe);
273 root 1.67 }
274 root 1.1
275 root 1.43 /* must be called at most once */
276 root 1.156 static SV *req_sv (aio_req req, HV *stash)
277 root 1.43 {
278 root 1.49 if (!req->self)
279     {
280     req->self = (SV *)newHV ();
281     sv_magic (req->self, 0, PERL_MAGIC_ext, (char *)req, 0);
282     }
283 root 1.43
284 root 1.156 return sv_2mortal (sv_bless (newRV_inc (req->self), stash));
285 root 1.43 }
286    
287 root 1.45 static aio_req SvAIO_REQ (SV *sv)
288 root 1.26 {
289 root 1.53 MAGIC *mg;
290    
291 root 1.156 if (!SvROK (sv)
292     || (SvSTASH (SvRV (sv)) != aio_grp_stash
293     && SvSTASH (SvRV (sv)) != aio_req_stash
294     && !sv_derived_from (sv, "IO::AIO::REQ")))
295     croak ("object of class IO::AIO::REQ expected");
296 root 1.43
297 root 1.53 mg = mg_find (SvRV (sv), PERL_MAGIC_ext);
298 root 1.43
299     return mg ? (aio_req)mg->mg_ptr : 0;
300     }
301    
302 root 1.49 static void aio_grp_feed (aio_req grp)
303     {
304 root 1.115 if (grp->sv2 && SvOK (grp->sv2))
305 root 1.49 {
306 root 1.115 dSP;
307 root 1.49
308 root 1.115 ENTER;
309     SAVETMPS;
310     PUSHMARK (SP);
311 root 1.156 XPUSHs (req_sv (grp, aio_grp_stash));
312 root 1.115 PUTBACK;
313     call_sv (grp->sv2, G_VOID | G_EVAL | G_KEEPERR);
314     SPAGAIN;
315     FREETMPS;
316     LEAVE;
317 root 1.50 }
318     }
319    
320 root 1.117 static void req_submit (eio_req *req)
321     {
322     eio_submit (req);
323    
324 root 1.127 if (expect_false (on_next_submit))
325 root 1.117 {
326     dSP;
327     SV *cb = sv_2mortal (on_next_submit);
328    
329     on_next_submit = 0;
330    
331     PUSHMARK (SP);
332     PUTBACK;
333     call_sv (cb, G_DISCARD | G_EVAL);
334     }
335     }
336    
337 root 1.115 static int req_invoke (eio_req *req)
338 root 1.45 {
339 root 1.100 if (req->flags & FLAG_SV2_RO_OFF)
340     SvREADONLY_off (req->sv2);
341 root 1.86
342 root 1.128 if (!EIO_CANCELLED (req) && req->callback)
343 root 1.67 {
344 root 1.166 dSP;
345 root 1.165 static SV *sv_result_cache; /* caches the result integer SV */
346     SV *sv_result;
347    
348 root 1.67 ENTER;
349     SAVETMPS;
350     PUSHMARK (SP);
351     EXTEND (SP, 1);
352 root 1.45
353 root 1.165 /* do not recreate the result IV from scratch each time */
354     if (expect_true (sv_result_cache))
355     {
356     sv_result = sv_result_cache; sv_result_cache = 0;
357     SvIV_set (sv_result, req->result);
358     }
359     else
360     {
361     sv_result = newSViv (req->result);
362     SvREADONLY_on (sv_result);
363     }
364    
365 root 1.67 switch (req->type)
366 root 1.45 {
367 root 1.115 case EIO_READDIR:
368 root 1.45 {
369 root 1.67 SV *rv = &PL_sv_undef;
370 root 1.45
371 root 1.67 if (req->result >= 0)
372 root 1.45 {
373 root 1.71 int i;
374 root 1.147 char *names = (char *)req->ptr2;
375     eio_dirent *ent = (eio_dirent *)req->ptr1; /* might be 0 */
376 root 1.67 AV *av = newAV ();
377    
378 root 1.71 av_extend (av, req->result - 1);
379    
380     for (i = 0; i < req->result; ++i)
381 root 1.67 {
382 root 1.141 if (req->int1 & EIO_READDIR_DENTS)
383     {
384 root 1.147 SV *namesv = newSVpvn (names + ent->nameofs, ent->namelen);
385 root 1.141
386     if (req->int1 & EIO_READDIR_CUSTOM2)
387     {
388     static SV *sv_type [EIO_DT_MAX + 1]; /* type sv cache */
389     AV *avent = newAV ();
390    
391     av_extend (avent, 2);
392    
393     if (!sv_type [ent->type])
394     {
395     sv_type [ent->type] = newSViv (ent->type);
396     SvREADONLY_on (sv_type [ent->type]);
397     }
398    
399     av_store (avent, 0, namesv);
400 root 1.143 av_store (avent, 1, SvREFCNT_inc (sv_type [ent->type]));
401     av_store (avent, 2, IVSIZE >= 8 ? newSVuv (ent->inode) : newSVnv (ent->inode));
402 root 1.141
403     av_store (av, i, newRV_noinc ((SV *)avent));
404     }
405     else
406     av_store (av, i, namesv);
407    
408 root 1.147 ++ent;
409 root 1.141 }
410     else
411     {
412 root 1.147 SV *name = newSVpv (names, 0);
413 root 1.141 av_store (av, i, name);
414 root 1.147 names += SvCUR (name) + 1;
415 root 1.141 }
416 root 1.67 }
417 root 1.45
418 root 1.67 rv = sv_2mortal (newRV_noinc ((SV *)av));
419 root 1.45 }
420    
421 root 1.67 PUSHs (rv);
422 root 1.141
423     if (req->int1 & EIO_READDIR_CUSTOM1)
424     XPUSHs (sv_2mortal (newSViv (req->int1 & ~(EIO_READDIR_CUSTOM1 | EIO_READDIR_CUSTOM2))));
425 root 1.45 }
426 root 1.67 break;
427 root 1.45
428 root 1.115 case EIO_OPEN:
429 root 1.67 {
430     /* convert fd to fh */
431 root 1.107 SV *fh = &PL_sv_undef;
432    
433     if (req->result >= 0)
434     {
435     GV *gv = (GV *)sv_newmortal ();
436     int flags = req->int1 & (O_RDONLY | O_WRONLY | O_RDWR);
437     char sym [64];
438     int symlen;
439    
440 root 1.146 symlen = snprintf (sym, sizeof (sym), "fd#%d", (int)req->result);
441 root 1.156 gv_init (gv, aio_stash, sym, symlen, 0);
442 root 1.107
443     symlen = snprintf (
444     sym,
445     sizeof (sym),
446 root 1.146 "%s&=%d",
447 root 1.107 flags == O_RDONLY ? "<" : flags == O_WRONLY ? ">" : "+<",
448 root 1.146 (int)req->result
449 root 1.107 );
450 root 1.45
451 root 1.107 if (do_open (gv, sym, symlen, 0, 0, 0, 0))
452 root 1.108 fh = (SV *)gv;
453 root 1.107 }
454 root 1.45
455 root 1.109 PUSHs (fh);
456 root 1.67 }
457     break;
458 root 1.45
459 root 1.159 case EIO_STATVFS:
460     case EIO_FSTATVFS:
461     {
462     SV *rv = &PL_sv_undef;
463    
464     if (req->result >= 0)
465     {
466     EIO_STRUCT_STATVFS *f = EIO_STATVFS_BUF (req);
467     HV *hv = newHV ();
468    
469 root 1.160 rv = sv_2mortal (newRV_noinc ((SV *)hv));
470 root 1.159
471     hv_store (hv, "bsize" , sizeof ("bsize" ) - 1, newSVval64 (f->f_bsize ), 0);
472     hv_store (hv, "frsize" , sizeof ("frsize" ) - 1, newSVval64 (f->f_frsize ), 0);
473     hv_store (hv, "blocks" , sizeof ("blocks" ) - 1, newSVval64 (f->f_blocks ), 0);
474     hv_store (hv, "bfree" , sizeof ("bfree" ) - 1, newSVval64 (f->f_bfree ), 0);
475     hv_store (hv, "bavail" , sizeof ("bavail" ) - 1, newSVval64 (f->f_bavail ), 0);
476     hv_store (hv, "files" , sizeof ("files" ) - 1, newSVval64 (f->f_files ), 0);
477     hv_store (hv, "ffree" , sizeof ("ffree" ) - 1, newSVval64 (f->f_ffree ), 0);
478     hv_store (hv, "favail" , sizeof ("favail" ) - 1, newSVval64 (f->f_favail ), 0);
479     hv_store (hv, "fsid" , sizeof ("fsid" ) - 1, newSVval64 (f->f_fsid ), 0);
480     hv_store (hv, "flag" , sizeof ("flag" ) - 1, newSVval64 (f->f_flag ), 0);
481     hv_store (hv, "namemax", sizeof ("namemax") - 1, newSVval64 (f->f_namemax), 0);
482     }
483    
484     PUSHs (rv);
485     }
486    
487     break;
488    
489 root 1.115 case EIO_GROUP:
490 root 1.86 req->int1 = 2; /* mark group as finished */
491 root 1.45
492 root 1.86 if (req->sv1)
493 root 1.67 {
494     int i;
495 root 1.86 AV *av = (AV *)req->sv1;
496 root 1.49
497 root 1.67 EXTEND (SP, AvFILL (av) + 1);
498     for (i = 0; i <= AvFILL (av); ++i)
499     PUSHs (*av_fetch (av, i, 0));
500     }
501     break;
502 root 1.48
503 root 1.115 case EIO_NOP:
504     case EIO_BUSY:
505 root 1.67 break;
506 root 1.48
507 root 1.115 case EIO_READLINK:
508 root 1.86 if (req->result > 0)
509 root 1.119 PUSHs (sv_2mortal (newSVpvn (req->ptr2, req->result)));
510 root 1.86 break;
511    
512 root 1.115 case EIO_STAT:
513     case EIO_LSTAT:
514     case EIO_FSTAT:
515     PL_laststype = req->type == EIO_LSTAT ? OP_LSTAT : OP_STAT;
516 root 1.87 PL_laststatval = req->result;
517 root 1.115 PL_statcache = *(EIO_STRUCT_STAT *)(req->ptr2);
518 root 1.165 PUSHs (sv_result);
519 root 1.87 break;
520    
521 root 1.115 case EIO_READ:
522 root 1.138 {
523     SvCUR_set (req->sv2, req->stroffset + (req->result > 0 ? req->result : 0));
524     *SvEND (req->sv2) = 0;
525     SvPOK_only (req->sv2);
526     SvSETMAGIC (req->sv2);
527 root 1.165 PUSHs (sv_result);
528 root 1.138 }
529 root 1.87 break;
530    
531 root 1.167 case EIO_DUP2: /* EIO_DUP2 actually means aio_close(), su fudge result value */
532 root 1.115 if (req->result > 0)
533 root 1.165 SvIV_set (sv_result, 0);
534 root 1.115 /* FALLTHROUGH */
535    
536 root 1.67 default:
537 root 1.165 PUSHs (sv_result);
538 root 1.67 break;
539     }
540 root 1.45
541 root 1.79 errno = req->errorno;
542 root 1.51
543 root 1.67 PUTBACK;
544 root 1.109 call_sv (req->callback, G_VOID | G_EVAL | G_DISCARD);
545 root 1.67 SPAGAIN;
546 root 1.51
547 root 1.165 if (expect_false (SvREFCNT (sv_result) != 1 || sv_result_cache))
548     SvREFCNT_dec (sv_result);
549     else
550     sv_result_cache = sv_result;
551    
552 root 1.67 FREETMPS;
553     LEAVE;
554 root 1.109
555     PUTBACK;
556 root 1.45 }
557    
558 root 1.115 return !!SvTRUE (ERRSV);
559 root 1.67 }
560    
561 root 1.101 static void req_destroy (aio_req req)
562 root 1.67 {
563 root 1.43 if (req->self)
564     {
565     sv_unmagic (req->self, PERL_MAGIC_ext);
566     SvREFCNT_dec (req->self);
567     }
568    
569 root 1.86 SvREFCNT_dec (req->sv1);
570     SvREFCNT_dec (req->sv2);
571 root 1.49 SvREFCNT_dec (req->callback);
572 root 1.26
573     Safefree (req);
574     }
575    
576 root 1.72 static void req_cancel_subs (aio_req grp)
577     {
578     aio_req sub;
579    
580 root 1.115 if (grp->type != EIO_GROUP)
581 root 1.72 return;
582    
583 root 1.86 SvREFCNT_dec (grp->sv2);
584     grp->sv2 = 0;
585 root 1.72
586 root 1.115 eio_grp_cancel (grp);
587 root 1.1 }
588    
589 root 1.104 static void
590 root 1.111 create_respipe (void)
591 root 1.104 {
592 root 1.153 if (s_epipe_renew (&respipe))
593 root 1.155 croak ("IO::AIO: unable to initialize result pipe");
594 root 1.104 }
595    
596 root 1.111 static void poll_wait (void)
597 root 1.80 {
598 root 1.115 while (eio_nreqs ())
599 root 1.30 {
600 root 1.80 int size;
601 root 1.115
602     X_LOCK (reslock);
603 root 1.80 size = res_queue.size;
604 root 1.115 X_UNLOCK (reslock);
605 root 1.80
606     if (size)
607     return;
608    
609 root 1.123 etp_maybe_start_thread ();
610 root 1.80
611 root 1.153 s_epipe_wait (&respipe);
612 root 1.22 }
613 root 1.80 }
614    
615 root 1.111 static int poll_cb (void)
616 root 1.80 {
617 root 1.124 for (;;)
618 root 1.116 {
619 root 1.124 int res = eio_poll ();
620 root 1.116
621     if (res > 0)
622     croak (0);
623 root 1.124
624     if (!max_outstanding || max_outstanding > eio_nreqs ())
625     return res;
626    
627     poll_wait ();
628 root 1.116 }
629 root 1.17 }
630 root 1.37
631 root 1.116 static void atfork_child (void)
632     {
633     create_respipe ();
634     }
635    
636 root 1.162 /*****************************************************************************/
637    
638 root 1.163 #if !_POSIX_MAPPED_FILES
639     # define mmap(addr,length,prot,flags,fd,offs) (errno = ENOSYS, -1)
640     # define munmap(addr,length) (errno = ENOSYS, -1)
641 root 1.171 # define mprotect(addr,len,prot) (errno = ENOSYS, -1)
642 root 1.174 # define PROT_NONE 0
643     # define PROT_WRITE 0
644     # define MAP_PRIVATE 0
645     # define MAP_SHARED 0
646     # define MAP_FIXED 0
647 root 1.163 #endif
648    
649 root 1.162 #define MMAP_MAGIC PERL_MAGIC_ext
650    
651     static int
652     mmap_free (pTHX_ SV *sv, MAGIC *mg)
653     {
654     int old_errno = errno;
655     munmap (mg->mg_ptr, (size_t)mg->mg_obj);
656     errno = old_errno;
657    
658     mg->mg_obj = 0; /* just in case */
659    
660     SvREADONLY_off (sv);
661 root 1.168
662     if (SvPVX (sv) != mg->mg_ptr)
663     croak ("ERROR: IO::AIO::mmap-mapped scalar changed location, detected");
664    
665 root 1.162 SvCUR_set (sv, 0);
666     SvPVX (sv) = 0;
667     SvOK_off (sv);
668    
669     return 0;
670     }
671    
672     static MGVTBL mmap_vtbl = {
673     0, 0, 0, 0, mmap_free
674     };
675    
676     /*****************************************************************************/
677    
678 root 1.128 static SV *
679     get_cb (SV *cb_sv)
680     {
681 root 1.152 SvGETMAGIC (cb_sv);
682     return SvOK (cb_sv) ? s_get_cv_croak (cb_sv) : 0;
683 root 1.128 }
684    
685 root 1.22 #define dREQ \
686 root 1.128 SV *cb_cv; \
687 root 1.22 aio_req req; \
688 root 1.60 int req_pri = next_pri; \
689 root 1.121 next_pri = EIO_PRI_DEFAULT; \
690 root 1.22 \
691 root 1.128 cb_cv = get_cb (callback); \
692 root 1.22 \
693 root 1.115 Newz (0, req, 1, eio_req); \
694 root 1.22 if (!req) \
695 root 1.115 croak ("out of memory during eio_req allocation"); \
696 root 1.22 \
697 root 1.128 req->callback = SvREFCNT_inc (cb_cv); \
698 root 1.60 req->pri = req_pri
699 root 1.43
700     #define REQ_SEND \
701 root 1.126 PUTBACK; \
702 root 1.117 req_submit (req); \
703 root 1.126 SPAGAIN; \
704 root 1.43 \
705     if (GIMME_V != G_VOID) \
706 root 1.156 XPUSHs (req_sv (req, aio_req_stash));
707 root 1.136
708 root 1.1 MODULE = IO::AIO PACKAGE = IO::AIO
709    
710 root 1.8 PROTOTYPES: ENABLE
711    
712 root 1.1 BOOT:
713     {
714 root 1.141 static const struct {
715     const char *name;
716     IV iv;
717     } *civ, const_iv[] = {
718 root 1.162 # define const_niv(name, value) { # name, (IV) value },
719     # define const_iv(name) { # name, (IV) name },
720 root 1.141 # define const_eio(name) { # name, (IV) EIO_ ## name },
721 root 1.162 const_iv (EXDEV)
722     const_iv (ENOSYS)
723     const_iv (O_RDONLY)
724     const_iv (O_WRONLY)
725 root 1.164 const_iv (O_RDWR)
726 root 1.162 const_iv (O_CREAT)
727     const_iv (O_TRUNC)
728 root 1.164 const_iv (O_EXCL)
729     const_iv (O_APPEND)
730 root 1.122 #ifndef _WIN32
731 root 1.162 const_iv (S_IFIFO)
732 root 1.103 #endif
733 root 1.162 const_niv (FADV_NORMAL , POSIX_FADV_NORMAL)
734     const_niv (FADV_SEQUENTIAL, POSIX_FADV_SEQUENTIAL)
735     const_niv (FADV_RANDOM , POSIX_FADV_RANDOM)
736     const_niv (FADV_NOREUSE , POSIX_FADV_NOREUSE)
737     const_niv (FADV_WILLNEED , POSIX_FADV_WILLNEED)
738     const_niv (FADV_DONTNEED , POSIX_FADV_DONTNEED)
739    
740 root 1.169 const_niv (MADV_NORMAL , POSIX_MADV_NORMAL)
741     const_niv (MADV_SEQUENTIAL, POSIX_MADV_SEQUENTIAL)
742     const_niv (MADV_RANDOM , POSIX_MADV_RANDOM)
743     const_niv (MADV_WILLNEED , POSIX_MADV_WILLNEED)
744     const_niv (MADV_DONTNEED , POSIX_MADV_DONTNEED)
745    
746 root 1.162 const_iv (ST_RDONLY)
747     const_iv (ST_NOSUID)
748     const_iv (ST_NODEV)
749     const_iv (ST_NOEXEC)
750     const_iv (ST_SYNCHRONOUS)
751     const_iv (ST_MANDLOCK)
752     const_iv (ST_WRITE)
753     const_iv (ST_APPEND)
754     const_iv (ST_IMMUTABLE)
755     const_iv (ST_NOATIME)
756     const_iv (ST_NODIRATIME)
757     const_iv (ST_RELATIME)
758    
759 root 1.171 const_iv (PROT_NONE)
760 root 1.162 const_iv (PROT_EXEC)
761     const_iv (PROT_READ)
762     const_iv (PROT_WRITE)
763    
764     /*const_iv (MAP_FIXED)*/
765     const_iv (MAP_PRIVATE)
766     const_iv (MAP_SHARED)
767     const_iv (MAP_ANONYMOUS)
768    
769     /* linuxish */
770     const_iv (MAP_HUGETLB)
771     const_iv (MAP_LOCKED)
772     const_iv (MAP_NORESERVE)
773     const_iv (MAP_POPULATE)
774     const_iv (MAP_NONBLOCK)
775 root 1.159
776 root 1.172 const_eio (MCL_FUTURE)
777     const_eio (MCL_CURRENT)
778 root 1.161
779 root 1.158 const_eio (MS_ASYNC)
780     const_eio (MS_INVALIDATE)
781     const_eio (MS_SYNC)
782    
783     const_eio (MT_MODIFY)
784    
785 root 1.141 const_eio (SYNC_FILE_RANGE_WAIT_BEFORE)
786     const_eio (SYNC_FILE_RANGE_WRITE)
787     const_eio (SYNC_FILE_RANGE_WAIT_AFTER)
788    
789     const_eio (READDIR_DENTS)
790     const_eio (READDIR_DIRS_FIRST)
791     const_eio (READDIR_STAT_ORDER)
792     const_eio (READDIR_FOUND_UNKNOWN)
793    
794     const_eio (DT_UNKNOWN)
795     const_eio (DT_FIFO)
796     const_eio (DT_CHR)
797     const_eio (DT_DIR)
798     const_eio (DT_BLK)
799     const_eio (DT_REG)
800     const_eio (DT_LNK)
801     const_eio (DT_SOCK)
802     const_eio (DT_WHT)
803     };
804 root 1.103
805 root 1.156 aio_stash = gv_stashpv ("IO::AIO" , 1);
806     aio_req_stash = gv_stashpv ("IO::AIO::REQ", 1);
807     aio_grp_stash = gv_stashpv ("IO::AIO::GRP", 1);
808 root 1.146
809 root 1.141 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
810 root 1.156 newCONSTSUB (aio_stash, (char *)civ->name, newSViv (civ->iv));
811 root 1.141
812 root 1.162 newCONSTSUB (aio_stash, "PAGESIZE", newSViv (PAGESIZE));
813    
814 root 1.141 create_respipe ();
815 root 1.41
816 root 1.141 if (eio_init (want_poll, done_poll) < 0)
817     croak ("IO::AIO: unable to initialise eio library");
818 root 1.116
819 root 1.141 /* atfork child called in fifo order, so before eio's handler */
820     X_THREAD_ATFORK (0, 0, atfork_child);
821 root 1.1 }
822    
823     void
824 root 1.85 max_poll_reqs (int nreqs)
825     PROTOTYPE: $
826     CODE:
827 root 1.115 eio_set_max_poll_reqs (nreqs);
828 root 1.85
829     void
830     max_poll_time (double nseconds)
831     PROTOTYPE: $
832     CODE:
833 root 1.115 eio_set_max_poll_time (nseconds);
834 root 1.85
835     void
836 root 1.78 min_parallel (int nthreads)
837 root 1.1 PROTOTYPE: $
838 root 1.115 CODE:
839     eio_set_min_parallel (nthreads);
840 root 1.1
841     void
842 root 1.78 max_parallel (int nthreads)
843     PROTOTYPE: $
844 root 1.115 CODE:
845     eio_set_max_parallel (nthreads);
846 root 1.78
847 root 1.85 void
848     max_idle (int nthreads)
849     PROTOTYPE: $
850     CODE:
851 root 1.115 eio_set_max_idle (nthreads);
852 root 1.85
853 root 1.115 void
854 root 1.78 max_outstanding (int maxreqs)
855 root 1.1 PROTOTYPE: $
856 root 1.78 CODE:
857     max_outstanding = maxreqs;
858 root 1.1
859     void
860 root 1.99 aio_open (SV8 *pathname, int flags, int mode, SV *callback=&PL_sv_undef)
861 root 1.43 PPCODE:
862 root 1.1 {
863 root 1.22 dREQ;
864 root 1.1
865 root 1.115 req->type = EIO_OPEN;
866 root 1.86 req->sv1 = newSVsv (pathname);
867 root 1.89 req->ptr1 = SvPVbyte_nolen (req->sv1);
868 root 1.86 req->int1 = flags;
869 root 1.115 req->int2 = mode;
870 root 1.1
871 root 1.43 REQ_SEND;
872 root 1.1 }
873    
874     void
875 root 1.107 aio_fsync (SV *fh, SV *callback=&PL_sv_undef)
876 root 1.1 ALIAS:
877 root 1.115 aio_fsync = EIO_FSYNC
878     aio_fdatasync = EIO_FDATASYNC
879 root 1.43 PPCODE:
880 root 1.1 {
881 root 1.151 int fd = s_fileno_croak (fh, 0);
882 root 1.22 dREQ;
883 root 1.1
884     req->type = ix;
885 root 1.99 req->sv1 = newSVsv (fh);
886 root 1.136 req->int1 = fd;
887 root 1.1
888 root 1.43 REQ_SEND (req);
889 root 1.1 }
890    
891     void
892 root 1.148 aio_sync_file_range (SV *fh, off_t offset, size_t nbytes, UV flags, SV *callback=&PL_sv_undef)
893 root 1.133 PPCODE:
894     {
895 root 1.151 int fd = s_fileno_croak (fh, 0);
896 root 1.133 dREQ;
897    
898     req->type = EIO_SYNC_FILE_RANGE;
899     req->sv1 = newSVsv (fh);
900 root 1.136 req->int1 = fd;
901 root 1.148 req->offs = offset;
902     req->size = nbytes;
903 root 1.133 req->int2 = flags;
904    
905     REQ_SEND (req);
906     }
907    
908     void
909 root 1.113 aio_close (SV *fh, SV *callback=&PL_sv_undef)
910 root 1.107 PPCODE:
911     {
912 root 1.115 static int close_pipe = -1; /* dummy fd to close fds via dup2 */
913 root 1.151 int fd = s_fileno_croak (fh, 0);
914 root 1.109 dREQ;
915 root 1.107
916 root 1.115 if (close_pipe < 0)
917     {
918     int pipefd [2];
919    
920     if (pipe (pipefd) < 0
921     || close (pipefd [1]) < 0
922     || fcntl (pipefd [0], F_SETFD, FD_CLOEXEC) < 0)
923     abort (); /*D*/
924    
925     close_pipe = pipefd [0];
926     }
927    
928     req->type = EIO_DUP2;
929     req->int1 = close_pipe;
930     req->sv2 = newSVsv (fh);
931 root 1.136 req->int2 = fd;
932 root 1.107
933 root 1.109 REQ_SEND (req);
934 root 1.107 }
935    
936     void
937 root 1.102 aio_read (SV *fh, SV *offset, SV *length, SV8 *data, IV dataoffset, SV *callback=&PL_sv_undef)
938 root 1.13 ALIAS:
939 root 1.115 aio_read = EIO_READ
940     aio_write = EIO_WRITE
941 root 1.43 PPCODE:
942 root 1.13 {
943     STRLEN svlen;
944 root 1.151 int fd = s_fileno_croak (fh, ix == EIO_WRITE);
945 root 1.21 char *svptr = SvPVbyte (data, svlen);
946 root 1.102 UV len = SvUV (length);
947 root 1.134
948 root 1.13 if (dataoffset < 0)
949     dataoffset += svlen;
950    
951     if (dataoffset < 0 || dataoffset > svlen)
952 root 1.102 croak ("dataoffset outside of data scalar");
953 root 1.13
954 root 1.115 if (ix == EIO_WRITE)
955 root 1.13 {
956     /* write: check length and adjust. */
957 root 1.102 if (!SvOK (length) || len + dataoffset > svlen)
958     len = svlen - dataoffset;
959 root 1.13 }
960     else
961     {
962 root 1.138 /* read: check type and grow scalar as necessary */
963     SvUPGRADE (data, SVt_PV);
964 root 1.102 svptr = SvGROW (data, len + dataoffset + 1);
965 root 1.13 }
966    
967 root 1.22 {
968     dREQ;
969 root 1.13
970 root 1.22 req->type = ix;
971 root 1.99 req->sv1 = newSVsv (fh);
972 root 1.135 req->int1 = fd;
973 root 1.101 req->offs = SvOK (offset) ? SvVAL64 (offset) : -1;
974 root 1.102 req->size = len;
975 root 1.132 req->sv2 = SvREFCNT_inc (data);
976 root 1.115 req->ptr2 = (char *)svptr + dataoffset;
977 root 1.86 req->stroffset = dataoffset;
978 root 1.13
979 root 1.28 if (!SvREADONLY (data))
980     {
981     SvREADONLY_on (data);
982 root 1.100 req->flags |= FLAG_SV2_RO_OFF;
983 root 1.28 }
984    
985 root 1.43 REQ_SEND;
986 root 1.22 }
987 root 1.13 }
988 root 1.1
989     void
990 root 1.99 aio_readlink (SV8 *path, SV *callback=&PL_sv_undef)
991 root 1.86 PPCODE:
992     {
993     SV *data;
994     dREQ;
995    
996 root 1.115 req->type = EIO_READLINK;
997 root 1.99 req->sv1 = newSVsv (path);
998 root 1.115 req->ptr1 = SvPVbyte_nolen (req->sv1);
999 root 1.86
1000     REQ_SEND;
1001     }
1002    
1003     void
1004 root 1.148 aio_sendfile (SV *out_fh, SV *in_fh, off_t in_offset, size_t length, SV *callback=&PL_sv_undef)
1005 root 1.43 PPCODE:
1006 root 1.32 {
1007 root 1.151 int ifd = s_fileno_croak (in_fh , 0);
1008     int ofd = s_fileno_croak (out_fh, 1);
1009 root 1.32 dREQ;
1010    
1011 root 1.115 req->type = EIO_SENDFILE;
1012 root 1.99 req->sv1 = newSVsv (out_fh);
1013 root 1.136 req->int1 = ofd;
1014 root 1.86 req->sv2 = newSVsv (in_fh);
1015 root 1.136 req->int2 = ifd;
1016 root 1.148 req->offs = in_offset;
1017 root 1.86 req->size = length;
1018 root 1.32
1019 root 1.43 REQ_SEND;
1020 root 1.32 }
1021    
1022     void
1023 root 1.148 aio_readahead (SV *fh, off_t offset, size_t length, SV *callback=&PL_sv_undef)
1024 root 1.43 PPCODE:
1025 root 1.1 {
1026 root 1.151 int fd = s_fileno_croak (fh, 0);
1027 root 1.22 dREQ;
1028 root 1.1
1029 root 1.115 req->type = EIO_READAHEAD;
1030 root 1.99 req->sv1 = newSVsv (fh);
1031 root 1.136 req->int1 = fd;
1032 root 1.148 req->offs = offset;
1033 root 1.86 req->size = length;
1034 root 1.1
1035 root 1.43 REQ_SEND;
1036 root 1.1 }
1037    
1038     void
1039 root 1.99 aio_stat (SV8 *fh_or_path, SV *callback=&PL_sv_undef)
1040 root 1.1 ALIAS:
1041 root 1.159 aio_stat = EIO_STAT
1042     aio_lstat = EIO_LSTAT
1043     aio_statvfs = EIO_STATVFS
1044 root 1.43 PPCODE:
1045 root 1.1 {
1046 root 1.22 dREQ;
1047 root 1.1
1048 root 1.99 req->sv1 = newSVsv (fh_or_path);
1049 root 1.87
1050 root 1.119 if (SvPOK (req->sv1))
1051 root 1.1 {
1052 root 1.8 req->type = ix;
1053 root 1.89 req->ptr1 = SvPVbyte_nolen (req->sv1);
1054 root 1.1 }
1055     else
1056     {
1057 root 1.159 req->type = ix == EIO_STATVFS ? EIO_FSTATVFS : EIO_FSTAT;
1058 root 1.86 req->int1 = PerlIO_fileno (IoIFP (sv_2io (fh_or_path)));
1059 root 1.1 }
1060    
1061 root 1.43 REQ_SEND;
1062 root 1.1 }
1063    
1064     void
1065 root 1.99 aio_utime (SV8 *fh_or_path, SV *atime, SV *mtime, SV *callback=&PL_sv_undef)
1066     PPCODE:
1067     {
1068     dREQ;
1069    
1070     req->nv1 = SvOK (atime) ? SvNV (atime) : -1.;
1071     req->nv2 = SvOK (mtime) ? SvNV (mtime) : -1.;
1072     req->sv1 = newSVsv (fh_or_path);
1073    
1074 root 1.119 if (SvPOK (req->sv1))
1075 root 1.99 {
1076 root 1.115 req->type = EIO_UTIME;
1077 root 1.99 req->ptr1 = SvPVbyte_nolen (req->sv1);
1078     }
1079     else
1080     {
1081 root 1.115 req->type = EIO_FUTIME;
1082 root 1.99 req->int1 = PerlIO_fileno (IoIFP (sv_2io (fh_or_path)));
1083     }
1084    
1085     REQ_SEND;
1086     }
1087    
1088     void
1089 root 1.103 aio_truncate (SV8 *fh_or_path, SV *offset, SV *callback=&PL_sv_undef)
1090     PPCODE:
1091     {
1092     dREQ;
1093    
1094     req->sv1 = newSVsv (fh_or_path);
1095     req->offs = SvOK (offset) ? SvVAL64 (offset) : -1;
1096    
1097 root 1.119 if (SvPOK (req->sv1))
1098 root 1.103 {
1099 root 1.115 req->type = EIO_TRUNCATE;
1100 root 1.103 req->ptr1 = SvPVbyte_nolen (req->sv1);
1101     }
1102     else
1103     {
1104 root 1.115 req->type = EIO_FTRUNCATE;
1105 root 1.103 req->int1 = PerlIO_fileno (IoIFP (sv_2io (fh_or_path)));
1106     }
1107    
1108     REQ_SEND;
1109     }
1110    
1111     void
1112 root 1.99 aio_chmod (SV8 *fh_or_path, int mode, SV *callback=&PL_sv_undef)
1113 root 1.115 ALIAS:
1114     aio_chmod = EIO_CHMOD
1115     aio_mkdir = EIO_MKDIR
1116 root 1.99 PPCODE:
1117     {
1118     dREQ;
1119    
1120 root 1.115 req->int2 = mode;
1121 root 1.99 req->sv1 = newSVsv (fh_or_path);
1122    
1123 root 1.119 if (SvPOK (req->sv1))
1124     {
1125 root 1.120 req->type = ix;
1126     req->ptr1 = SvPVbyte_nolen (req->sv1);
1127 root 1.119 }
1128 root 1.99 else
1129 root 1.119 {
1130 root 1.120 req->type = EIO_FCHMOD;
1131     req->int1 = PerlIO_fileno (IoIFP (sv_2io (fh_or_path)));
1132 root 1.119 }
1133 root 1.99
1134     REQ_SEND;
1135     }
1136    
1137     void
1138     aio_chown (SV8 *fh_or_path, SV *uid, SV *gid, SV *callback=&PL_sv_undef)
1139     PPCODE:
1140     {
1141     dREQ;
1142    
1143     req->int2 = SvOK (uid) ? SvIV (uid) : -1;
1144     req->int3 = SvOK (gid) ? SvIV (gid) : -1;
1145     req->sv1 = newSVsv (fh_or_path);
1146    
1147 root 1.119 if (SvPOK (req->sv1))
1148 root 1.99 {
1149 root 1.115 req->type = EIO_CHOWN;
1150 root 1.99 req->ptr1 = SvPVbyte_nolen (req->sv1);
1151     }
1152     else
1153     {
1154 root 1.115 req->type = EIO_FCHOWN;
1155 root 1.99 req->int1 = PerlIO_fileno (IoIFP (sv_2io (fh_or_path)));
1156     }
1157    
1158     REQ_SEND;
1159     }
1160    
1161     void
1162 root 1.141 aio_readdirx (SV8 *pathname, IV flags, SV *callback=&PL_sv_undef)
1163     PPCODE:
1164     {
1165     dREQ;
1166    
1167     req->type = EIO_READDIR;
1168     req->sv1 = newSVsv (pathname);
1169     req->ptr1 = SvPVbyte_nolen (req->sv1);
1170     req->int1 = flags | EIO_READDIR_DENTS | EIO_READDIR_CUSTOM1;
1171    
1172     if (flags & EIO_READDIR_DENTS)
1173 root 1.142 req->int1 |= EIO_READDIR_CUSTOM2;
1174 root 1.141
1175     REQ_SEND;
1176     }
1177    
1178     void
1179 root 1.99 aio_unlink (SV8 *pathname, SV *callback=&PL_sv_undef)
1180 root 1.22 ALIAS:
1181 root 1.115 aio_unlink = EIO_UNLINK
1182     aio_rmdir = EIO_RMDIR
1183     aio_readdir = EIO_READDIR
1184 root 1.43 PPCODE:
1185 root 1.1 {
1186 root 1.22 dREQ;
1187 root 1.1
1188 root 1.22 req->type = ix;
1189 root 1.86 req->sv1 = newSVsv (pathname);
1190 root 1.89 req->ptr1 = SvPVbyte_nolen (req->sv1);
1191 root 1.87
1192 root 1.43 REQ_SEND;
1193 root 1.22 }
1194    
1195     void
1196 root 1.99 aio_link (SV8 *oldpath, SV8 *newpath, SV *callback=&PL_sv_undef)
1197 root 1.40 ALIAS:
1198 root 1.115 aio_link = EIO_LINK
1199     aio_symlink = EIO_SYMLINK
1200     aio_rename = EIO_RENAME
1201 root 1.43 PPCODE:
1202 root 1.22 {
1203     dREQ;
1204 root 1.1
1205 root 1.40 req->type = ix;
1206 root 1.115 req->sv1 = newSVsv (oldpath);
1207     req->ptr1 = SvPVbyte_nolen (req->sv1);
1208     req->sv2 = newSVsv (newpath);
1209 root 1.99 req->ptr2 = SvPVbyte_nolen (req->sv2);
1210 root 1.1
1211 root 1.43 REQ_SEND;
1212 root 1.1 }
1213    
1214 root 1.42 void
1215 root 1.99 aio_mknod (SV8 *pathname, int mode, UV dev, SV *callback=&PL_sv_undef)
1216 root 1.81 PPCODE:
1217     {
1218     dREQ;
1219    
1220 root 1.115 req->type = EIO_MKNOD;
1221 root 1.86 req->sv1 = newSVsv (pathname);
1222 root 1.89 req->ptr1 = SvPVbyte_nolen (req->sv1);
1223 root 1.115 req->int2 = (mode_t)mode;
1224 root 1.86 req->offs = dev;
1225 root 1.81
1226     REQ_SEND;
1227     }
1228    
1229     void
1230 root 1.158 aio_mtouch (SV8 *data, IV offset = 0, SV *length = &PL_sv_undef, int flags = 0, SV *callback=&PL_sv_undef)
1231     ALIAS:
1232     aio_mtouch = EIO_MTOUCH
1233     aio_msync = EIO_MSYNC
1234     PPCODE:
1235     {
1236     STRLEN svlen;
1237 root 1.172 char *svptr = SvPVbyte (data, svlen);
1238 root 1.158 UV len = SvUV (length);
1239    
1240     if (offset < 0)
1241     offset += svlen;
1242    
1243     if (offset < 0 || offset > svlen)
1244     croak ("offset outside of scalar");
1245    
1246     if (!SvOK (length) || len + offset > svlen)
1247     len = svlen - offset;
1248    
1249     {
1250     dREQ;
1251    
1252     req->type = ix;
1253 root 1.172 req->sv2 = SvREFCNT_inc (data);
1254     req->ptr2 = (char *)svptr + offset;
1255 root 1.158 req->size = len;
1256 root 1.172 req->int1 = flags;
1257    
1258     REQ_SEND;
1259     }
1260     }
1261    
1262     void
1263     aio_mlock (SV8 *data, IV offset = 0, SV *length = &PL_sv_undef, SV *callback=&PL_sv_undef)
1264     PPCODE:
1265     {
1266     STRLEN svlen;
1267     char *svptr = SvPVbyte (data, svlen);
1268     UV len = SvUV (length);
1269    
1270     if (offset < 0)
1271     offset += svlen;
1272    
1273     if (offset < 0 || offset > svlen)
1274     croak ("offset outside of scalar");
1275    
1276     if (!SvOK (length) || len + offset > svlen)
1277     len = svlen - offset;
1278    
1279     {
1280     dREQ;
1281    
1282     req->type = EIO_MLOCK;
1283 root 1.158 req->sv2 = SvREFCNT_inc (data);
1284     req->ptr2 = (char *)svptr + offset;
1285 root 1.172 req->size = len;
1286 root 1.158
1287     REQ_SEND;
1288     }
1289     }
1290    
1291     void
1292 root 1.172 aio_mlockall (IV flags, SV *callback=&PL_sv_undef)
1293     PPCODE:
1294     {
1295     dREQ;
1296    
1297     req->type = EIO_MLOCKALL;
1298     req->int1 = flags;
1299    
1300     REQ_SEND;
1301     }
1302    
1303     void
1304 root 1.99 aio_busy (double delay, SV *callback=&PL_sv_undef)
1305 root 1.45 PPCODE:
1306     {
1307     dREQ;
1308    
1309 root 1.115 req->type = EIO_BUSY;
1310 root 1.99 req->nv1 = delay < 0. ? 0. : delay;
1311 root 1.45
1312     REQ_SEND;
1313     }
1314    
1315     void
1316 root 1.99 aio_group (SV *callback=&PL_sv_undef)
1317 root 1.44 PPCODE:
1318 root 1.42 {
1319 root 1.44 dREQ;
1320 root 1.60
1321 root 1.115 req->type = EIO_GROUP;
1322 root 1.86
1323 root 1.127 req_submit (req);
1324 root 1.156 XPUSHs (req_sv (req, aio_grp_stash));
1325 root 1.42 }
1326    
1327 root 1.6 void
1328 root 1.99 aio_nop (SV *callback=&PL_sv_undef)
1329 root 1.110 ALIAS:
1330 root 1.115 aio_nop = EIO_NOP
1331     aio_sync = EIO_SYNC
1332 root 1.54 PPCODE:
1333     {
1334     dREQ;
1335    
1336 root 1.110 req->type = ix;
1337 root 1.54
1338     REQ_SEND;
1339     }
1340    
1341 root 1.79 int
1342     aioreq_pri (int pri = 0)
1343     CODE:
1344 root 1.121 RETVAL = next_pri;
1345 root 1.79 if (items > 0)
1346     {
1347 root 1.115 if (pri < EIO_PRI_MIN) pri = EIO_PRI_MIN;
1348     if (pri > EIO_PRI_MAX) pri = EIO_PRI_MAX;
1349 root 1.121 next_pri = pri;
1350 root 1.79 }
1351     OUTPUT:
1352     RETVAL
1353 root 1.68
1354     void
1355     aioreq_nice (int nice = 0)
1356 root 1.79 CODE:
1357     nice = next_pri - nice;
1358 root 1.115 if (nice < EIO_PRI_MIN) nice = EIO_PRI_MIN;
1359     if (nice > EIO_PRI_MAX) nice = EIO_PRI_MAX;
1360 root 1.121 next_pri = nice;
1361 root 1.60
1362 root 1.54 void
1363 root 1.40 flush ()
1364 root 1.6 CODE:
1365 root 1.116 while (eio_nreqs ())
1366 root 1.6 {
1367     poll_wait ();
1368 root 1.91 poll_cb ();
1369 root 1.6 }
1370    
1371 root 1.91 int
1372 root 1.172 poll ()
1373 root 1.7 CODE:
1374 root 1.92 poll_wait ();
1375     RETVAL = poll_cb ();
1376 root 1.91 OUTPUT:
1377     RETVAL
1378 root 1.7
1379 root 1.1 int
1380 root 1.172 poll_fileno ()
1381 root 1.1 CODE:
1382 root 1.153 RETVAL = s_epipe_fd (&respipe);
1383 root 1.1 OUTPUT:
1384     RETVAL
1385    
1386     int
1387 root 1.172 poll_cb (...)
1388 root 1.1 PROTOTYPE:
1389     CODE:
1390 root 1.85 RETVAL = poll_cb ();
1391 root 1.1 OUTPUT:
1392     RETVAL
1393    
1394     void
1395 root 1.172 poll_wait ()
1396 root 1.1 CODE:
1397 root 1.92 poll_wait ();
1398 root 1.1
1399     int
1400 root 1.172 nreqs ()
1401 root 1.1 CODE:
1402 root 1.115 RETVAL = eio_nreqs ();
1403 root 1.1 OUTPUT:
1404     RETVAL
1405    
1406 root 1.79 int
1407 root 1.172 nready ()
1408 root 1.79 CODE:
1409 root 1.115 RETVAL = eio_nready ();
1410 root 1.79 OUTPUT:
1411     RETVAL
1412    
1413     int
1414 root 1.172 npending ()
1415 root 1.79 CODE:
1416 root 1.115 RETVAL = eio_npending ();
1417 root 1.79 OUTPUT:
1418     RETVAL
1419    
1420 root 1.85 int
1421 root 1.172 nthreads ()
1422 root 1.85 CODE:
1423 root 1.122 RETVAL = eio_nthreads ();
1424 root 1.85 OUTPUT:
1425     RETVAL
1426    
1427 root 1.148 int
1428     fadvise (aio_rfd fh, off_t offset, off_t length, IV advice)
1429     CODE:
1430     RETVAL = posix_fadvise (fh, offset, length, advice);
1431     OUTPUT:
1432     RETVAL
1433    
1434     ssize_t
1435     sendfile (aio_wfd ofh, aio_rfd ifh, off_t offset, size_t count)
1436     CODE:
1437 root 1.157 RETVAL = eio_sendfile_sync (ofh, ifh, offset, count);
1438     OUTPUT:
1439     RETVAL
1440 root 1.148
1441 root 1.162 void
1442     mmap (SV *scalar, size_t length, int prot, int flags, SV *fh, off_t offset = 0)
1443     PPCODE:
1444     sv_unmagic (scalar, MMAP_MAGIC);
1445     {
1446     int fd = SvOK (fh) ? s_fileno_croak (fh, flags & PROT_WRITE) : -1;
1447     void *addr = (void *)mmap (0, length, prot, flags, fd, offset);
1448     if (addr == (void *)-1)
1449     XSRETURN_NO;
1450    
1451 root 1.168 sv_force_normal (scalar);
1452    
1453 root 1.162 /* we store the length in mg_obj, as namlen is I32 :/ */
1454     sv_magicext (scalar, 0, MMAP_MAGIC, &mmap_vtbl, (char *)addr, 0)
1455     ->mg_obj = (SV *)length;
1456    
1457     SvUPGRADE (scalar, SVt_PV); /* nop... */
1458 root 1.168
1459 root 1.162 if (!(prot & PROT_WRITE))
1460     SvREADONLY_on (scalar);
1461    
1462 root 1.168 if (SvLEN (scalar))
1463     Safefree (SvPVX (scalar));
1464    
1465 root 1.162 SvPVX (scalar) = (char *)addr;
1466     SvCUR_set (scalar, length);
1467     SvLEN_set (scalar, 0);
1468     SvPOK_only (scalar);
1469    
1470     XSRETURN_YES;
1471     }
1472    
1473     void
1474     munmap (SV *scalar)
1475     CODE:
1476     sv_unmagic (scalar, MMAP_MAGIC);
1477    
1478 root 1.161 int
1479 root 1.172 madvise (SV *scalar, off_t offset = 0, SV *length = &PL_sv_undef, IV advice_or_prot)
1480 root 1.171 ALIAS:
1481     mprotect = 1
1482 root 1.169 CODE:
1483     {
1484 root 1.172 STRLEN svlen;
1485     void *addr = SvPVbyte (scalar, svlen);
1486     size_t len = SvUV (length);
1487    
1488     if (offset < 0)
1489     offset += svlen;
1490    
1491     if (offset < 0 || offset > svlen)
1492     croak ("offset outside of scalar");
1493    
1494     if (!SvOK (length) || len + offset > svlen)
1495     len = svlen - offset;
1496 root 1.169
1497 root 1.172 addr = (void *)(((intptr_t)addr) + offset);
1498     eio_page_align (&addr, &len);
1499    
1500     switch (ix)
1501 root 1.171 {
1502 root 1.172 case 0: RETVAL = posix_madvise (addr, len, advice_or_prot); break;
1503     case 1: RETVAL = mprotect (addr, len, advice_or_prot); break;
1504 root 1.171 }
1505 root 1.169 }
1506     OUTPUT:
1507     RETVAL
1508    
1509     int
1510 root 1.172 munlock (SV *scalar, off_t offset = 0, SV *length = &PL_sv_undef)
1511 root 1.161 CODE:
1512 root 1.172 {
1513     STRLEN svlen;
1514     void *addr = SvPVbyte (scalar, svlen);
1515     size_t len = SvUV (length);
1516    
1517     if (offset < 0)
1518     offset += svlen;
1519    
1520     if (offset < 0 || offset > svlen)
1521     croak ("offset outside of scalar");
1522    
1523     if (!SvOK (length) || len + offset > svlen)
1524     len = svlen - offset;
1525    
1526     addr = (void *)(((intptr_t)addr) + offset);
1527     eio_page_align (&addr, &len);
1528 root 1.161 #if _POSIX_MEMLOCK
1529 root 1.172 RETVAL = munlock (addr, len);
1530 root 1.161 #else
1531 root 1.172 RETVAL = ((errno = ENOSYS), -1);
1532 root 1.161 #endif
1533 root 1.172 }
1534 root 1.161 OUTPUT:
1535     RETVAL
1536    
1537     int
1538     munlockall ()
1539     CODE:
1540     #if _POSIX_MEMLOCK
1541     munlockall ();
1542     #else
1543 root 1.162 RETVAL = -1;
1544 root 1.161 errno = ENOSYS;
1545     #endif
1546     OUTPUT:
1547     RETVAL
1548    
1549 root 1.117 void _on_next_submit (SV *cb)
1550     CODE:
1551     SvREFCNT_dec (on_next_submit);
1552     on_next_submit = SvOK (cb) ? newSVsv (cb) : 0;
1553    
1554 root 1.48 PROTOTYPES: DISABLE
1555    
1556 root 1.44 MODULE = IO::AIO PACKAGE = IO::AIO::REQ
1557 root 1.43
1558     void
1559     cancel (aio_req_ornot req)
1560     CODE:
1561 root 1.115 eio_cancel (req);
1562 root 1.45
1563 root 1.56 void
1564 root 1.59 cb (aio_req_ornot req, SV *callback=&PL_sv_undef)
1565 root 1.128 PPCODE:
1566     {
1567     if (GIMME_V != G_VOID)
1568     XPUSHs (req->callback ? sv_2mortal (newRV_inc (req->callback)) : &PL_sv_undef);
1569    
1570     if (items > 1)
1571     {
1572 root 1.152 SV *cb_cv =get_cb (callback);
1573 root 1.128
1574     SvREFCNT_dec (req->callback);
1575     req->callback = SvREFCNT_inc (cb_cv);
1576     }
1577     }
1578 root 1.56
1579 root 1.45 MODULE = IO::AIO PACKAGE = IO::AIO::GRP
1580    
1581     void
1582     add (aio_req grp, ...)
1583     PPCODE:
1584     {
1585     int i;
1586 root 1.94
1587 root 1.86 if (grp->int1 == 2)
1588 root 1.49 croak ("cannot add requests to IO::AIO::GRP after the group finished");
1589    
1590 root 1.45 for (i = 1; i < items; ++i )
1591     {
1592 root 1.115 aio_req req;
1593    
1594 root 1.46 if (GIMME_V != G_VOID)
1595     XPUSHs (sv_2mortal (newSVsv (ST (i))));
1596    
1597 root 1.53 req = SvAIO_REQ (ST (i));
1598 root 1.45
1599 root 1.46 if (req)
1600 root 1.115 eio_grp_add (grp, req);
1601 root 1.45 }
1602     }
1603 root 1.43
1604 root 1.48 void
1605 root 1.72 cancel_subs (aio_req_ornot req)
1606     CODE:
1607     req_cancel_subs (req);
1608    
1609     void
1610 root 1.51 result (aio_req grp, ...)
1611     CODE:
1612     {
1613     int i;
1614 root 1.79 AV *av;
1615    
1616     grp->errorno = errno;
1617    
1618     av = newAV ();
1619 root 1.141 av_extend (av, items - 1);
1620 root 1.51
1621     for (i = 1; i < items; ++i )
1622     av_push (av, newSVsv (ST (i)));
1623    
1624 root 1.86 SvREFCNT_dec (grp->sv1);
1625     grp->sv1 = (SV *)av;
1626 root 1.51 }
1627    
1628     void
1629 root 1.79 errno (aio_req grp, int errorno = errno)
1630     CODE:
1631     grp->errorno = errorno;
1632    
1633     void
1634 root 1.67 limit (aio_req grp, int limit)
1635 root 1.49 CODE:
1636 root 1.115 eio_grp_limit (grp, limit);
1637 root 1.49
1638     void
1639 root 1.56 feed (aio_req grp, SV *callback=&PL_sv_undef)
1640 root 1.49 CODE:
1641     {
1642 root 1.86 SvREFCNT_dec (grp->sv2);
1643 root 1.131 grp->sv2 = newSVsv (callback);
1644     grp->feed = aio_grp_feed;
1645 root 1.49
1646 root 1.86 if (grp->int2 <= 0)
1647     grp->int2 = 2;
1648 root 1.49
1649 root 1.115 eio_grp_limit (grp, grp->int2);
1650 root 1.49 }
1651