1 | #include "eio.h" |
1 | #include "eio.h" |
2 | #include "xthread.h" |
2 | #include "xthread.h" |
3 | |
3 | |
4 | #include <errno.h> |
4 | #include <errno.h> |
5 | |
|
|
6 | #include "EXTERN.h" |
|
|
7 | #include "perl.h" |
|
|
8 | #include "XSUB.h" |
|
|
9 | |
|
|
10 | #include <stddef.h> |
5 | #include <stddef.h> |
11 | #include <stdlib.h> |
6 | #include <stdlib.h> |
|
|
7 | #include <string.h> |
12 | #include <errno.h> |
8 | #include <errno.h> |
13 | #include <sys/types.h> |
9 | #include <sys/types.h> |
14 | #include <sys/stat.h> |
10 | #include <sys/stat.h> |
15 | #include <limits.h> |
11 | #include <limits.h> |
16 | #include <fcntl.h> |
12 | #include <fcntl.h> |
17 | #include <sched.h> |
13 | #include <sched.h> |
|
|
14 | #include <dirent.h> |
18 | |
15 | |
19 | #ifndef EIO_FINISH |
16 | #ifndef EIO_FINISH |
20 | # define EIO_FINISH(req) ((req)->finish) && !EIO_CANCELLED (req) ? (req)->finish (req) : 0 |
17 | # define EIO_FINISH(req) ((req)->finish) && !EIO_CANCELLED (req) ? (req)->finish (req) : 0 |
21 | #endif |
18 | #endif |
22 | |
19 | |
… | |
… | |
239 | } |
236 | } |
240 | |
237 | |
241 | abort (); |
238 | abort (); |
242 | } |
239 | } |
243 | |
240 | |
244 | static void grp_feed (eio_req *grp) |
241 | static void grp_try_feed (eio_req *grp) |
245 | { |
242 | { |
246 | while (grp->size < grp->int2 && !EIO_CANCELLED (grp)) |
243 | while (grp->size < grp->int2 && !EIO_CANCELLED (grp)) |
247 | { |
244 | { |
248 | int old_len = grp->size; |
245 | int old_len = grp->size; |
249 | |
246 | |
… | |
… | |
251 | |
248 | |
252 | /* stop if no progress has been made */ |
249 | /* stop if no progress has been made */ |
253 | if (old_len == grp->size) |
250 | if (old_len == grp->size) |
254 | { |
251 | { |
255 | grp->feed = 0; |
252 | grp->feed = 0; |
256 | grp->int2 = 0; |
253 | break; |
257 | } |
254 | } |
258 | } |
255 | } |
259 | } |
256 | } |
260 | |
257 | |
261 | static int eio_invoke (eio_req *req); |
258 | static int eio_finish (eio_req *req); |
262 | |
259 | |
263 | static int grp_dec (eio_req *grp) |
260 | static int grp_dec (eio_req *grp) |
264 | { |
261 | { |
265 | --grp->size; |
262 | --grp->size; |
266 | |
263 | |
267 | /* call feeder, if applicable */ |
264 | /* call feeder, if applicable */ |
268 | grp_feed (grp); |
265 | grp_try_feed (grp); |
269 | |
266 | |
270 | /* finish, if done */ |
267 | /* finish, if done */ |
271 | if (!grp->size && grp->int1) |
268 | if (!grp->size && grp->int1) |
272 | return eio_invoke (grp); |
269 | return eio_finish (grp); |
273 | else |
270 | else |
274 | return 0; |
271 | return 0; |
275 | } |
272 | } |
276 | |
273 | |
277 | void eio_destroy (eio_req *req) |
274 | void eio_destroy (eio_req *req) |
… | |
… | |
280 | free (req->ptr2); |
277 | free (req->ptr2); |
281 | |
278 | |
282 | EIO_DESTROY (req); |
279 | EIO_DESTROY (req); |
283 | } |
280 | } |
284 | |
281 | |
285 | static int eio_invoke (eio_req *req) |
282 | static int eio_finish (eio_req *req) |
286 | { |
283 | { |
287 | int res = EIO_FINISH (req); |
284 | int res = EIO_FINISH (req); |
288 | |
285 | |
289 | if (req->grp) |
286 | if (req->grp) |
290 | { |
287 | { |
… | |
… | |
443 | |
440 | |
444 | if (req) |
441 | if (req) |
445 | { |
442 | { |
446 | --npending; |
443 | --npending; |
447 | |
444 | |
448 | if (!res_queue.size) |
445 | if (!res_queue.size && done_poll_cb) |
449 | done_poll_cb (); |
446 | done_poll_cb (); |
450 | } |
447 | } |
451 | |
448 | |
452 | X_UNLOCK (reslock); |
449 | X_UNLOCK (reslock); |
453 | |
450 | |
… | |
… | |
461 | req->int1 = 1; /* mark request as delayed */ |
458 | req->int1 = 1; /* mark request as delayed */ |
462 | continue; |
459 | continue; |
463 | } |
460 | } |
464 | else |
461 | else |
465 | { |
462 | { |
466 | int res = eio_invoke (req); |
463 | int res = eio_finish (req); |
467 | if (res) |
464 | if (res) |
468 | return res; |
465 | return res; |
469 | } |
466 | } |
470 | |
467 | |
471 | if (maxreqs && !--maxreqs) |
468 | if (maxreqs && !--maxreqs) |
… | |
… | |
571 | |
568 | |
572 | while (todo > 0) |
569 | while (todo > 0) |
573 | { |
570 | { |
574 | size_t len = todo < EIO_BUFSIZE ? todo : EIO_BUFSIZE; |
571 | size_t len = todo < EIO_BUFSIZE ? todo : EIO_BUFSIZE; |
575 | |
572 | |
576 | pread (fd, aio_buf, len, offset); |
573 | pread (fd, eio_buf, len, offset); |
577 | offset += len; |
574 | offset += len; |
578 | todo -= len; |
575 | todo -= len; |
579 | } |
576 | } |
580 | |
577 | |
581 | errno = 0; |
578 | errno = 0; |
… | |
… | |
917 | |
914 | |
918 | X_LOCK (reslock); |
915 | X_LOCK (reslock); |
919 | |
916 | |
920 | ++npending; |
917 | ++npending; |
921 | |
918 | |
922 | if (!reqq_push (&res_queue, req)) |
919 | if (!reqq_push (&res_queue, req) && want_poll_cb) |
923 | want_poll_cb (); |
920 | want_poll_cb (); |
924 | |
921 | |
925 | self->req = 0; |
922 | self->req = 0; |
926 | worker_clear (self); |
923 | worker_clear (self); |
927 | |
924 | |
… | |
… | |
936 | return 0; |
933 | return 0; |
937 | } |
934 | } |
938 | |
935 | |
939 | /*****************************************************************************/ |
936 | /*****************************************************************************/ |
940 | |
937 | |
941 | static void atfork_prepare (void) |
938 | static void eio_atfork_prepare (void) |
942 | { |
939 | { |
943 | X_LOCK (wrklock); |
940 | X_LOCK (wrklock); |
944 | X_LOCK (reqlock); |
941 | X_LOCK (reqlock); |
945 | X_LOCK (reslock); |
942 | X_LOCK (reslock); |
946 | #if !HAVE_PREADWRITE |
943 | #if !HAVE_PREADWRITE |
… | |
… | |
949 | #if !HAVE_READDIR_R |
946 | #if !HAVE_READDIR_R |
950 | X_LOCK (readdirlock); |
947 | X_LOCK (readdirlock); |
951 | #endif |
948 | #endif |
952 | } |
949 | } |
953 | |
950 | |
954 | static void atfork_parent (void) |
951 | static void eio_atfork_parent (void) |
955 | { |
952 | { |
956 | #if !HAVE_READDIR_R |
953 | #if !HAVE_READDIR_R |
957 | X_UNLOCK (readdirlock); |
954 | X_UNLOCK (readdirlock); |
958 | #endif |
955 | #endif |
959 | #if !HAVE_PREADWRITE |
956 | #if !HAVE_PREADWRITE |
… | |
… | |
962 | X_UNLOCK (reslock); |
959 | X_UNLOCK (reslock); |
963 | X_UNLOCK (reqlock); |
960 | X_UNLOCK (reqlock); |
964 | X_UNLOCK (wrklock); |
961 | X_UNLOCK (wrklock); |
965 | } |
962 | } |
966 | |
963 | |
967 | static void atfork_child (void) |
964 | static void eio_atfork_child (void) |
968 | { |
965 | { |
969 | eio_req *prv; |
966 | eio_req *prv; |
970 | |
967 | |
971 | while (prv = reqq_shift (&req_queue)) |
968 | while (prv = reqq_shift (&req_queue)) |
972 | eio_destroy (prv); |
969 | eio_destroy (prv); |
… | |
… | |
989 | idle = 0; |
986 | idle = 0; |
990 | nreqs = 0; |
987 | nreqs = 0; |
991 | nready = 0; |
988 | nready = 0; |
992 | npending = 0; |
989 | npending = 0; |
993 | |
990 | |
994 | atfork_parent (); |
991 | eio_atfork_parent (); |
995 | } |
992 | } |
996 | |
993 | |
997 | int eio_init (void (*want_poll)(void), void (*done_poll)(void)) |
994 | int eio_init (void (*want_poll)(void), void (*done_poll)(void)) |
998 | { |
995 | { |
999 | want_poll_cb = want_poll; |
996 | want_poll_cb = want_poll; |
… | |
… | |
1008 | X_MUTEX_CHECK (readdirlock); |
1005 | X_MUTEX_CHECK (readdirlock); |
1009 | |
1006 | |
1010 | X_COND_CHECK (reqwait); |
1007 | X_COND_CHECK (reqwait); |
1011 | #endif |
1008 | #endif |
1012 | |
1009 | |
1013 | X_THREAD_ATFORK (atfork_prepare, atfork_parent, atfork_child); |
1010 | X_THREAD_ATFORK (eio_atfork_prepare, eio_atfork_parent, eio_atfork_child); |
1014 | } |
1011 | } |
1015 | |
1012 | |
1016 | #if 0 |
1013 | #if 0 |
1017 | |
1014 | |
1018 | eio_req *eio_fsync (int fd, eio_cb cb); |
1015 | eio_req *eio_fsync (int fd, eio_cb cb); |
… | |
… | |
1414 | { |
1411 | { |
1415 | dREQ; |
1412 | dREQ; |
1416 | |
1413 | |
1417 | #endif |
1414 | #endif |
1418 | |
1415 | |
1419 | void eio_grp_feed (eio_req *grp, int limit, void (*feed)(eio_req *req)) |
1416 | void eio_grp_feed (eio_req *grp, void (*feed)(eio_req *req), int limit) |
1420 | { |
1417 | { |
1421 | grp->int2 = limit; |
1418 | grp->int2 = limit; |
1422 | grp->feed = feed; |
1419 | grp->feed = feed; |
|
|
1420 | |
|
|
1421 | grp_try_feed (grp); |
|
|
1422 | } |
|
|
1423 | |
|
|
1424 | void eio_grp_limit (eio_req *grp, int limit) |
|
|
1425 | { |
|
|
1426 | grp->int2 = limit; |
|
|
1427 | |
|
|
1428 | grp_try_feed (grp); |
1423 | } |
1429 | } |
1424 | |
1430 | |
1425 | void eio_grp_add (eio_req *grp, eio_req *req) |
1431 | void eio_grp_add (eio_req *grp, eio_req *req) |
1426 | { |
1432 | { |
1427 | assert (("cannot add requests to IO::AIO::GRP after the group finished", grp->int1 != 2)); |
1433 | assert (("cannot add requests to IO::AIO::GRP after the group finished", grp->int1 != 2)); |