Re: [PATCH v2 0/2] Optimise io_uring completion waiting

From: Peter Zijlstra
Date: Tue Sep 24 2019 - 05:49:58 EST


On Tue, Sep 24, 2019 at 10:36:28AM +0200, Jens Axboe wrote:

> +struct io_wait_queue {
> + struct wait_queue_entry wq;
> + struct io_ring_ctx *ctx;
> + struct task_struct *task;

wq.private is where the normal waitqueue stores the task pointer.

(I'm going to rename that)

> + unsigned to_wait;
> + unsigned nr_timeouts;
> +};
> +
> +static inline bool io_should_wake(struct io_wait_queue *iowq)
> +{
> + struct io_ring_ctx *ctx = iowq->ctx;
> +
> + /*
> + * Wake up if we have enough events, or if a timeout occured since we
> + * started waiting. For timeouts, we always want to return to userspace,
> + * regardless of event count.
> + */
> + return io_cqring_events(ctx->rings) >= iowq->to_wait ||
> + atomic_read(&ctx->cq_timeouts) != iowq->nr_timeouts;
> +}
> +
> +static int io_wake_function(struct wait_queue_entry *curr, unsigned int mode,
> + int wake_flags, void *key)
> +{
> + struct io_wait_queue *iowq = container_of(curr, struct io_wait_queue,
> + wq);
> +
> + if (io_should_wake(iowq)) {
> + list_del_init(&curr->entry);
> + wake_up_process(iowq->task);

Then you can use autoremove_wake_function() here.

> + return 1;
> + }
> +
> + return -1;
> +}

Ideally we'd get wait_event()'s @cond in a custom wake function. Then we
can _always_ do this.

This is one I'd love to have lambda functions for. It would actually
work with GCC nested functions, because the wake function will always be
in scope, but we can't use those in the kernel for other reasons :/