To test and profile the overhead of io_uring task_work and the various types of it, add IORING_NOP_TW which tells nop to signal completions through task_work rather than complete them inline.
Unified · Split
| @@ -449,6 +449,7 @@ enum io_uring_msg_ring_flags { · 448 unmodified lines | ||
| 449 | 449 | #define IORING_NOP_FILE (1U << 1) |
| 450 | 450 | #define IORING_NOP_FIXED_FILE (1U << 2) |
| 451 | 451 | #define IORING_NOP_FIXED_BUFFER (1U << 3) |
| 452 | +#define IORING_NOP_TW (1U << 4) | |
| 452 | 453 | |
| 453 | 454 | /* |
| 454 | 455 | * IO completion data structure (Completion Queue Entry) |
| @@ -20,7 +20,8 @@ struct io_nop { · 19 unmodified lines | ||
| 20 | 20 | }; |
| 21 | 21 | |
| 22 | 22 | #define NOP_FLAGS (IORING_NOP_INJECT_RESULT | IORING_NOP_FIXED_FILE | \ |
| 23 | − IORING_NOP_FIXED_BUFFER | IORING_NOP_FILE) | |
| 23 | + IORING_NOP_FIXED_BUFFER | IORING_NOP_FILE | \ | |
| 24 | + IORING_NOP_TW) | |
| 24 | 25 | |
| 25 | 26 | int io_nop_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) |
| 26 | 27 | { |
| @@ -68,5 +69,10 @@ done: · 41 unmodified lines | ||
| 68 | 69 | if (ret < 0) |
| 69 | 70 | req_set_fail(req); |
| 70 | 71 | io_req_set_res(req, nop->result, 0); |
| 72 | + if (nop->flags & IORING_NOP_TW) { | |
| 73 | + req->io_task_work.func = io_req_task_complete; | |
| 74 | + io_req_task_work_add(req); | |
| 75 | + return IOU_ISSUE_SKIP_COMPLETE; | |
| 76 | + } | |
| 71 | 77 | return IOU_COMPLETE; |
| 72 | 78 | } |