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

Comparing Linux-AIO/AIO.xs (file contents):
Revision 1.13 by root, Mon Apr 1 20:30:08 2002 UTC vs.
Revision 1.17 by root, Thu May 6 12:16:48 2004 UTC

1#define PERL_NO_GET_CONTEXT
2
1#include "EXTERN.h" 3#include "EXTERN.h"
2#include "perl.h" 4#include "perl.h"
3#include "XSUB.h" 5#include "XSUB.h"
4 6
5#include <sys/types.h> 7#include <sys/types.h>
11 13
12typedef void *InputStream; /* hack, but 5.6.1 is simply toooo old ;) */ 14typedef void *InputStream; /* hack, but 5.6.1 is simply toooo old ;) */
13typedef void *OutputStream; /* hack, but 5.6.1 is simply toooo old ;) */ 15typedef void *OutputStream; /* hack, but 5.6.1 is simply toooo old ;) */
14typedef void *InOutStream; /* hack, but 5.6.1 is simply toooo old ;) */ 16typedef void *InOutStream; /* hack, but 5.6.1 is simply toooo old ;) */
15 17
18#ifndef __NR_pread64
19# define __NR_pread64 __NR_pread
20#endif
21#ifndef __NR_pwrite64
22# define __NR_pwrite64 __NR_pwrite
23#endif
24
16#define STACKSIZE 1024 /* yeah */ 25#define STACKSIZE 1024 /* yeah */
17 26
18enum { REQ_QUIT, REQ_OPEN, REQ_CLOSE, REQ_READ, REQ_WRITE, REQ_STAT, REQ_LSTAT, REQ_FSTAT}; 27enum { REQ_QUIT, REQ_OPEN, REQ_CLOSE, REQ_READ, REQ_WRITE, REQ_STAT, REQ_LSTAT, REQ_FSTAT};
19 28
20typedef struct { 29typedef struct {
22} aio_thread; 31} aio_thread;
23 32
24typedef struct { 33typedef struct {
25 int type; 34 int type;
26 aio_thread *thread; 35 aio_thread *thread;
27
28 SV *savesv;
29 36
30 int fd; 37 int fd;
31 off_t offset; 38 off_t offset;
32 size_t length; 39 size_t length;
33 ssize_t result; 40 ssize_t result;
79 nreqs++; 86 nreqs++;
80 write (reqpipe[1], &req, sizeof (aio_req)); 87 write (reqpipe[1], &req, sizeof (aio_req));
81} 88}
82 89
83static void 90static void
91read_write (pTHX_
84read_write (pTHX_ int dowrite, int fd, off_t offset, size_t length, 92 int dowrite, int fd, off_t offset, size_t length,
85 SV *data, STRLEN dataoffset, SV*callback) 93 SV *data, STRLEN dataoffset, SV*callback)
86{ 94{
87 aio_req req; 95 aio_req req;
88 STRLEN svlen; 96 STRLEN svlen;
89 char *svptr = SvPV (data, svlen); 97 char *svptr = SvPV (data, svlen);
110 } 118 }
111 119
112 if (length < 0) 120 if (length < 0)
113 croak ("length must not be negative"); 121 croak ("length must not be negative");
114 122
115 New (0, req, 1, aio_cb); 123 Newz (0, req, 1, aio_cb);
116 124
117 if (!req) 125 if (!req)
118 croak ("out of memory during aio_req allocation"); 126 croak ("out of memory during aio_req allocation");
119 127
120 req->type = dowrite ? REQ_WRITE : REQ_READ; 128 req->type = dowrite ? REQ_WRITE : REQ_READ;
145 else 153 else
146 { 154 {
147 int errorno = errno; 155 int errorno = errno;
148 errno = req->errorno; 156 errno = req->errorno;
149 157
150 if (req->savesv)
151 SvREFCNT_dec (req->savesv);
152
153 if (req->type == REQ_READ) 158 if (req->type == REQ_READ)
154 SvCUR_set (req->data, req->dataoffset 159 SvCUR_set (req->data, req->dataoffset
155 + req->result > 0 ? req->result : 0); 160 + req->result > 0 ? req->result : 0);
161
162 if (req->data)
163 SvREFCNT_dec (req->data);
156 164
157 if (req->type == REQ_STAT || req->type == REQ_LSTAT || req->type == REQ_FSTAT) 165 if (req->type == REQ_STAT || req->type == REQ_LSTAT || req->type == REQ_FSTAT)
158 { 166 {
159 PL_laststype = req->type == REQ_LSTAT ? OP_LSTAT : OP_STAT; 167 PL_laststype = req->type == REQ_LSTAT ? OP_LSTAT : OP_STAT;
160 PL_laststatval = req->result; 168 PL_laststatval = req->result;
179 XPUSHs (sv_2mortal (newSViv (req->result))); 187 XPUSHs (sv_2mortal (newSViv (req->result)));
180 PUTBACK; 188 PUTBACK;
181 call_sv (req->callback, G_VOID); 189 call_sv (req->callback, G_VOID);
182 SPAGAIN; 190 SPAGAIN;
183 191
184 SvREFCNT_dec (req->data); 192 if (req->callback)
185 SvREFCNT_dec (req->callback); 193 SvREFCNT_dec (req->callback);
186 194
187 errno = errorno; 195 errno = errorno;
188 nreqs--; 196 nreqs--;
189 count++; 197 count++;
190 } 198 }
205{ 213{
206 aio_thread *thr = thr_arg; 214 aio_thread *thr = thr_arg;
207 aio_req req; 215 aio_req req;
208 int errno; 216 int errno;
209 217
218 /* this is very much x86 and kernel-specific :(:(:( */
210 /* we rely on gcc's ability to create closures. */ 219 /* we rely on gcc's ability to create closures. */
211 _syscall3(int,read,int,fd,char *,buf,size_t,count) 220 _syscall3(int,read,int,fd,char *,buf,size_t,count)
212 _syscall3(int,write,int,fd,char *,buf,size_t,count) 221 _syscall3(int,write,int,fd,char *,buf,size_t,count)
213 222
214 _syscall3(int,open,char *,pathname,int,flags,mode_t,mode) 223 _syscall3(int,open,char *,pathname,int,flags,mode_t,mode)
215 _syscall1(int,close,int,fd) 224 _syscall1(int,close,int,fd)
216 225
217 _syscall4(int,pread,int,fd,char *,buf,size_t,count,off_t,offset) 226 _syscall5(int,pread64,int,fd,char *,buf,size_t,count,unsigned int,offset_lo,unsigned int,offset_hi)
218 _syscall4(int,pwrite,int,fd,char *,buf,size_t,count,off_t,offset) 227 _syscall5(int,pwrite64,int,fd,char *,buf,size_t,count,unsigned int,offset_lo,unsigned int,offset_hi)
219 228
220 _syscall2(int,stat64, const char *, filename, struct stat64 *, buf) 229 _syscall2(int,stat64, const char *, filename, struct stat64 *, buf)
221 _syscall2(int,lstat64, const char *, filename, struct stat64 *, buf) 230 _syscall2(int,lstat64, const char *, filename, struct stat64 *, buf)
222 _syscall2(int,fstat64, int, fd, struct stat64 *, buf) 231 _syscall2(int,fstat64, int, fd, struct stat64 *, buf)
223 232
225 234
226 /* then loop */ 235 /* then loop */
227 while (read (reqpipe[0], (void *)&req, sizeof (req)) == sizeof (req)) 236 while (read (reqpipe[0], (void *)&req, sizeof (req)) == sizeof (req))
228 { 237 {
229 req->thread = thr; 238 req->thread = thr;
230 errno = 0; 239 errno = 0; /* strictly unnecessary */
231 240
232 if (req->type == REQ_READ) 241 if (req->type == REQ_READ)
233 req->result = pread (req->fd, req->dataptr, req->length, req->offset); 242 req->result = pread64 (req->fd, req->dataptr, req->length, req->offset & 0xffffffff, req->offset >> 32);
234 else if (req->type == REQ_WRITE) 243 else if (req->type == REQ_WRITE)
235 req->result = pwrite (req->fd, req->dataptr, req->length, req->offset); 244 req->result = pwrite64(req->fd, req->dataptr, req->length, req->offset & 0xffffffff, req->offset >> 32);
236 else if (req->type == REQ_OPEN) 245 else if (req->type == REQ_OPEN)
237 req->result = open (req->dataptr, req->fd, req->mode); 246 req->result = open (req->dataptr, req->fd, req->mode);
238 else if (req->type == REQ_CLOSE) 247 else if (req->type == REQ_CLOSE)
239 req->result = close (req->fd); 248 req->result = close (req->fd);
240 else if (req->type == REQ_STAT) 249 else if (req->type == REQ_STAT)
241 req->result = stat64 (req->dataptr, req->statdata); 250 req->result = stat64 (req->dataptr, req->statdata);
242 else if (req->type == REQ_LSTAT) 251 else if (req->type == REQ_LSTAT)
243 req->result = lstat64 (req->dataptr, req->statdata); 252 req->result = lstat64 (req->dataptr, req->statdata);
244 else if (req->type == REQ_FSTAT) 253 else if (req->type == REQ_FSTAT)
245 req->result = fstat64 (req->fd, req->statdata); 254 req->result = fstat64 (req->fd, req->statdata);
246 else 255 else
247 { 256 {
248 write (respipe[1], (void *)&req, sizeof (req)); 257 write (respipe[1], (void *)&req, sizeof (req));
249 break; 258 break;
250 } 259 }
291 { 300 {
292 end_thread (); 301 end_thread ();
293 cur--; 302 cur--;
294 } 303 }
295 304
296 poll_cb ();
297 while (started > nthreads) 305 while (started > nthreads)
298 { 306 {
299 sched_yield (); 307 fd_set rfd;
300 fcntl (respipe[0], F_SETFL, 0); 308 FD_ZERO(&rfd);
309 FD_SET(respipe[0], &rfd);
310
311 select (respipe[0] + 1, &rfd, 0, 0, 0);
301 poll_cb (); 312 poll_cb (aTHX);
302 fcntl (respipe[0], F_SETFL, O_NONBLOCK);
303 } 313 }
304 314
305void 315void
306aio_open(pathname,flags,mode,callback) 316aio_open(pathname,flags,mode,callback)
307 SV * pathname 317 SV * pathname
310 SV * callback 320 SV * callback
311 PROTOTYPE: $$$$ 321 PROTOTYPE: $$$$
312 CODE: 322 CODE:
313 aio_req req; 323 aio_req req;
314 324
315 New (0, req, 1, aio_cb); 325 Newz (0, req, 1, aio_cb);
316 326
317 if (!req) 327 if (!req)
318 croak ("out of memory during aio_req allocation"); 328 croak ("out of memory during aio_req allocation");
319 329
320 req->type = REQ_OPEN; 330 req->type = REQ_OPEN;
321 req->savesv = newSVsv (pathname); 331 req->data = newSVsv (pathname);
322 req->dataptr = SvPV_nolen (req->savesv); 332 req->dataptr = SvPV_nolen (req->data);
323 req->fd = flags; 333 req->fd = flags;
324 req->mode = mode; 334 req->mode = mode;
325 req->callback = SvREFCNT_inc (callback); 335 req->callback = SvREFCNT_inc (callback);
326 336
327 send_req (req); 337 send_req (req);
328 338
329void 339void
330aio_close(fh,callback) 340aio_close(fh,callback)
331 InputStream fh 341 InputStream fh
332 SV * callback 342 SV * callback
333 PROTOTYPE: $ 343 PROTOTYPE: $$
334 CODE: 344 CODE:
335 aio_req req; 345 aio_req req;
336 346
337 New (0, req, 1, aio_cb); 347 Newz (0, req, 1, aio_cb);
338 348
339 if (!req) 349 if (!req)
340 croak ("out of memory during aio_req allocation"); 350 croak ("out of memory during aio_req allocation");
341 351
342 req->type = REQ_CLOSE; 352 req->type = REQ_CLOSE;
377 ALIAS: 387 ALIAS:
378 aio_lstat = 1 388 aio_lstat = 1
379 CODE: 389 CODE:
380 aio_req req; 390 aio_req req;
381 391
382 New (0, req, 1, aio_cb); 392 Newz (0, req, 1, aio_cb);
383 393
384 if (!req) 394 if (!req)
385 croak ("out of memory during aio_req allocation"); 395 croak ("out of memory during aio_req allocation");
386 396
387 New (0, req->statdata, 1, struct stat64); 397 New (0, req->statdata, 1, struct stat64);
390 croak ("out of memory during aio_req->statdata allocation"); 400 croak ("out of memory during aio_req->statdata allocation");
391 401
392 if (SvPOK (fh_or_path)) 402 if (SvPOK (fh_or_path))
393 { 403 {
394 req->type = ix ? REQ_LSTAT : REQ_STAT; 404 req->type = ix ? REQ_LSTAT : REQ_STAT;
395 req->savesv = newSVsv (fh_or_path); 405 req->data = newSVsv (fh_or_path);
396 req->dataptr = SvPV_nolen (req->savesv); 406 req->dataptr = SvPV_nolen (req->data);
397 } 407 }
398 else 408 else
399 { 409 {
400 req->type = REQ_FSTAT; 410 req->type = REQ_FSTAT;
401 req->fd = PerlIO_fileno (IoIFP (sv_2io (fh_or_path))); 411 req->fd = PerlIO_fileno (IoIFP (sv_2io (fh_or_path)));

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines