Re: [PATCH 3/6] io_uring: switch local task_work to a mpscq

Jens Axboe <[email protected]>
Newsgroups org.kernel.vger.io-uring
Message-ID <[email protected]>
On 6/11/26 9:20 PM, Caleb Sander Mateos wrote:
>> diff --git a/include/linux/io_uring_types.h b/include/linux/io_uring_types.h
>> index 85e12b4884a5..9df5584ec3b1 100644
>> --- a/include/linux/io_uring_types.h
>> +++ b/include/linux/io_uring_types.h
>> @@ -351,6 +351,14 @@ struct io_ring_ctx {
>>                  */
>>                 atomic_t                cancel_seq;
>>
>> +               /*
>> +                * Consumer cursor for ->work_list, protected by ->uring_lock.
>> +                * Deliberately kept away from the producer side of the queue,
>> +                * as it's written for every popped entry, and the producer
>> +                * cacheline is contended enough as it is.
>> +                */
>> +               struct llist_node       *work_head;
> 
> Looks like this field has padding both before (next to atomic_t) and
> after (next to bool). Probably doesn't matter currently, as the outer
> struct is cache-aligned and has 16 bytes of padding at the end, but
> could save 8 bytes of padding by reordering next to an existing
> 8-byte-aligned field.

Indeed - I'll still move it, then we don't have to hunt holes later.

>> +       /*
>> +        * No one is waiting (IO_CQ_WAKE_INIT), or this cycle's wake up has
>> +        * already been issued (zero or negative, see below).
>> +        */
>>         nr_wait = atomic_read(&ctx->cq_wait_nr);
>> -       /* not enough or no one is waiting */
>> -       if (nr_tw < nr_wait)
>> +       if (nr_wait <= 0)
>>                 return;
>> -       /* the previous add has already woken it up */
>> -       if (nr_tw_prev >= nr_wait)
>> +       if (flags & IOU_F_TWQ_LAZY_WAKE) {
>> +               /*
>> +                * ->cq_wait_nr counts down the number of lazy adds, once it
>> +                * hits zero we're good to wake the waiter.
>> +                */
>> +               if (!atomic_dec_and_test(&ctx->cq_wait_nr))
>> +                       return;
> 
> It's possible that another task work wakes up the task before this one
> reaches the atomic_dec_and_test(), right? If the submitter task begins
> a new wait in between, this could decrement cq_wait_nr even though the
> queued task work has already been processed after the previous wakeup.
> I guess that's okay; in the worse case, the waiter will be woken
> prematurely.

That's correct, if the race is particularly unlucky, it could wake
early. I think that's fine, that's worth living with, and should be rare
enough to not really matter. It's not a lost wake, which would have been
a real problem.

I'll add a comment.

>> diff --git a/io_uring/wait.h b/io_uring/wait.h
>> index a4274b137f81..6d494297e1ce 100644
>> --- a/io_uring/wait.h
>> +++ b/io_uring/wait.h
>> @@ -5,12 +5,14 @@
>>  #include <linux/io_uring_types.h>
>>
>>  /*
>> - * No waiters. It's larger than any valid value of the tw counter
>> - * so that tests against ->cq_wait_nr would fail and skip wake_up().
>> + * ->cq_wait_nr is armed with the number of lazy task_work adds the waiter
>> + * still needs, and counted down by the add side, with the add reaching zero
>> + * issuing the (single) wake up for this wait cycle. Zero and below means no
>> + * wake up is to be issued: IO_CQ_WAKE_INIT when no task is waiting (also
>> + * what a forced wake up resets it to when claiming one), zero once the
>> + * countdown has fired.
>>   */
>>  #define IO_CQ_WAKE_INIT                (-1U)
> 
> Since cq_wait_nr is now used as a signed value, would it make sense to
> drop the U here?

Indeed, I'll fix that too.

-- 
Jens Axboe
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.