workqueue - queue + drain

Martin Kaiser lists at kaiser.cx
Thu Aug 11 12:03:51 EDT 2022


Dear all,

would you mind helping me understand how workers and workqueues act in a
seemingly simple scenario? I'm calling

queue_work(my_queue, my_worker)

to add a worker to a queue that was created by calling
create_singlethread_workqueue().

This goes into

queue_work
   queue_work_on
         ...
         if (!test_and_set_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(work))) {
            __queue_work(cpu, wq, work);
            ret = true;
         }
         ... return false if __queue_work hasn't been called...


with

static void __queue_work(int cpu, struct workqueue_struct *wq, struct work_struct *work)
   ...
   /* if draining, only works from the same workqueue are allowed */
   if (unlikely(wq->flags & __WQ_DRAINING) &&
       WARN_ON_ONCE(!is_chained_work(wq)))
      return;


If drain_workqueue(my_queue) is running while
queue_work(my_queue, my_worker)
is called, my_worker will have WORK_STRUCT_PENDING_BIT set, but it's not
queued and no error is returned.

With WORK_STRUCT_PENDING_BIT set, all further attempts to
queue_work(my_queue, my_worker)
later, after draining is done, will fail.

This code has been unchanged since at least 4.14. Could anyone shed some
light on this, where am I getting things wrong?

Thanks and best regards,

   Martin



More information about the Kernelnewbies mailing list