ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/IO-AIO/AIO.xs
(Generate patch)

Comparing IO-AIO/AIO.xs (file contents):
Revision 1.96 by root, Sat Dec 23 04:49:37 2006 UTC vs.
Revision 1.100 by root, Fri Jun 1 06:00:40 2007 UTC

1/* solaris */ 1#include "xthread.h"
2#define _POSIX_PTHREAD_SEMANTICS 1
3
4#if __linux && !defined(_GNU_SOURCE)
5# define _GNU_SOURCE
6#endif
7
8/* just in case */
9#define _REENTRANT 1
10 2
11#include <errno.h> 3#include <errno.h>
12 4
13#include "EXTERN.h" 5#include "EXTERN.h"
14#include "perl.h" 6#include "perl.h"
15#include "XSUB.h" 7#include "XSUB.h"
16 8
17#include "autoconf/config.h" 9#include "autoconf/config.h"
18
19#include <pthread.h>
20 10
21#include <stddef.h> 11#include <stddef.h>
22#include <stdlib.h> 12#include <stdlib.h>
23#include <errno.h> 13#include <errno.h>
24#include <sys/time.h> 14#include <sys/time.h>
28#include <limits.h> 18#include <limits.h>
29#include <unistd.h> 19#include <unistd.h>
30#include <fcntl.h> 20#include <fcntl.h>
31#include <signal.h> 21#include <signal.h>
32#include <sched.h> 22#include <sched.h>
23#include <utime.h>
33 24
34#if HAVE_SENDFILE 25#if HAVE_SENDFILE
35# if __linux 26# if __linux
36# include <sys/sendfile.h> 27# include <sys/sendfile.h>
37# elif __freebsd 28# elif __freebsd
52/* used for struct dirent, AIX doesn't provide it */ 43/* used for struct dirent, AIX doesn't provide it */
53#ifndef NAME_MAX 44#ifndef NAME_MAX
54# define NAME_MAX 4096 45# define NAME_MAX 4096
55#endif 46#endif
56 47
57#ifndef PTHREAD_STACK_MIN
58/* care for broken platforms, e.g. windows */
59# define PTHREAD_STACK_MIN 16384
60#endif
61
62#if __ia64
63# define STACKSIZE 65536
64#elif __i386 || __x86_64 /* 16k is unreasonably high :( */
65# define STACKSIZE PTHREAD_STACK_MIN
66#else
67# define STACKSIZE 16384
68#endif
69
70/* wether word reads are potentially non-atomic.
71 * this is conservatice, likely most arches this runs
72 * on have atomic word read/writes.
73 */
74#ifndef WORDACCESS_UNSAFE
75# if __i386 || __x86_64
76# define WORDACCESS_UNSAFE 0
77# else
78# define WORDACCESS_UNSAFE 1
79# endif
80#endif
81
82/* buffer size for various temporary buffers */ 48/* buffer size for various temporary buffers */
83#define AIO_BUFSIZE 65536 49#define AIO_BUFSIZE 65536
84 50
85#define dBUF \ 51#define dBUF \
86 char *aio_buf; \ 52 char *aio_buf; \
96 REQ_QUIT, 62 REQ_QUIT,
97 REQ_OPEN, REQ_CLOSE, 63 REQ_OPEN, REQ_CLOSE,
98 REQ_READ, REQ_WRITE, REQ_READAHEAD, 64 REQ_READ, REQ_WRITE, REQ_READAHEAD,
99 REQ_SENDFILE, 65 REQ_SENDFILE,
100 REQ_STAT, REQ_LSTAT, REQ_FSTAT, 66 REQ_STAT, REQ_LSTAT, REQ_FSTAT,
67 REQ_UTIME, REQ_FUTIME, /* must be consecutive */
68 REQ_CHMOD, REQ_FCHMOD, /* must be consecutive */
69 REQ_CHOWN, REQ_FCHOWN, /* must be consecutive */
101 REQ_FSYNC, REQ_FDATASYNC, 70 REQ_FSYNC, REQ_FDATASYNC,
102 REQ_UNLINK, REQ_RMDIR, REQ_RENAME, 71 REQ_UNLINK, REQ_RMDIR, REQ_MKDIR, REQ_RENAME,
103 REQ_MKNOD, REQ_READDIR, 72 REQ_MKNOD, REQ_READDIR,
104 REQ_LINK, REQ_SYMLINK, REQ_READLINK, 73 REQ_LINK, REQ_SYMLINK, REQ_READLINK,
105 REQ_GROUP, REQ_NOP, 74 REQ_GROUP, REQ_NOP,
106 REQ_BUSY, 75 REQ_BUSY,
107}; 76};
111 80
112typedef struct aio_cb 81typedef struct aio_cb
113{ 82{
114 struct aio_cb *volatile next; 83 struct aio_cb *volatile next;
115 84
116 SV *callback, *fh; 85 SV *callback;
117 SV *sv1, *sv2; 86 SV *sv1, *sv2;
118 void *ptr1, *ptr2; 87 void *ptr1, *ptr2;
119 off_t offs; 88 off_t offs;
120 size_t size; 89 size_t size;
121 ssize_t result; 90 ssize_t result;
91 double nv1, nv2;
122 92
123 STRLEN stroffset; 93 STRLEN stroffset;
124 int type; 94 int type;
125 int int1, int2; 95 int int1, int2, int3;
126 int errorno; 96 int errorno;
127 mode_t mode; /* open */ 97 mode_t mode; /* open */
128 98
129 unsigned char flags; 99 unsigned char flags;
130 unsigned char pri; 100 unsigned char pri;
133 struct aio_cb *grp, *grp_prev, *grp_next, *grp_first; 103 struct aio_cb *grp, *grp_prev, *grp_next, *grp_first;
134} aio_cb; 104} aio_cb;
135 105
136enum { 106enum {
137 FLAG_CANCELLED = 0x01, /* request was cancelled */ 107 FLAG_CANCELLED = 0x01, /* request was cancelled */
138 FLAG_SV1_RO_OFF = 0x40, /* data was set readonly */ 108 FLAG_SV2_RO_OFF = 0x40, /* data was set readonly */
139 FLAG_PTR2_FREE = 0x80, /* need to free(ptr2) */ 109 FLAG_PTR2_FREE = 0x80, /* need to free(ptr2) */
140}; 110};
141 111
142typedef aio_cb *aio_req; 112typedef aio_cb *aio_req;
143typedef aio_cb *aio_req_ornot; 113typedef aio_cb *aio_req_ornot;
161{ 131{
162 return (tv2->tv_sec - tv1->tv_sec ) * AIO_TICKS 132 return (tv2->tv_sec - tv1->tv_sec ) * AIO_TICKS
163 + ((tv2->tv_usec - tv1->tv_usec) >> 10); 133 + ((tv2->tv_usec - tv1->tv_usec) >> 10);
164} 134}
165 135
166static pthread_t main_tid; 136static thread_t main_tid;
167static int main_sig; 137static int main_sig;
168static int block_sig_level; 138static int block_sig_level;
169 139
170void block_sig () 140void block_sig ()
171{ 141{
199 169
200static int next_pri = DEFAULT_PRI + PRI_BIAS; 170static int next_pri = DEFAULT_PRI + PRI_BIAS;
201 171
202static unsigned int started, idle, wanted; 172static unsigned int started, idle, wanted;
203 173
204#if __linux && defined (PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP)
205# define AIO_MUTEX_INIT PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
206#else
207# define AIO_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
208#endif
209
210#define LOCK(mutex) pthread_mutex_lock (&(mutex))
211#define UNLOCK(mutex) pthread_mutex_unlock (&(mutex))
212
213/* worker threads management */ 174/* worker threads management */
214static pthread_mutex_t wrklock = AIO_MUTEX_INIT; 175static mutex_t wrklock = MUTEX_INIT;
215 176
216typedef struct worker { 177typedef struct worker {
217 /* locked by wrklock */ 178 /* locked by wrklock */
218 struct worker *prev, *next; 179 struct worker *prev, *next;
219 180
220 pthread_t tid; 181 thread_t tid;
221 182
222 /* locked by reslock, reqlock or wrklock */ 183 /* locked by reslock, reqlock or wrklock */
223 aio_req req; /* currently processed request */ 184 aio_req req; /* currently processed request */
224 void *dbuf; 185 void *dbuf;
225 DIR *dirp; 186 DIR *dirp;
253static volatile unsigned int nreqs, nready, npending; 214static volatile unsigned int nreqs, nready, npending;
254static volatile unsigned int max_idle = 4; 215static volatile unsigned int max_idle = 4;
255static volatile unsigned int max_outstanding = 0xffffffff; 216static volatile unsigned int max_outstanding = 0xffffffff;
256static int respipe [2]; 217static int respipe [2];
257 218
258static pthread_mutex_t reslock = AIO_MUTEX_INIT; 219static mutex_t reslock = MUTEX_INIT;
259static pthread_mutex_t reqlock = AIO_MUTEX_INIT; 220static mutex_t reqlock = MUTEX_INIT;
260static pthread_cond_t reqwait = PTHREAD_COND_INITIALIZER; 221static cond_t reqwait = COND_INIT;
261 222
262#if WORDACCESS_UNSAFE 223#if WORDACCESS_UNSAFE
263 224
264static unsigned int get_nready () 225static unsigned int get_nready ()
265{ 226{
446 407
447static int req_invoke (aio_req req) 408static int req_invoke (aio_req req)
448{ 409{
449 dSP; 410 dSP;
450 411
451 if (req->flags & FLAG_SV1_RO_OFF) 412 if (req->flags & FLAG_SV2_RO_OFF)
452 SvREADONLY_off (req->sv1); 413 SvREADONLY_off (req->sv2);
453 414
454 if (!(req->flags & FLAG_CANCELLED) && SvOK (req->callback)) 415 if (!(req->flags & FLAG_CANCELLED) && SvOK (req->callback))
455 { 416 {
456 ENTER; 417 ENTER;
457 SAVETMPS; 418 SAVETMPS;
522 break; 483 break;
523 484
524 case REQ_READLINK: 485 case REQ_READLINK:
525 if (req->result > 0) 486 if (req->result > 0)
526 { 487 {
527 SvCUR_set (req->sv1, req->result); 488 SvCUR_set (req->sv2, req->result);
528 *SvEND (req->sv1) = 0; 489 *SvEND (req->sv2) = 0;
529 PUSHs (req->sv1); 490 PUSHs (req->sv2);
530 } 491 }
531 break; 492 break;
532 493
533 case REQ_STAT: 494 case REQ_STAT:
534 case REQ_LSTAT: 495 case REQ_LSTAT:
538 PL_statcache = *(Stat_t *)(req->ptr2); 499 PL_statcache = *(Stat_t *)(req->ptr2);
539 PUSHs (sv_2mortal (newSViv (req->result))); 500 PUSHs (sv_2mortal (newSViv (req->result)));
540 break; 501 break;
541 502
542 case REQ_READ: 503 case REQ_READ:
543 SvCUR_set (req->sv1, req->stroffset + (req->result > 0 ? req->result : 0)); 504 SvCUR_set (req->sv2, req->stroffset + (req->result > 0 ? req->result : 0));
544 *SvEND (req->sv1) = 0; 505 *SvEND (req->sv2) = 0;
545 PUSHs (sv_2mortal (newSViv (req->result))); 506 PUSHs (sv_2mortal (newSViv (req->result)));
546 break; 507 break;
547 508
548 default: 509 default:
549 PUSHs (sv_2mortal (newSViv (req->result))); 510 PUSHs (sv_2mortal (newSViv (req->result)));
583 { 544 {
584 sv_unmagic (req->self, PERL_MAGIC_ext); 545 sv_unmagic (req->self, PERL_MAGIC_ext);
585 SvREFCNT_dec (req->self); 546 SvREFCNT_dec (req->self);
586 } 547 }
587 548
588 SvREFCNT_dec (req->fh);
589 SvREFCNT_dec (req->sv1); 549 SvREFCNT_dec (req->sv1);
590 SvREFCNT_dec (req->sv2); 550 SvREFCNT_dec (req->sv2);
591 SvREFCNT_dec (req->callback); 551 SvREFCNT_dec (req->callback);
592 552
593 if (req->flags & FLAG_PTR2_FREE) 553 if (req->flags & FLAG_PTR2_FREE)
619 579
620static void *aio_proc(void *arg); 580static void *aio_proc(void *arg);
621 581
622static void start_thread (void) 582static void start_thread (void)
623{ 583{
624 sigset_t fullsigset, oldsigset;
625 pthread_attr_t attr;
626
627 worker *wrk = calloc (1, sizeof (worker)); 584 worker *wrk = calloc (1, sizeof (worker));
628 585
629 if (!wrk) 586 if (!wrk)
630 croak ("unable to allocate worker thread data"); 587 croak ("unable to allocate worker thread data");
631 588
632 pthread_attr_init (&attr);
633 pthread_attr_setstacksize (&attr, STACKSIZE);
634 pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
635#ifdef PTHREAD_SCOPE_PROCESS
636 pthread_attr_setscope (&attr, PTHREAD_SCOPE_PROCESS);
637#endif
638
639 sigfillset (&fullsigset);
640
641 LOCK (wrklock); 589 LOCK (wrklock);
642 pthread_sigmask (SIG_SETMASK, &fullsigset, &oldsigset);
643 590
644 if (pthread_create (&wrk->tid, &attr, aio_proc, (void *)wrk) == 0) 591 if (thread_create (&wrk->tid, aio_proc, (void *)wrk))
645 { 592 {
646 wrk->prev = &wrk_first; 593 wrk->prev = &wrk_first;
647 wrk->next = wrk_first.next; 594 wrk->next = wrk_first.next;
648 wrk_first.next->prev = wrk; 595 wrk_first.next->prev = wrk;
649 wrk_first.next = wrk; 596 wrk_first.next = wrk;
650 ++started; 597 ++started;
651 } 598 }
652 else 599 else
653 free (wrk); 600 free (wrk);
654 601
655 pthread_sigmask (SIG_SETMASK, &oldsigset, 0);
656 UNLOCK (wrklock); 602 UNLOCK (wrklock);
657} 603}
658 604
659static void maybe_start_thread () 605static void maybe_start_thread ()
660{ 606{
675 ++nreqs; 621 ++nreqs;
676 622
677 LOCK (reqlock); 623 LOCK (reqlock);
678 ++nready; 624 ++nready;
679 reqq_push (&req_queue, req); 625 reqq_push (&req_queue, req);
680 pthread_cond_signal (&reqwait); 626 COND_SIGNAL (reqwait);
681 UNLOCK (reqlock); 627 UNLOCK (reqlock);
682 628
683 unblock_sig (); 629 unblock_sig ();
684 630
685 maybe_start_thread (); 631 maybe_start_thread ();
694 req->type = REQ_QUIT; 640 req->type = REQ_QUIT;
695 req->pri = PRI_MAX + PRI_BIAS; 641 req->pri = PRI_MAX + PRI_BIAS;
696 642
697 LOCK (reqlock); 643 LOCK (reqlock);
698 reqq_push (&req_queue, req); 644 reqq_push (&req_queue, req);
699 pthread_cond_signal (&reqwait); 645 COND_SIGNAL (reqwait);
700 UNLOCK (reqlock); 646 UNLOCK (reqlock);
701 647
702 LOCK (wrklock); 648 LOCK (wrklock);
703 --started; 649 --started;
704 UNLOCK (wrklock); 650 UNLOCK (wrklock);
857/* 803/*
858 * make our pread/pwrite safe against themselves, but not against 804 * make our pread/pwrite safe against themselves, but not against
859 * normal read/write by using a mutex. slows down execution a lot, 805 * normal read/write by using a mutex. slows down execution a lot,
860 * but that's your problem, not mine. 806 * but that's your problem, not mine.
861 */ 807 */
862static pthread_mutex_t preadwritelock = PTHREAD_MUTEX_INITIALIZER; 808static mutex_t preadwritelock = MUTEX_INIT;
863 809
864static ssize_t pread (int fd, void *buf, size_t count, off_t offset) 810static ssize_t pread (int fd, void *buf, size_t count, off_t offset)
865{ 811{
866 ssize_t res; 812 ssize_t res;
867 off_t ooffset; 813 off_t ooffset;
890 836
891 return res; 837 return res;
892} 838}
893#endif 839#endif
894 840
841#ifndef HAVE_FUTIMES
842
843# define utimes(path,times) aio_utimes (path, times)
844# define futimes(fd,times) aio_futimes (fd, times)
845
846int aio_utimes (const char *filename, const struct timeval times[2])
847{
848 if (times)
849 {
850 struct utimbuf buf;
851
852 buf.actime = times[0].tv_sec;
853 buf.modtime = times[1].tv_sec;
854
855 return utime (filename, &buf);
856 }
857 else
858 return utime (filename, 0);
859}
860
861int aio_futimes (int fd, const struct timeval tv[2])
862{
863 errno = ENOSYS;
864 return -1;
865}
866
867#endif
868
895#if !HAVE_FDATASYNC 869#if !HAVE_FDATASYNC
896# define fdatasync fsync 870# define fdatasync fsync
897#endif 871#endif
898 872
899#if !HAVE_READAHEAD 873#if !HAVE_READAHEAD
918#endif 892#endif
919 893
920#if !HAVE_READDIR_R 894#if !HAVE_READDIR_R
921# define readdir_r aio_readdir_r 895# define readdir_r aio_readdir_r
922 896
923static pthread_mutex_t readdirlock = PTHREAD_MUTEX_INITIALIZER; 897static mutex_t readdirlock = MUTEX_INIT;
924 898
925static int readdir_r (DIR *dirp, struct dirent *ent, struct dirent **res) 899static int readdir_r (DIR *dirp, struct dirent *ent, struct dirent **res)
926{ 900{
927 struct dirent *e; 901 struct dirent *e;
928 int errorno; 902 int errorno;
1127 if (req) 1101 if (req)
1128 break; 1102 break;
1129 1103
1130 ++idle; 1104 ++idle;
1131 1105
1132 if (pthread_cond_timedwait (&reqwait, &reqlock, &ts) 1106 if (COND_TIMEDWAIT (reqwait, reqlock, ts)
1133 == ETIMEDOUT) 1107 == ETIMEDOUT)
1134 { 1108 {
1135 if (idle > max_idle) 1109 if (idle > max_idle)
1136 { 1110 {
1137 --idle; 1111 --idle;
1141 UNLOCK (wrklock); 1115 UNLOCK (wrklock);
1142 goto quit; 1116 goto quit;
1143 } 1117 }
1144 1118
1145 /* we are allowed to idle, so do so without any timeout */ 1119 /* we are allowed to idle, so do so without any timeout */
1146 pthread_cond_wait (&reqwait, &reqlock); 1120 COND_WAIT (reqwait, reqlock);
1147 ts.tv_sec = time (0) + IDLE_TIMEOUT; 1121 ts.tv_sec = time (0) + IDLE_TIMEOUT;
1148 } 1122 }
1149 1123
1150 --idle; 1124 --idle;
1151 } 1125 }
1167 1141
1168 case REQ_STAT: req->result = stat (req->ptr1, (Stat_t *)req->ptr2); break; 1142 case REQ_STAT: req->result = stat (req->ptr1, (Stat_t *)req->ptr2); break;
1169 case REQ_LSTAT: req->result = lstat (req->ptr1, (Stat_t *)req->ptr2); break; 1143 case REQ_LSTAT: req->result = lstat (req->ptr1, (Stat_t *)req->ptr2); break;
1170 case REQ_FSTAT: req->result = fstat (req->int1, (Stat_t *)req->ptr2); break; 1144 case REQ_FSTAT: req->result = fstat (req->int1, (Stat_t *)req->ptr2); break;
1171 1145
1146 case REQ_CHOWN: req->result = chown (req->ptr1, req->int2, req->int3); break;
1147 case REQ_FCHOWN: req->result = fchown (req->int1, req->int2, req->int3); break;
1148 case REQ_CHMOD: req->result = chmod (req->ptr1, req->mode); break;
1149 case REQ_FCHMOD: req->result = fchmod (req->int1, req->mode); break;
1150
1172 case REQ_OPEN: req->result = open (req->ptr1, req->int1, req->mode); break; 1151 case REQ_OPEN: req->result = open (req->ptr1, req->int1, req->mode); break;
1173 case REQ_CLOSE: req->result = close (req->int1); break; 1152 case REQ_CLOSE: req->result = close (req->int1); break;
1174 case REQ_UNLINK: req->result = unlink (req->ptr1); break; 1153 case REQ_UNLINK: req->result = unlink (req->ptr1); break;
1175 case REQ_RMDIR: req->result = rmdir (req->ptr1); break; 1154 case REQ_RMDIR: req->result = rmdir (req->ptr1); break;
1155 case REQ_MKDIR: req->result = mkdir (req->ptr1, req->mode); break;
1176 case REQ_RENAME: req->result = rename (req->ptr2, req->ptr1); break; 1156 case REQ_RENAME: req->result = rename (req->ptr2, req->ptr1); break;
1177 case REQ_LINK: req->result = link (req->ptr2, req->ptr1); break; 1157 case REQ_LINK: req->result = link (req->ptr2, req->ptr1); break;
1178 case REQ_SYMLINK: req->result = symlink (req->ptr2, req->ptr1); break; 1158 case REQ_SYMLINK: req->result = symlink (req->ptr2, req->ptr1); break;
1179 case REQ_MKNOD: req->result = mknod (req->ptr2, req->mode, (dev_t)req->offs); break; 1159 case REQ_MKNOD: req->result = mknod (req->ptr2, req->mode, (dev_t)req->offs); break;
1180 case REQ_READLINK: req->result = readlink (req->ptr2, req->ptr1, NAME_MAX); break; 1160 case REQ_READLINK: req->result = readlink (req->ptr2, req->ptr1, NAME_MAX); break;
1185 1165
1186 case REQ_BUSY: 1166 case REQ_BUSY:
1187 { 1167 {
1188 struct timeval tv; 1168 struct timeval tv;
1189 1169
1190 tv.tv_sec = req->int1; 1170 tv.tv_sec = req->nv1;
1191 tv.tv_usec = req->int2; 1171 tv.tv_usec = (req->nv1 - tv.tv_usec) * 1000000.;
1192 1172
1193 req->result = select (0, 0, 0, 0, &tv); 1173 req->result = select (0, 0, 0, 0, &tv);
1174 }
1175
1176 case REQ_UTIME:
1177 case REQ_FUTIME:
1178 {
1179 struct timeval tv[2];
1180 struct timeval *times;
1181
1182 if (req->nv1 != -1. || req->nv2 != -1.)
1183 {
1184 tv[0].tv_sec = req->nv1;
1185 tv[0].tv_usec = (req->nv1 - tv[0].tv_sec) * 1000000.;
1186 tv[1].tv_sec = req->nv2;
1187 tv[1].tv_usec = (req->nv2 - tv[1].tv_sec) * 1000000.;
1188
1189 times = tv;
1190 }
1191 else
1192 times = 0;
1193
1194
1195 req->result = req->type == REQ_FUTIME
1196 ? futimes (req->int1, times)
1197 : utimes (req->ptr1, times);
1194 } 1198 }
1195 1199
1196 case REQ_GROUP: 1200 case REQ_GROUP:
1197 case REQ_NOP: 1201 case REQ_NOP:
1198 break; 1202 break;
1199 1203
1200 case REQ_QUIT: 1204 case REQ_QUIT:
1201 goto quit; 1205 goto quit;
1202 1206
1203 default: 1207 default:
1204 req->result = ENOSYS; 1208 req->result = -1;
1205 break; 1209 break;
1206 } 1210 }
1207 1211
1208 req->errorno = errno; 1212 req->errorno = errno;
1209 1213
1333 newCONSTSUB (stash, "O_TRUNC", newSViv (O_TRUNC)); 1337 newCONSTSUB (stash, "O_TRUNC", newSViv (O_TRUNC));
1334 newCONSTSUB (stash, "S_IFIFO", newSViv (S_IFIFO)); 1338 newCONSTSUB (stash, "S_IFIFO", newSViv (S_IFIFO));
1335 newCONSTSUB (stash, "SIGIO", newSViv (SIGIO)); 1339 newCONSTSUB (stash, "SIGIO", newSViv (SIGIO));
1336 1340
1337 create_pipe (); 1341 create_pipe ();
1338 pthread_atfork (atfork_prepare, atfork_parent, atfork_child); 1342 ATFORK (atfork_prepare, atfork_parent, atfork_child);
1339} 1343}
1340 1344
1341void 1345void
1342max_poll_reqs (int nreqs) 1346max_poll_reqs (int nreqs)
1343 PROTOTYPE: $ 1347 PROTOTYPE: $
1372 max_outstanding = maxreqs; 1376 max_outstanding = maxreqs;
1373 OUTPUT: 1377 OUTPUT:
1374 RETVAL 1378 RETVAL
1375 1379
1376void 1380void
1377aio_open (pathname,flags,mode,callback=&PL_sv_undef) 1381aio_open (SV8 *pathname, int flags, int mode, SV *callback=&PL_sv_undef)
1378 SV8 * pathname
1379 int flags
1380 int mode
1381 SV * callback
1382 PROTOTYPE: $$$;$ 1382 PROTOTYPE: $$$;$
1383 PPCODE: 1383 PPCODE:
1384{ 1384{
1385 dREQ; 1385 dREQ;
1386 1386
1392 1392
1393 REQ_SEND; 1393 REQ_SEND;
1394} 1394}
1395 1395
1396void 1396void
1397aio_close (fh,callback=&PL_sv_undef) 1397aio_close (SV *fh, SV *callback=&PL_sv_undef)
1398 SV * fh
1399 SV * callback
1400 PROTOTYPE: $;$ 1398 PROTOTYPE: $;$
1401 ALIAS: 1399 ALIAS:
1402 aio_close = REQ_CLOSE 1400 aio_close = REQ_CLOSE
1403 aio_fsync = REQ_FSYNC 1401 aio_fsync = REQ_FSYNC
1404 aio_fdatasync = REQ_FDATASYNC 1402 aio_fdatasync = REQ_FDATASYNC
1405 PPCODE: 1403 PPCODE:
1406{ 1404{
1407 dREQ; 1405 dREQ;
1408 1406
1409 req->type = ix; 1407 req->type = ix;
1410 req->fh = newSVsv (fh); 1408 req->sv1 = newSVsv (fh);
1411 req->int1 = PerlIO_fileno (IoIFP (sv_2io (fh))); 1409 req->int1 = PerlIO_fileno (IoIFP (sv_2io (fh)));
1412 1410
1413 REQ_SEND (req); 1411 REQ_SEND (req);
1414} 1412}
1415 1413
1416void 1414void
1417aio_read (fh,offset,length,data,dataoffset,callback=&PL_sv_undef) 1415aio_read (SV *fh, UV offset, UV length, SV8 *data, UV dataoffset, SV *callback=&PL_sv_undef)
1418 SV * fh
1419 UV offset
1420 UV length
1421 SV8 * data
1422 UV dataoffset
1423 SV * callback
1424 ALIAS: 1416 ALIAS:
1425 aio_read = REQ_READ 1417 aio_read = REQ_READ
1426 aio_write = REQ_WRITE 1418 aio_write = REQ_WRITE
1427 PROTOTYPE: $$$$$;$ 1419 PROTOTYPE: $$$$$;$
1428 PPCODE: 1420 PPCODE:
1456 1448
1457 { 1449 {
1458 dREQ; 1450 dREQ;
1459 1451
1460 req->type = ix; 1452 req->type = ix;
1461 req->fh = newSVsv (fh); 1453 req->sv1 = newSVsv (fh);
1462 req->int1 = PerlIO_fileno (ix == REQ_READ ? IoIFP (sv_2io (fh)) 1454 req->int1 = PerlIO_fileno (ix == REQ_READ ? IoIFP (sv_2io (fh))
1463 : IoOFP (sv_2io (fh))); 1455 : IoOFP (sv_2io (fh)));
1464 req->offs = offset; 1456 req->offs = offset;
1465 req->size = length; 1457 req->size = length;
1466 req->sv1 = SvREFCNT_inc (data); 1458 req->sv2 = SvREFCNT_inc (data);
1467 req->ptr1 = (char *)svptr + dataoffset; 1459 req->ptr1 = (char *)svptr + dataoffset;
1468 req->stroffset = dataoffset; 1460 req->stroffset = dataoffset;
1469 1461
1470 if (!SvREADONLY (data)) 1462 if (!SvREADONLY (data))
1471 { 1463 {
1472 SvREADONLY_on (data); 1464 SvREADONLY_on (data);
1473 req->flags |= FLAG_SV1_RO_OFF; 1465 req->flags |= FLAG_SV2_RO_OFF;
1474 } 1466 }
1475 1467
1476 REQ_SEND; 1468 REQ_SEND;
1477 } 1469 }
1478} 1470}
1479 1471
1480void 1472void
1481aio_readlink (path,callback=&PL_sv_undef) 1473aio_readlink (SV8 *path, SV *callback=&PL_sv_undef)
1482 SV8 * path
1483 SV * callback
1484 PROTOTYPE: $$;$ 1474 PROTOTYPE: $$;$
1485 PPCODE: 1475 PPCODE:
1486{ 1476{
1487 SV *data; 1477 SV *data;
1488 dREQ; 1478 dREQ;
1489 1479
1490 data = newSV (NAME_MAX); 1480 data = newSV (NAME_MAX);
1491 SvPOK_on (data); 1481 SvPOK_on (data);
1492 1482
1493 req->type = REQ_READLINK; 1483 req->type = REQ_READLINK;
1494 req->fh = newSVsv (path); 1484 req->sv1 = newSVsv (path);
1495 req->ptr2 = SvPVbyte_nolen (req->fh); 1485 req->ptr2 = SvPVbyte_nolen (req->sv1);
1496 req->sv1 = data; 1486 req->sv2 = data;
1497 req->ptr1 = SvPVbyte_nolen (data); 1487 req->ptr1 = SvPVbyte_nolen (data);
1498 1488
1499 REQ_SEND; 1489 REQ_SEND;
1500} 1490}
1501 1491
1502void 1492void
1503aio_sendfile (out_fh,in_fh,in_offset,length,callback=&PL_sv_undef) 1493aio_sendfile (SV *out_fh, SV *in_fh, UV in_offset, UV length, SV *callback=&PL_sv_undef)
1504 SV * out_fh
1505 SV * in_fh
1506 UV in_offset
1507 UV length
1508 SV * callback
1509 PROTOTYPE: $$$$;$ 1494 PROTOTYPE: $$$$;$
1510 PPCODE: 1495 PPCODE:
1511{ 1496{
1512 dREQ; 1497 dREQ;
1513 1498
1514 req->type = REQ_SENDFILE; 1499 req->type = REQ_SENDFILE;
1515 req->fh = newSVsv (out_fh); 1500 req->sv1 = newSVsv (out_fh);
1516 req->int1 = PerlIO_fileno (IoIFP (sv_2io (out_fh))); 1501 req->int1 = PerlIO_fileno (IoIFP (sv_2io (out_fh)));
1517 req->sv2 = newSVsv (in_fh); 1502 req->sv2 = newSVsv (in_fh);
1518 req->int2 = PerlIO_fileno (IoIFP (sv_2io (in_fh))); 1503 req->int2 = PerlIO_fileno (IoIFP (sv_2io (in_fh)));
1519 req->offs = in_offset; 1504 req->offs = in_offset;
1520 req->size = length; 1505 req->size = length;
1521 1506
1522 REQ_SEND; 1507 REQ_SEND;
1523} 1508}
1524 1509
1525void 1510void
1526aio_readahead (fh,offset,length,callback=&PL_sv_undef) 1511aio_readahead (SV *fh, UV offset, IV length, SV *callback=&PL_sv_undef)
1527 SV * fh
1528 UV offset
1529 IV length
1530 SV * callback
1531 PROTOTYPE: $$$;$ 1512 PROTOTYPE: $$$;$
1532 PPCODE: 1513 PPCODE:
1533{ 1514{
1534 dREQ; 1515 dREQ;
1535 1516
1536 req->type = REQ_READAHEAD; 1517 req->type = REQ_READAHEAD;
1537 req->fh = newSVsv (fh); 1518 req->sv1 = newSVsv (fh);
1538 req->int1 = PerlIO_fileno (IoIFP (sv_2io (fh))); 1519 req->int1 = PerlIO_fileno (IoIFP (sv_2io (fh)));
1539 req->offs = offset; 1520 req->offs = offset;
1540 req->size = length; 1521 req->size = length;
1541 1522
1542 REQ_SEND; 1523 REQ_SEND;
1543} 1524}
1544 1525
1545void 1526void
1546aio_stat (fh_or_path,callback=&PL_sv_undef) 1527aio_stat (SV8 *fh_or_path, SV *callback=&PL_sv_undef)
1547 SV8 * fh_or_path
1548 SV * callback
1549 ALIAS: 1528 ALIAS:
1550 aio_stat = REQ_STAT 1529 aio_stat = REQ_STAT
1551 aio_lstat = REQ_LSTAT 1530 aio_lstat = REQ_LSTAT
1552 PPCODE: 1531 PPCODE:
1553{ 1532{
1559 req_free (req); 1538 req_free (req);
1560 croak ("out of memory during aio_stat statdata allocation"); 1539 croak ("out of memory during aio_stat statdata allocation");
1561 } 1540 }
1562 1541
1563 req->flags |= FLAG_PTR2_FREE; 1542 req->flags |= FLAG_PTR2_FREE;
1543 req->sv1 = newSVsv (fh_or_path);
1564 1544
1565 if (SvPOK (fh_or_path)) 1545 if (SvPOK (fh_or_path))
1566 { 1546 {
1567 req->type = ix; 1547 req->type = ix;
1568 req->sv1 = newSVsv (fh_or_path);
1569 req->ptr1 = SvPVbyte_nolen (req->sv1); 1548 req->ptr1 = SvPVbyte_nolen (req->sv1);
1570 } 1549 }
1571 else 1550 else
1572 { 1551 {
1573 req->type = REQ_FSTAT; 1552 req->type = REQ_FSTAT;
1574 req->fh = newSVsv (fh_or_path);
1575 req->int1 = PerlIO_fileno (IoIFP (sv_2io (fh_or_path))); 1553 req->int1 = PerlIO_fileno (IoIFP (sv_2io (fh_or_path)));
1576 } 1554 }
1577 1555
1578 REQ_SEND; 1556 REQ_SEND;
1579} 1557}
1580 1558
1581void 1559void
1560aio_utime (SV8 *fh_or_path, SV *atime, SV *mtime, SV *callback=&PL_sv_undef)
1561 PPCODE:
1562{
1563 dREQ;
1564
1565 req->nv1 = SvOK (atime) ? SvNV (atime) : -1.;
1566 req->nv2 = SvOK (mtime) ? SvNV (mtime) : -1.;
1567 req->sv1 = newSVsv (fh_or_path);
1568
1569 if (SvPOK (fh_or_path))
1570 {
1571 req->type = REQ_UTIME;
1572 req->ptr1 = SvPVbyte_nolen (req->sv1);
1573 }
1574 else
1575 {
1576 req->type = REQ_FUTIME;
1577 req->int1 = PerlIO_fileno (IoIFP (sv_2io (fh_or_path)));
1578 }
1579
1580 REQ_SEND;
1581}
1582
1583void
1584aio_chmod (SV8 *fh_or_path, int mode, SV *callback=&PL_sv_undef)
1585 PPCODE:
1586{
1587 dREQ;
1588
1589 req->mode = mode;
1590 req->sv1 = newSVsv (fh_or_path);
1591
1592 if (SvPOK (fh_or_path))
1593 {
1594 req->type = REQ_CHMOD;
1595 req->ptr1 = SvPVbyte_nolen (req->sv1);
1596 }
1597 else
1598 {
1599 req->type = REQ_FCHMOD;
1600 req->int1 = PerlIO_fileno (IoIFP (sv_2io (fh_or_path)));
1601 }
1602
1603 REQ_SEND;
1604}
1605
1606void
1607aio_chown (SV8 *fh_or_path, SV *uid, SV *gid, SV *callback=&PL_sv_undef)
1608 PPCODE:
1609{
1610 dREQ;
1611
1612 req->int2 = SvOK (uid) ? SvIV (uid) : -1;
1613 req->int3 = SvOK (gid) ? SvIV (gid) : -1;
1614 req->sv1 = newSVsv (fh_or_path);
1615
1616 if (SvPOK (fh_or_path))
1617 {
1618 req->type = REQ_CHOWN;
1619 req->ptr1 = SvPVbyte_nolen (req->sv1);
1620 }
1621 else
1622 {
1623 req->type = REQ_FCHOWN;
1624 req->int1 = PerlIO_fileno (IoIFP (sv_2io (fh_or_path)));
1625 }
1626
1627 REQ_SEND;
1628}
1629
1630void
1582aio_unlink (pathname,callback=&PL_sv_undef) 1631aio_unlink (SV8 *pathname, SV *callback=&PL_sv_undef)
1583 SV8 * pathname
1584 SV * callback
1585 ALIAS: 1632 ALIAS:
1586 aio_unlink = REQ_UNLINK 1633 aio_unlink = REQ_UNLINK
1587 aio_rmdir = REQ_RMDIR 1634 aio_rmdir = REQ_RMDIR
1588 aio_readdir = REQ_READDIR 1635 aio_readdir = REQ_READDIR
1589 PPCODE: 1636 PPCODE:
1596 1643
1597 REQ_SEND; 1644 REQ_SEND;
1598} 1645}
1599 1646
1600void 1647void
1648aio_mkdir (SV8 *pathname, int mode, SV *callback=&PL_sv_undef)
1649 PPCODE:
1650{
1651 dREQ;
1652
1653 req->type = REQ_MKDIR;
1654 req->sv1 = newSVsv (pathname);
1655 req->ptr1 = SvPVbyte_nolen (req->sv1);
1656 req->mode = mode;
1657
1658 REQ_SEND;
1659}
1660
1661void
1601aio_link (oldpath,newpath,callback=&PL_sv_undef) 1662aio_link (SV8 *oldpath, SV8 *newpath, SV *callback=&PL_sv_undef)
1602 SV8 * oldpath
1603 SV8 * newpath
1604 SV * callback
1605 ALIAS: 1663 ALIAS:
1606 aio_link = REQ_LINK 1664 aio_link = REQ_LINK
1607 aio_symlink = REQ_SYMLINK 1665 aio_symlink = REQ_SYMLINK
1608 aio_rename = REQ_RENAME 1666 aio_rename = REQ_RENAME
1609 PPCODE: 1667 PPCODE:
1610{ 1668{
1611 dREQ; 1669 dREQ;
1612 1670
1613 req->type = ix; 1671 req->type = ix;
1614 req->fh = newSVsv (oldpath); 1672 req->sv2 = newSVsv (oldpath);
1615 req->ptr2 = SvPVbyte_nolen (req->fh); 1673 req->ptr2 = SvPVbyte_nolen (req->sv2);
1616 req->sv1 = newSVsv (newpath); 1674 req->sv1 = newSVsv (newpath);
1617 req->ptr1 = SvPVbyte_nolen (req->sv1); 1675 req->ptr1 = SvPVbyte_nolen (req->sv1);
1618 1676
1619 REQ_SEND; 1677 REQ_SEND;
1620} 1678}
1621 1679
1622void 1680void
1623aio_mknod (pathname,mode,dev,callback=&PL_sv_undef) 1681aio_mknod (SV8 *pathname, int mode, UV dev, SV *callback=&PL_sv_undef)
1624 SV8 * pathname
1625 SV * callback
1626 UV mode
1627 UV dev
1628 PPCODE: 1682 PPCODE:
1629{ 1683{
1630 dREQ; 1684 dREQ;
1631 1685
1632 req->type = REQ_MKNOD; 1686 req->type = REQ_MKNOD;
1637 1691
1638 REQ_SEND; 1692 REQ_SEND;
1639} 1693}
1640 1694
1641void 1695void
1642aio_busy (delay,callback=&PL_sv_undef) 1696aio_busy (double delay, SV *callback=&PL_sv_undef)
1643 double delay
1644 SV * callback
1645 PPCODE: 1697 PPCODE:
1646{ 1698{
1647 dREQ; 1699 dREQ;
1648 1700
1649 req->type = REQ_BUSY; 1701 req->type = REQ_BUSY;
1650 req->int1 = delay < 0. ? 0 : delay; 1702 req->nv1 = delay < 0. ? 0. : delay;
1651 req->int2 = delay < 0. ? 0 : 1000. * (delay - req->int1);
1652 1703
1653 REQ_SEND; 1704 REQ_SEND;
1654} 1705}
1655 1706
1656void 1707void
1657aio_group (callback=&PL_sv_undef) 1708aio_group (SV *callback=&PL_sv_undef)
1658 SV * callback
1659 PROTOTYPE: ;$ 1709 PROTOTYPE: ;$
1660 PPCODE: 1710 PPCODE:
1661{ 1711{
1662 dREQ; 1712 dREQ;
1663 1713
1666 req_send (req); 1716 req_send (req);
1667 XPUSHs (req_sv (req, AIO_GRP_KLASS)); 1717 XPUSHs (req_sv (req, AIO_GRP_KLASS));
1668} 1718}
1669 1719
1670void 1720void
1671aio_nop (callback=&PL_sv_undef) 1721aio_nop (SV *callback=&PL_sv_undef)
1672 SV * callback
1673 PPCODE: 1722 PPCODE:
1674{ 1723{
1675 dREQ; 1724 dREQ;
1676 1725
1677 req->type = REQ_NOP; 1726 req->type = REQ_NOP;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines