… | |
… | |
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); \ |
… | |
… | |
59 | typedef SV SV8; /* byte-sv, used for argument-checking */ |
66 | typedef SV SV8; /* byte-sv, used for argument-checking */ |
60 | |
67 | |
61 | enum { |
68 | enum { |
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 | |
320 | static int poll_cb (); |
327 | static int poll_cb (); |
321 | static int req_invoke (aio_req req); |
328 | static int req_invoke (aio_req req); |
322 | static void req_free (aio_req req); |
329 | static void req_destroy (aio_req req); |
323 | static void req_cancel (aio_req req); |
330 | static void req_cancel (aio_req req); |
324 | |
331 | |
325 | /* must be called at most once */ |
332 | /* must be called at most once */ |
326 | static SV *req_sv (aio_req req, const char *klass) |
333 | static 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 | |
408 | static int req_invoke (aio_req req) |
415 | static int req_invoke (aio_req req) |
… | |
… | |
536 | } |
543 | } |
537 | |
544 | |
538 | return !SvTRUE (ERRSV); |
545 | return !SvTRUE (ERRSV); |
539 | } |
546 | } |
540 | |
547 | |
541 | static void req_free (aio_req req) |
548 | static 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 | |
580 | static void *aio_proc(void *arg); |
587 | static void *aio_proc (void *arg); |
581 | |
588 | |
582 | static void start_thread (void) |
589 | static 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; |
… | |
… | |
1270 | static void atfork_child (void) |
1281 | static 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 | |
1414 | void |
1425 | void |
1415 | aio_read (SV *fh, UV offset, UV length, SV8 *data, UV dataoffset, SV *callback=&PL_sv_undef) |
1426 | aio_read (SV *fh, SV *offset, UV length, SV8 *data, UV 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: |
… | |
… | |
1451 | |
1462 | |
1452 | req->type = ix; |
1463 | req->type = ix; |
1453 | req->sv1 = newSVsv (fh); |
1464 | req->sv1 = newSVsv (fh); |
1454 | req->int1 = PerlIO_fileno (ix == REQ_READ ? IoIFP (sv_2io (fh)) |
1465 | req->int1 = PerlIO_fileno (ix == REQ_READ ? IoIFP (sv_2io (fh)) |
1455 | : IoOFP (sv_2io (fh))); |
1466 | : IoOFP (sv_2io (fh))); |
1456 | req->offs = offset; |
1467 | req->offs = SvOK (offset) ? SvVAL64 (offset) : -1; |
1457 | req->size = length; |
1468 | req->size = length; |
1458 | req->sv2 = SvREFCNT_inc (data); |
1469 | req->sv2 = SvREFCNT_inc (data); |
1459 | req->ptr1 = (char *)svptr + dataoffset; |
1470 | req->ptr1 = (char *)svptr + dataoffset; |
1460 | req->stroffset = dataoffset; |
1471 | req->stroffset = dataoffset; |
1461 | |
1472 | |
… | |
… | |
1488 | |
1499 | |
1489 | REQ_SEND; |
1500 | REQ_SEND; |
1490 | } |
1501 | } |
1491 | |
1502 | |
1492 | void |
1503 | void |
1493 | aio_sendfile (SV *out_fh, SV *in_fh, UV in_offset, UV length, SV *callback=&PL_sv_undef) |
1504 | aio_sendfile (SV *out_fh, SV *in_fh, SV *in_offset, UV length, SV *callback=&PL_sv_undef) |
1494 | PROTOTYPE: $$$$;$ |
1505 | PROTOTYPE: $$$$;$ |
1495 | PPCODE: |
1506 | PPCODE: |
1496 | { |
1507 | { |
1497 | dREQ; |
1508 | dREQ; |
1498 | |
1509 | |
1499 | req->type = REQ_SENDFILE; |
1510 | req->type = REQ_SENDFILE; |
1500 | req->sv1 = newSVsv (out_fh); |
1511 | req->sv1 = newSVsv (out_fh); |
1501 | req->int1 = PerlIO_fileno (IoIFP (sv_2io (out_fh))); |
1512 | req->int1 = PerlIO_fileno (IoIFP (sv_2io (out_fh))); |
1502 | req->sv2 = newSVsv (in_fh); |
1513 | req->sv2 = newSVsv (in_fh); |
1503 | req->int2 = PerlIO_fileno (IoIFP (sv_2io (in_fh))); |
1514 | req->int2 = PerlIO_fileno (IoIFP (sv_2io (in_fh))); |
1504 | req->offs = in_offset; |
1515 | req->offs = SvVAL64 (in_offset); |
1505 | req->size = length; |
1516 | req->size = length; |
1506 | |
1517 | |
1507 | REQ_SEND; |
1518 | REQ_SEND; |
1508 | } |
1519 | } |
1509 | |
1520 | |
1510 | void |
1521 | void |
1511 | aio_readahead (SV *fh, UV offset, IV length, SV *callback=&PL_sv_undef) |
1522 | aio_readahead (SV *fh, SV *offset, IV length, SV *callback=&PL_sv_undef) |
1512 | PROTOTYPE: $$$;$ |
1523 | PROTOTYPE: $$$;$ |
1513 | PPCODE: |
1524 | PPCODE: |
1514 | { |
1525 | { |
1515 | dREQ; |
1526 | dREQ; |
1516 | |
1527 | |
1517 | req->type = REQ_READAHEAD; |
1528 | req->type = REQ_READAHEAD; |
1518 | req->sv1 = newSVsv (fh); |
1529 | req->sv1 = newSVsv (fh); |
1519 | req->int1 = PerlIO_fileno (IoIFP (sv_2io (fh))); |
1530 | req->int1 = PerlIO_fileno (IoIFP (sv_2io (fh))); |
1520 | req->offs = offset; |
1531 | req->offs = SvVAL64 (offset); |
1521 | req->size = length; |
1532 | req->size = length; |
1522 | |
1533 | |
1523 | REQ_SEND; |
1534 | REQ_SEND; |
1524 | } |
1535 | } |
1525 | |
1536 | |
… | |
… | |
1533 | dREQ; |
1544 | dREQ; |
1534 | |
1545 | |
1535 | req->ptr2 = malloc (sizeof (Stat_t)); |
1546 | req->ptr2 = malloc (sizeof (Stat_t)); |
1536 | if (!req->ptr2) |
1547 | if (!req->ptr2) |
1537 | { |
1548 | { |
1538 | req_free (req); |
1549 | req_destroy (req); |
1539 | croak ("out of memory during aio_stat statdata allocation"); |
1550 | croak ("out of memory during aio_stat statdata allocation"); |
1540 | } |
1551 | } |
1541 | |
1552 | |
1542 | req->flags |= FLAG_PTR2_FREE; |
1553 | req->flags |= FLAG_PTR2_FREE; |
1543 | req->sv1 = newSVsv (fh_or_path); |
1554 | req->sv1 = newSVsv (fh_or_path); |