Skip to content

Commit 35d90f9

Browse files
committed
io_uring: include task_work run after scheduling in wait for events
It's quite possible that we got woken up because task_work was queued, and we need to process this task_work to generate the events waited for. If we return to the wait loop without running task_work, we'll end up adding the task to the waitqueue again, only to call io_cqring_wait_schedule() again which will run the task_work. This is less efficient than it could be, as it requires adding to the cq_wait queue again. It also triggers the wakeup path for completions as cq_wait is now non-empty with the task itself, and it'll require another lock grab and deletion to remove ourselves from the waitqueue. Signed-off-by: Jens Axboe <[email protected]>
1 parent 6434ec0 commit 35d90f9

File tree

1 file changed

+10
-1
lines changed

1 file changed

+10
-1
lines changed

io_uring/io_uring.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2481,7 +2481,14 @@ static inline int io_cqring_wait_schedule(struct io_ring_ctx *ctx,
24812481
}
24822482
if (!schedule_hrtimeout(&timeout, HRTIMER_MODE_ABS))
24832483
return -ETIME;
2484-
return 1;
2484+
2485+
/*
2486+
* Run task_work after scheduling. If we got woken because of
2487+
* task_work being processed, run it now rather than let the caller
2488+
* do another wait loop.
2489+
*/
2490+
ret = io_run_task_work_sig(ctx);
2491+
return ret < 0 ? ret : 1;
24852492
}
24862493

24872494
/*
@@ -2546,6 +2553,8 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events,
25462553
prepare_to_wait_exclusive(&ctx->cq_wait, &iowq.wq,
25472554
TASK_INTERRUPTIBLE);
25482555
ret = io_cqring_wait_schedule(ctx, &iowq, timeout);
2556+
if (__io_cqring_events_user(ctx) >= min_events)
2557+
break;
25492558
cond_resched();
25502559
} while (ret > 0);
25512560

0 commit comments

Comments
 (0)