… | |
… | |
400 | { |
400 | { |
401 | /* we assume the sqe's are all "properly" initialised */ |
401 | /* we assume the sqe's are all "properly" initialised */ |
402 | struct io_uring_sqe *sqe = iouring_sqe_get (EV_A); |
402 | struct io_uring_sqe *sqe = iouring_sqe_get (EV_A); |
403 | sqe->opcode = IORING_OP_POLL_REMOVE; |
403 | sqe->opcode = IORING_OP_POLL_REMOVE; |
404 | sqe->fd = fd; |
404 | sqe->fd = fd; |
405 | sqe->user_data = -1; |
405 | /* Jens Axboe notified me that user_data is not what is documented, but is |
|
|
406 | * some kind of unique ID that has to match, otherwise the request cannot |
|
|
407 | * be removed. Since we don't *really* have that, we pass in the old |
|
|
408 | * generation counter - if that fails, too bad, it will hopefully be removed |
|
|
409 | * at close time and then be ignored. */ |
|
|
410 | sqe->user_data = (uint32_t)fd | ((__u64)(uint32_t)anfds [fd].egen << 32); |
406 | iouring_sqe_submit (EV_A_ sqe); |
411 | iouring_sqe_submit (EV_A_ sqe); |
407 | |
412 | |
408 | /* increment generation counter to avoid handling old events */ |
413 | /* increment generation counter to avoid handling old events */ |
409 | ++anfds [fd].egen; |
414 | ++anfds [fd].egen; |
410 | } |
415 | } |
… | |
… | |
451 | { |
456 | { |
452 | int fd = cqe->user_data & 0xffffffffU; |
457 | int fd = cqe->user_data & 0xffffffffU; |
453 | uint32_t gen = cqe->user_data >> 32; |
458 | uint32_t gen = cqe->user_data >> 32; |
454 | int res = cqe->res; |
459 | int res = cqe->res; |
455 | |
460 | |
456 | /* ignore fd removal events, if there are any. TODO: verify */ |
|
|
457 | /* TODO: yes, this triggers */ |
|
|
458 | if (cqe->user_data == (__u64)-1) |
|
|
459 | return; |
|
|
460 | |
|
|
461 | assert (("libev: io_uring fd must be in-bounds", fd >= 0 && fd < anfdmax)); |
461 | assert (("libev: io_uring fd must be in-bounds", fd >= 0 && fd < anfdmax)); |
462 | |
462 | |
463 | /* documentation lies, of course. the result value is NOT like |
463 | /* documentation lies, of course. the result value is NOT like |
464 | * normal syscalls, but like linux raw syscalls, i.e. negative |
464 | * normal syscalls, but like linux raw syscalls, i.e. negative |
465 | * error numbers. fortunate, as otherwise there would be no way |
465 | * error numbers. fortunate, as otherwise there would be no way |
466 | * to get error codes at all. still, why not document this? |
466 | * to get error codes at all. still, why not document this? |
467 | */ |
467 | */ |
468 | |
468 | |
469 | /* ignore event if generation doesn't match */ |
469 | /* ignore event if generation doesn't match */ |
|
|
470 | /* other than skipping removal events, */ |
470 | /* this should actually be very rare */ |
471 | /* this should actually be very rare */ |
471 | if (ecb_expect_false (gen != (uint32_t)anfds [fd].egen)) |
472 | if (ecb_expect_false (gen != (uint32_t)anfds [fd].egen)) |
472 | return; |
473 | return; |
473 | |
474 | |
474 | if (ecb_expect_false (res < 0)) |
475 | if (ecb_expect_false (res < 0)) |