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.100 by root, Fri Jun 1 06:00:40 2007 UTC vs.
Revision 1.102 by root, Sun Jun 3 09:44:17 2007 UTC

46#endif 46#endif
47 47
48/* buffer size for various temporary buffers */ 48/* buffer size for various temporary buffers */
49#define AIO_BUFSIZE 65536 49#define AIO_BUFSIZE 65536
50 50
51/* use NV for 32 bit perls as it allows larger offsets */
52#if IVSIZE >= 8
53# define SvVAL64 SvIV
54#else
55# define SvVAL64 SvNV
56#endif
57
51#define dBUF \ 58#define dBUF \
52 char *aio_buf; \ 59 char *aio_buf; \
53 LOCK (wrklock); \ 60 LOCK (wrklock); \
54 self->dbuf = aio_buf = malloc (AIO_BUFSIZE); \ 61 self->dbuf = aio_buf = malloc (AIO_BUFSIZE); \
55 UNLOCK (wrklock); \ 62 UNLOCK (wrklock); \
59typedef SV SV8; /* byte-sv, used for argument-checking */ 66typedef SV SV8; /* byte-sv, used for argument-checking */
60 67
61enum { 68enum {
62 REQ_QUIT, 69 REQ_QUIT,
63 REQ_OPEN, REQ_CLOSE, 70 REQ_OPEN, REQ_CLOSE,
64 REQ_READ, REQ_WRITE, REQ_READAHEAD, 71 REQ_READ, REQ_WRITE,
65 REQ_SENDFILE, 72 REQ_READAHEAD, REQ_SENDFILE,
66 REQ_STAT, REQ_LSTAT, REQ_FSTAT, 73 REQ_STAT, REQ_LSTAT, REQ_FSTAT,
67 REQ_UTIME, REQ_FUTIME, /* must be consecutive */ 74 REQ_UTIME, REQ_FUTIME,
68 REQ_CHMOD, REQ_FCHMOD, /* must be consecutive */ 75 REQ_CHMOD, REQ_FCHMOD,
69 REQ_CHOWN, REQ_FCHOWN, /* must be consecutive */ 76 REQ_CHOWN, REQ_FCHOWN,
70 REQ_FSYNC, REQ_FDATASYNC, 77 REQ_FSYNC, REQ_FDATASYNC,
71 REQ_UNLINK, REQ_RMDIR, REQ_MKDIR, REQ_RENAME, 78 REQ_UNLINK, REQ_RMDIR, REQ_MKDIR, REQ_RENAME,
72 REQ_MKNOD, REQ_READDIR, 79 REQ_MKNOD, REQ_READDIR,
73 REQ_LINK, REQ_SYMLINK, REQ_READLINK, 80 REQ_LINK, REQ_SYMLINK, REQ_READLINK,
74 REQ_GROUP, REQ_NOP, 81 REQ_GROUP, REQ_NOP,
317 abort (); 324 abort ();
318} 325}
319 326
320static int poll_cb (); 327static int poll_cb ();
321static int req_invoke (aio_req req); 328static int req_invoke (aio_req req);
322static void req_free (aio_req req); 329static void req_destroy (aio_req req);
323static void req_cancel (aio_req req); 330static void req_cancel (aio_req req);
324 331
325/* must be called at most once */ 332/* must be called at most once */
326static SV *req_sv (aio_req req, const char *klass) 333static SV *req_sv (aio_req req, const char *klass)
327{ 334{
393 { 400 {
394 block_sig (); 401 block_sig ();
395 402
396 if (!req_invoke (grp)) 403 if (!req_invoke (grp))
397 { 404 {
398 req_free (grp); 405 req_destroy (grp);
399 unblock_sig (); 406 unblock_sig ();
400 croak (0); 407 croak (0);
401 } 408 }
402 409
403 req_free (grp); 410 req_destroy (grp);
404 unblock_sig (); 411 unblock_sig ();
405 } 412 }
406} 413}
407 414
408static int req_invoke (aio_req req) 415static int req_invoke (aio_req req)
536 } 543 }
537 544
538 return !SvTRUE (ERRSV); 545 return !SvTRUE (ERRSV);
539} 546}
540 547
541static void req_free (aio_req req) 548static void req_destroy (aio_req req)
542{ 549{
543 if (req->self) 550 if (req->self)
544 { 551 {
545 sv_unmagic (req->self, PERL_MAGIC_ext); 552 sv_unmagic (req->self, PERL_MAGIC_ext);
546 SvREFCNT_dec (req->self); 553 SvREFCNT_dec (req->self);
575 req->flags |= FLAG_CANCELLED; 582 req->flags |= FLAG_CANCELLED;
576 583
577 req_cancel_subs (req); 584 req_cancel_subs (req);
578} 585}
579 586
580static void *aio_proc(void *arg); 587static void *aio_proc (void *arg);
581 588
582static void start_thread (void) 589static void start_thread (void)
583{ 590{
584 worker *wrk = calloc (1, sizeof (worker)); 591 worker *wrk = calloc (1, sizeof (worker));
585 592
745 } 752 }
746 else 753 else
747 { 754 {
748 if (!req_invoke (req)) 755 if (!req_invoke (req))
749 { 756 {
750 req_free (req); 757 req_destroy (req);
751 unblock_sig (); 758 unblock_sig ();
752 croak (0); 759 croak (0);
753 } 760 }
754 761
755 count++; 762 count++;
756 } 763 }
757 764
758 req_free (req); 765 req_destroy (req);
759 766
760 if (maxreqs && !--maxreqs) 767 if (maxreqs && !--maxreqs)
761 break; 768 break;
762 769
763 if (max_poll_time) 770 if (max_poll_time)
1131 errno = 0; /* strictly unnecessary */ 1138 errno = 0; /* strictly unnecessary */
1132 1139
1133 if (!(req->flags & FLAG_CANCELLED)) 1140 if (!(req->flags & FLAG_CANCELLED))
1134 switch (req->type) 1141 switch (req->type)
1135 { 1142 {
1136 case REQ_READ: req->result = pread (req->int1, req->ptr1, req->size, req->offs); break; 1143 case REQ_READ: req->result = req->offs >= 0
1137 case REQ_WRITE: req->result = pwrite (req->int1, req->ptr1, req->size, req->offs); break; 1144 ? pread (req->int1, req->ptr1, req->size, req->offs)
1145 : read (req->int1, req->ptr1, req->size); break;
1146 case REQ_WRITE: req->result = req->offs >= 0
1147 ? pwrite (req->int1, req->ptr1, req->size, req->offs)
1148 : write (req->int1, req->ptr1, req->size); break;
1138 1149
1139 case REQ_READAHEAD: req->result = readahead (req->int1, req->offs, req->size); break; 1150 case REQ_READAHEAD: req->result = readahead (req->int1, req->offs, req->size); break;
1140 case REQ_SENDFILE: req->result = sendfile_ (req->int1, req->int2, req->offs, req->size, self); break; 1151 case REQ_SENDFILE: req->result = sendfile_ (req->int1, req->int2, req->offs, req->size, self); break;
1141 1152
1142 case REQ_STAT: req->result = stat (req->ptr1, (Stat_t *)req->ptr2); break; 1153 case REQ_STAT: req->result = stat (req->ptr1, (Stat_t *)req->ptr2); break;
1270static void atfork_child (void) 1281static void atfork_child (void)
1271{ 1282{
1272 aio_req prv; 1283 aio_req prv;
1273 1284
1274 while (prv = reqq_shift (&req_queue)) 1285 while (prv = reqq_shift (&req_queue))
1275 req_free (prv); 1286 req_destroy (prv);
1276 1287
1277 while (prv = reqq_shift (&res_queue)) 1288 while (prv = reqq_shift (&res_queue))
1278 req_free (prv); 1289 req_destroy (prv);
1279 1290
1280 while (wrk_first.next != &wrk_first) 1291 while (wrk_first.next != &wrk_first)
1281 { 1292 {
1282 worker *wrk = wrk_first.next; 1293 worker *wrk = wrk_first.next;
1283 1294
1284 if (wrk->req) 1295 if (wrk->req)
1285 req_free (wrk->req); 1296 req_destroy (wrk->req);
1286 1297
1287 worker_clear (wrk); 1298 worker_clear (wrk);
1288 worker_free (wrk); 1299 worker_free (wrk);
1289 } 1300 }
1290 1301
1410 1421
1411 REQ_SEND (req); 1422 REQ_SEND (req);
1412} 1423}
1413 1424
1414void 1425void
1415aio_read (SV *fh, UV offset, UV length, SV8 *data, UV dataoffset, SV *callback=&PL_sv_undef) 1426aio_read (SV *fh, SV *offset, SV *length, SV8 *data, IV dataoffset, SV *callback=&PL_sv_undef)
1416 ALIAS: 1427 ALIAS:
1417 aio_read = REQ_READ 1428 aio_read = REQ_READ
1418 aio_write = REQ_WRITE 1429 aio_write = REQ_WRITE
1419 PROTOTYPE: $$$$$;$ 1430 PROTOTYPE: $$$$$;$
1420 PPCODE: 1431 PPCODE:
1421{ 1432{
1422 STRLEN svlen; 1433 STRLEN svlen;
1423 char *svptr = SvPVbyte (data, svlen); 1434 char *svptr = SvPVbyte (data, svlen);
1435 UV len = SvUV (length);
1424 1436
1425 SvUPGRADE (data, SVt_PV); 1437 SvUPGRADE (data, SVt_PV);
1426 SvPOK_on (data); 1438 SvPOK_on (data);
1427 1439
1428 if (dataoffset < 0) 1440 if (dataoffset < 0)
1429 dataoffset += svlen; 1441 dataoffset += svlen;
1430 1442
1431 if (dataoffset < 0 || dataoffset > svlen) 1443 if (dataoffset < 0 || dataoffset > svlen)
1432 croak ("data offset outside of string"); 1444 croak ("dataoffset outside of data scalar");
1433 1445
1434 if (ix == REQ_WRITE) 1446 if (ix == REQ_WRITE)
1435 { 1447 {
1436 /* write: check length and adjust. */ 1448 /* write: check length and adjust. */
1437 if (length < 0 || length + dataoffset > svlen) 1449 if (!SvOK (length) || len + dataoffset > svlen)
1438 length = svlen - dataoffset; 1450 len = svlen - dataoffset;
1439 } 1451 }
1440 else 1452 else
1441 { 1453 {
1442 /* read: grow scalar as necessary */ 1454 /* read: grow scalar as necessary */
1443 svptr = SvGROW (data, length + dataoffset + 1); 1455 svptr = SvGROW (data, len + dataoffset + 1);
1444 } 1456 }
1445 1457
1446 if (length < 0) 1458 if (len < 0)
1447 croak ("length must not be negative"); 1459 croak ("length must not be negative");
1448 1460
1449 { 1461 {
1450 dREQ; 1462 dREQ;
1451 1463
1452 req->type = ix; 1464 req->type = ix;
1453 req->sv1 = newSVsv (fh); 1465 req->sv1 = newSVsv (fh);
1454 req->int1 = PerlIO_fileno (ix == REQ_READ ? IoIFP (sv_2io (fh)) 1466 req->int1 = PerlIO_fileno (ix == REQ_READ ? IoIFP (sv_2io (fh))
1455 : IoOFP (sv_2io (fh))); 1467 : IoOFP (sv_2io (fh)));
1456 req->offs = offset; 1468 req->offs = SvOK (offset) ? SvVAL64 (offset) : -1;
1457 req->size = length; 1469 req->size = len;
1458 req->sv2 = SvREFCNT_inc (data); 1470 req->sv2 = SvREFCNT_inc (data);
1459 req->ptr1 = (char *)svptr + dataoffset; 1471 req->ptr1 = (char *)svptr + dataoffset;
1460 req->stroffset = dataoffset; 1472 req->stroffset = dataoffset;
1461 1473
1462 if (!SvREADONLY (data)) 1474 if (!SvREADONLY (data))
1488 1500
1489 REQ_SEND; 1501 REQ_SEND;
1490} 1502}
1491 1503
1492void 1504void
1493aio_sendfile (SV *out_fh, SV *in_fh, UV in_offset, UV length, SV *callback=&PL_sv_undef) 1505aio_sendfile (SV *out_fh, SV *in_fh, SV *in_offset, UV length, SV *callback=&PL_sv_undef)
1494 PROTOTYPE: $$$$;$ 1506 PROTOTYPE: $$$$;$
1495 PPCODE: 1507 PPCODE:
1496{ 1508{
1497 dREQ; 1509 dREQ;
1498 1510
1499 req->type = REQ_SENDFILE; 1511 req->type = REQ_SENDFILE;
1500 req->sv1 = newSVsv (out_fh); 1512 req->sv1 = newSVsv (out_fh);
1501 req->int1 = PerlIO_fileno (IoIFP (sv_2io (out_fh))); 1513 req->int1 = PerlIO_fileno (IoIFP (sv_2io (out_fh)));
1502 req->sv2 = newSVsv (in_fh); 1514 req->sv2 = newSVsv (in_fh);
1503 req->int2 = PerlIO_fileno (IoIFP (sv_2io (in_fh))); 1515 req->int2 = PerlIO_fileno (IoIFP (sv_2io (in_fh)));
1504 req->offs = in_offset; 1516 req->offs = SvVAL64 (in_offset);
1505 req->size = length; 1517 req->size = length;
1506 1518
1507 REQ_SEND; 1519 REQ_SEND;
1508} 1520}
1509 1521
1510void 1522void
1511aio_readahead (SV *fh, UV offset, IV length, SV *callback=&PL_sv_undef) 1523aio_readahead (SV *fh, SV *offset, IV length, SV *callback=&PL_sv_undef)
1512 PROTOTYPE: $$$;$ 1524 PROTOTYPE: $$$;$
1513 PPCODE: 1525 PPCODE:
1514{ 1526{
1515 dREQ; 1527 dREQ;
1516 1528
1517 req->type = REQ_READAHEAD; 1529 req->type = REQ_READAHEAD;
1518 req->sv1 = newSVsv (fh); 1530 req->sv1 = newSVsv (fh);
1519 req->int1 = PerlIO_fileno (IoIFP (sv_2io (fh))); 1531 req->int1 = PerlIO_fileno (IoIFP (sv_2io (fh)));
1520 req->offs = offset; 1532 req->offs = SvVAL64 (offset);
1521 req->size = length; 1533 req->size = length;
1522 1534
1523 REQ_SEND; 1535 REQ_SEND;
1524} 1536}
1525 1537
1533 dREQ; 1545 dREQ;
1534 1546
1535 req->ptr2 = malloc (sizeof (Stat_t)); 1547 req->ptr2 = malloc (sizeof (Stat_t));
1536 if (!req->ptr2) 1548 if (!req->ptr2)
1537 { 1549 {
1538 req_free (req); 1550 req_destroy (req);
1539 croak ("out of memory during aio_stat statdata allocation"); 1551 croak ("out of memory during aio_stat statdata allocation");
1540 } 1552 }
1541 1553
1542 req->flags |= FLAG_PTR2_FREE; 1554 req->flags |= FLAG_PTR2_FREE;
1543 req->sv1 = newSVsv (fh_or_path); 1555 req->sv1 = newSVsv (fh_or_path);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines