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