On 9/24/19 3:49 AM, Peter Zijlstra wrote: > 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) If you do that, then we can just base the io_uring parts on 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 :/ I'll be happy enough if I can just call autoremove_wake_function(), I think that will simplify the case enough for io_uring to not really make me care too much about going further. I'll leave that to you, if you have the desire :-) -- Jens Axboe