… | |
… | |
286 | linuxaio_modify (EV_P_ int fd, int oev, int nev) |
286 | linuxaio_modify (EV_P_ int fd, int oev, int nev) |
287 | { |
287 | { |
288 | array_needsize (ANIOCBP, linuxaio_iocbps, linuxaio_iocbpmax, fd + 1, linuxaio_array_needsize_iocbp); |
288 | array_needsize (ANIOCBP, linuxaio_iocbps, linuxaio_iocbpmax, fd + 1, linuxaio_array_needsize_iocbp); |
289 | ANIOCBP iocb = linuxaio_iocbps [fd]; |
289 | ANIOCBP iocb = linuxaio_iocbps [fd]; |
290 | |
290 | |
291 | if (expect_false (iocb->io.aio_reqprio < 0)) |
291 | if (ecb_expect_false (iocb->io.aio_reqprio < 0)) |
292 | { |
292 | { |
293 | /* we handed this fd over to epoll, so undo this first */ |
293 | /* we handed this fd over to epoll, so undo this first */ |
294 | /* we do it manually because the optimisations on epoll_modify won't do us any good */ |
294 | /* we do it manually because the optimisations on epoll_modify won't do us any good */ |
295 | epoll_ctl (backend_fd, EPOLL_CTL_DEL, fd, 0); |
295 | epoll_ctl (backend_fd, EPOLL_CTL_DEL, fd, 0); |
296 | anfds [fd].emask = 0; |
296 | anfds [fd].emask = 0; |
297 | iocb->io.aio_reqprio = 0; |
297 | iocb->io.aio_reqprio = 0; |
298 | } |
298 | } |
299 | |
299 | |
300 | if (expect_false (iocb->io.aio_buf)) |
300 | if (ecb_expect_false (iocb->io.aio_buf)) |
301 | { |
301 | { |
302 | /* iocb active, so cancel it first before resubmit */ |
302 | /* iocb active, so cancel it first before resubmit */ |
303 | for (;;) |
303 | for (;;) |
304 | { |
304 | { |
305 | /* on all relevant kernels, io_cancel fails with EINPROGRESS on "success" */ |
305 | /* on all relevant kernels, io_cancel fails with EINPROGRESS on "success" */ |
306 | if (expect_false (evsys_io_cancel (linuxaio_ctx, &iocb->io, (struct io_event *)0) == 0)) |
306 | if (ecb_expect_false (evsys_io_cancel (linuxaio_ctx, &iocb->io, (struct io_event *)0) == 0)) |
307 | break; |
307 | break; |
308 | |
308 | |
309 | if (expect_true (errno == EINPROGRESS)) |
309 | if (ecb_expect_true (errno == EINPROGRESS)) |
310 | break; |
310 | break; |
311 | |
311 | |
312 | /* the EINPROGRESS test is for nicer error message. clumsy. */ |
312 | /* the EINPROGRESS test is for nicer error message. clumsy. */ |
313 | assert (("libev: linuxaio unexpected io_cancel failed", errno != EINPROGRESS && errno != EINTR)); |
313 | assert (("libev: linuxaio unexpected io_cancel failed", errno != EINPROGRESS && errno != EINTR)); |
314 | } |
314 | } |
… | |
… | |
407 | int |
407 | int |
408 | linuxaio_ringbuf_valid (EV_P) |
408 | linuxaio_ringbuf_valid (EV_P) |
409 | { |
409 | { |
410 | struct aio_ring *ring = (struct aio_ring *)linuxaio_ctx; |
410 | struct aio_ring *ring = (struct aio_ring *)linuxaio_ctx; |
411 | |
411 | |
412 | return expect_true (ring->magic == AIO_RING_MAGIC) |
412 | return ecb_expect_true (ring->magic == AIO_RING_MAGIC) |
413 | && ring->incompat_features == EV_AIO_RING_INCOMPAT_FEATURES |
413 | && ring->incompat_features == EV_AIO_RING_INCOMPAT_FEATURES |
414 | && ring->header_length == sizeof (struct aio_ring); /* TODO: or use it to find io_event[0]? */ |
414 | && ring->header_length == sizeof (struct aio_ring); /* TODO: or use it to find io_event[0]? */ |
415 | } |
415 | } |
416 | |
416 | |
417 | /* read at least one event from kernel, or timeout */ |
417 | /* read at least one event from kernel, or timeout */ |
… | |
… | |
422 | struct timespec ts; |
422 | struct timespec ts; |
423 | struct io_event ioev[8]; /* 256 octet stack space */ |
423 | struct io_event ioev[8]; /* 256 octet stack space */ |
424 | int want = 1; /* how many events to request */ |
424 | int want = 1; /* how many events to request */ |
425 | int ringbuf_valid = linuxaio_ringbuf_valid (EV_A); |
425 | int ringbuf_valid = linuxaio_ringbuf_valid (EV_A); |
426 | |
426 | |
427 | if (expect_true (ringbuf_valid)) |
427 | if (ecb_expect_true (ringbuf_valid)) |
428 | { |
428 | { |
429 | /* if the ring buffer has any events, we don't wait or call the kernel at all */ |
429 | /* if the ring buffer has any events, we don't wait or call the kernel at all */ |
430 | if (linuxaio_get_events_from_ring (EV_A)) |
430 | if (linuxaio_get_events_from_ring (EV_A)) |
431 | return; |
431 | return; |
432 | |
432 | |
… | |
… | |
462 | else if (res) |
462 | else if (res) |
463 | { |
463 | { |
464 | /* at least one event available, handle them */ |
464 | /* at least one event available, handle them */ |
465 | linuxaio_parse_events (EV_A_ ioev, res); |
465 | linuxaio_parse_events (EV_A_ ioev, res); |
466 | |
466 | |
467 | if (expect_true (ringbuf_valid)) |
467 | if (ecb_expect_true (ringbuf_valid)) |
468 | { |
468 | { |
469 | /* if we have a ring buffer, handle any remaining events in it */ |
469 | /* if we have a ring buffer, handle any remaining events in it */ |
470 | linuxaio_get_events_from_ring (EV_A); |
470 | linuxaio_get_events_from_ring (EV_A); |
471 | |
471 | |
472 | /* at this point, we should have handled all outstanding events */ |
472 | /* at this point, we should have handled all outstanding events */ |
… | |
… | |
503 | /* which allows us to pinpoint the erroneous iocb */ |
503 | /* which allows us to pinpoint the erroneous iocb */ |
504 | for (submitted = 0; submitted < linuxaio_submitcnt; ) |
504 | for (submitted = 0; submitted < linuxaio_submitcnt; ) |
505 | { |
505 | { |
506 | int res = evsys_io_submit (linuxaio_ctx, linuxaio_submitcnt - submitted, linuxaio_submits + submitted); |
506 | int res = evsys_io_submit (linuxaio_ctx, linuxaio_submitcnt - submitted, linuxaio_submits + submitted); |
507 | |
507 | |
508 | if (expect_false (res < 0)) |
508 | if (ecb_expect_false (res < 0)) |
509 | if (errno == EINVAL) |
509 | if (errno == EINVAL) |
510 | { |
510 | { |
511 | /* This happens for unsupported fds, officially, but in my testing, |
511 | /* This happens for unsupported fds, officially, but in my testing, |
512 | * also randomly happens for supported fds. We fall back to good old |
512 | * also randomly happens for supported fds. We fall back to good old |
513 | * poll() here, under the assumption that this is a very rare case. |
513 | * poll() here, under the assumption that this is a very rare case. |