… | |
… | |
36 | * provisions above, a recipient may use your version of this file under |
36 | * provisions above, a recipient may use your version of this file under |
37 | * either the BSD or the GPL. |
37 | * either the BSD or the GPL. |
38 | */ |
38 | */ |
39 | |
39 | |
40 | #include "eio.h" |
40 | #include "eio.h" |
|
|
41 | |
|
|
42 | #ifdef EIO_STACKSIZE |
|
|
43 | # define XTHREAD_STACKSIZE EIO_STACKSIZE |
|
|
44 | #endif |
41 | #include "xthread.h" |
45 | #include "xthread.h" |
42 | |
46 | |
43 | #include <errno.h> |
47 | #include <errno.h> |
44 | #include <stddef.h> |
48 | #include <stddef.h> |
45 | #include <stdlib.h> |
49 | #include <stdlib.h> |
… | |
… | |
604 | |
608 | |
605 | static void grp_try_feed (eio_req *grp) |
609 | static void grp_try_feed (eio_req *grp) |
606 | { |
610 | { |
607 | while (grp->size < grp->int2 && !EIO_CANCELLED (grp)) |
611 | while (grp->size < grp->int2 && !EIO_CANCELLED (grp)) |
608 | { |
612 | { |
609 | int old_len = grp->size; |
613 | grp->flags &= ~EIO_FLAG_GROUPADD; |
610 | |
614 | |
611 | EIO_FEED (grp); |
615 | EIO_FEED (grp); |
612 | |
616 | |
613 | /* stop if no progress has been made */ |
617 | /* stop if no progress has been made */ |
614 | if (old_len == grp->size) |
618 | if (!(grp->flags & EIO_FLAG_GROUPADD)) |
615 | { |
619 | { |
616 | grp->feed = 0; |
620 | grp->feed = 0; |
617 | break; |
621 | break; |
618 | } |
622 | } |
619 | } |
623 | } |
… | |
… | |
736 | |
740 | |
737 | /*****************************************************************************/ |
741 | /*****************************************************************************/ |
738 | /* work around various missing functions */ |
742 | /* work around various missing functions */ |
739 | |
743 | |
740 | #if !HAVE_PREADWRITE |
744 | #if !HAVE_PREADWRITE |
|
|
745 | # undef pread |
|
|
746 | # undef pwrite |
741 | # define pread eio__pread |
747 | # define pread eio__pread |
742 | # define pwrite eio__pwrite |
748 | # define pwrite eio__pwrite |
743 | |
749 | |
744 | static ssize_t |
750 | static ssize_t |
745 | eio__pread (int fd, void *buf, size_t count, off_t offset) |
751 | eio__pread (int fd, void *buf, size_t count, off_t offset) |
… | |
… | |
765 | |
771 | |
766 | X_LOCK (preadwritelock); |
772 | X_LOCK (preadwritelock); |
767 | ooffset = lseek (fd, 0, SEEK_CUR); |
773 | ooffset = lseek (fd, 0, SEEK_CUR); |
768 | lseek (fd, offset, SEEK_SET); |
774 | lseek (fd, offset, SEEK_SET); |
769 | res = write (fd, buf, count); |
775 | res = write (fd, buf, count); |
770 | lseek (fd, offset, SEEK_SET); |
776 | lseek (fd, ooffset, SEEK_SET); |
771 | X_UNLOCK (preadwritelock); |
777 | X_UNLOCK (preadwritelock); |
772 | |
778 | |
773 | return res; |
779 | return res; |
774 | } |
780 | } |
775 | #endif |
781 | #endif |
776 | |
782 | |
777 | #ifndef HAVE_FUTIMES |
783 | #ifndef HAVE_FUTIMES |
778 | |
784 | |
|
|
785 | # undef utimes |
|
|
786 | # undef futimes |
779 | # define utimes(path,times) eio__utimes (path, times) |
787 | # define utimes(path,times) eio__utimes (path, times) |
780 | # define futimes(fd,times) eio__futimes (fd, times) |
788 | # define futimes(fd,times) eio__futimes (fd, times) |
781 | |
789 | |
782 | static int |
790 | static int |
783 | eio__utimes (const char *filename, const struct timeval times[2]) |
791 | eio__utimes (const char *filename, const struct timeval times[2]) |
… | |
… | |
802 | } |
810 | } |
803 | |
811 | |
804 | #endif |
812 | #endif |
805 | |
813 | |
806 | #if !HAVE_FDATASYNC |
814 | #if !HAVE_FDATASYNC |
|
|
815 | # undef fdatasync |
807 | # define fdatasync fsync |
816 | # define fdatasync(fd) fsync (fd) |
808 | #endif |
817 | #endif |
|
|
818 | |
|
|
819 | /* sync_file_range always needs emulation */ |
|
|
820 | int |
|
|
821 | eio__sync_file_range (int fd, off_t offset, size_t nbytes, unsigned int flags) |
|
|
822 | { |
|
|
823 | #if HAVE_SYNC_FILE_RANGE |
|
|
824 | int res; |
|
|
825 | |
|
|
826 | if (EIO_SYNC_FILE_RANGE_WAIT_BEFORE != SYNC_FILE_RANGE_WAIT_BEFORE |
|
|
827 | || EIO_SYNC_FILE_RANGE_WRITE != SYNC_FILE_RANGE_WRITE |
|
|
828 | || EIO_SYNC_FILE_RANGE_WAIT_AFTER != SYNC_FILE_RANGE_WAIT_AFTER) |
|
|
829 | { |
|
|
830 | flags = 0 |
|
|
831 | | (flags & EIO_SYNC_FILE_RANGE_WAIT_BEFORE ? SYNC_FILE_RANGE_WAIT_BEFORE : 0) |
|
|
832 | | (flags & EIO_SYNC_FILE_RANGE_WRITE ? SYNC_FILE_RANGE_WRITE : 0) |
|
|
833 | | (flags & EIO_SYNC_FILE_RANGE_WAIT_AFTER ? SYNC_FILE_RANGE_WAIT_AFTER : 0); |
|
|
834 | } |
|
|
835 | |
|
|
836 | res = sync_file_range (fd, offset, nbytes, flags); |
|
|
837 | |
|
|
838 | if (!res || errno != ENOSYS) |
|
|
839 | return res; |
|
|
840 | #endif |
|
|
841 | |
|
|
842 | /* even though we could play tricks with the flags, it's better to always |
|
|
843 | * call fdatasync, as thta matches the expectation of it's users best */ |
|
|
844 | return fdatasync (fd); |
|
|
845 | } |
809 | |
846 | |
810 | #if !HAVE_READAHEAD |
847 | #if !HAVE_READAHEAD |
|
|
848 | # undef readahead |
811 | # define readahead(fd,offset,count) eio__readahead (fd, offset, count, self) |
849 | # define readahead(fd,offset,count) eio__readahead (fd, offset, count, self) |
812 | |
850 | |
813 | static ssize_t |
851 | static ssize_t |
814 | eio__readahead (int fd, off_t offset, size_t count, etp_worker *self) |
852 | eio__readahead (int fd, off_t offset, size_t count, etp_worker *self) |
815 | { |
853 | { |
… | |
… | |
981 | |
1019 | |
982 | req->result = res; |
1020 | req->result = res; |
983 | } |
1021 | } |
984 | |
1022 | |
985 | #if !(_POSIX_MAPPED_FILES && _POSIX_SYNCHRONIZED_IO) |
1023 | #if !(_POSIX_MAPPED_FILES && _POSIX_SYNCHRONIZED_IO) |
|
|
1024 | # undef msync |
986 | # define msync(a,b,c) ENOSYS |
1025 | # define msync(a,b,c) ((errno = ENOSYS), -1) |
987 | #endif |
1026 | #endif |
988 | |
1027 | |
989 | int |
1028 | int |
990 | eio__mtouch (void *mem, size_t len, int flags) |
1029 | eio__mtouch (void *mem, size_t len, int flags) |
991 | { |
1030 | { |
… | |
… | |
1185 | case EIO_SYNC: req->result = 0; sync (); break; |
1224 | case EIO_SYNC: req->result = 0; sync (); break; |
1186 | case EIO_FSYNC: req->result = fsync (req->int1); break; |
1225 | case EIO_FSYNC: req->result = fsync (req->int1); break; |
1187 | case EIO_FDATASYNC: req->result = fdatasync (req->int1); break; |
1226 | case EIO_FDATASYNC: req->result = fdatasync (req->int1); break; |
1188 | case EIO_MSYNC: req->result = msync (req->ptr2, req->size, req->int1); break; |
1227 | case EIO_MSYNC: req->result = msync (req->ptr2, req->size, req->int1); break; |
1189 | case EIO_MTOUCH: req->result = eio__mtouch (req->ptr2, req->size, req->int1); break; |
1228 | case EIO_MTOUCH: req->result = eio__mtouch (req->ptr2, req->size, req->int1); break; |
|
|
1229 | case EIO_SYNC_FILE_RANGE: req->result = eio__sync_file_range (req->int1, req->offs, req->size, req->int2); break; |
1190 | |
1230 | |
1191 | case EIO_READDIR: eio__scandir (req, self); break; |
1231 | case EIO_READDIR: eio__scandir (req, self); break; |
1192 | |
1232 | |
1193 | case EIO_BUSY: |
1233 | case EIO_BUSY: |
1194 | #ifdef _WIN32 |
1234 | #ifdef _WIN32 |
… | |
… | |
1226 | |
1266 | |
1227 | req->result = req->type == EIO_FUTIME |
1267 | req->result = req->type == EIO_FUTIME |
1228 | ? futimes (req->int1, times) |
1268 | ? futimes (req->int1, times) |
1229 | : utimes (req->ptr1, times); |
1269 | : utimes (req->ptr1, times); |
1230 | } |
1270 | } |
|
|
1271 | break; |
1231 | |
1272 | |
1232 | case EIO_GROUP: |
1273 | case EIO_GROUP: |
1233 | abort (); /* handled in eio_request */ |
1274 | abort (); /* handled in eio_request */ |
1234 | |
1275 | |
1235 | case EIO_NOP: |
1276 | case EIO_NOP: |
… | |
… | |
1276 | } |
1317 | } |
1277 | |
1318 | |
1278 | eio_req *eio_mtouch (void *addr, size_t length, int flags, int pri, eio_cb cb, void *data) |
1319 | eio_req *eio_mtouch (void *addr, size_t length, int flags, int pri, eio_cb cb, void *data) |
1279 | { |
1320 | { |
1280 | REQ (EIO_MTOUCH); req->ptr2 = addr; req->size = length; req->int1 = flags; SEND; |
1321 | REQ (EIO_MTOUCH); req->ptr2 = addr; req->size = length; req->int1 = flags; SEND; |
|
|
1322 | } |
|
|
1323 | |
|
|
1324 | eio_req *eio_sync_file_range (int fd, off_t offset, size_t nbytes, unsigned int flags, int pri, eio_cb cb, void *data) |
|
|
1325 | { |
|
|
1326 | REQ (EIO_SYNC_FILE_RANGE); req->int1 = fd; req->offs = offset; req->size = nbytes; req->int2 = flags; SEND; |
1281 | } |
1327 | } |
1282 | |
1328 | |
1283 | eio_req *eio_fdatasync (int fd, int pri, eio_cb cb, void *data) |
1329 | eio_req *eio_fdatasync (int fd, int pri, eio_cb cb, void *data) |
1284 | { |
1330 | { |
1285 | REQ (EIO_FDATASYNC); req->int1 = fd; SEND; |
1331 | REQ (EIO_FDATASYNC); req->int1 = fd; SEND; |
… | |
… | |
1480 | |
1526 | |
1481 | void eio_grp_add (eio_req *grp, eio_req *req) |
1527 | void eio_grp_add (eio_req *grp, eio_req *req) |
1482 | { |
1528 | { |
1483 | assert (("cannot add requests to IO::AIO::GRP after the group finished", grp->int1 != 2)); |
1529 | assert (("cannot add requests to IO::AIO::GRP after the group finished", grp->int1 != 2)); |
1484 | |
1530 | |
|
|
1531 | grp->flags |= EIO_FLAG_GROUPADD; |
|
|
1532 | |
1485 | ++grp->size; |
1533 | ++grp->size; |
1486 | req->grp = grp; |
1534 | req->grp = grp; |
1487 | |
1535 | |
1488 | req->grp_prev = 0; |
1536 | req->grp_prev = 0; |
1489 | req->grp_next = grp->grp_first; |
1537 | req->grp_next = grp->grp_first; |