workqueue: Use rcuwait for wq_manager_wait
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>
Wed, 27 May 2020 19:46:32 +0000 (21:46 +0200)
committerTejun Heo <tj@kernel.org>
Fri, 29 May 2020 14:00:35 +0000 (10:00 -0400)
commitd8bb65ab70f702531aaaa11d9710f9450078e295
tree9b5a3c74f1f5c8a84ba57271d49b65c65020845a
parent342ed2400b78072cc01c0130ce41240dec60d56d
workqueue: Use rcuwait for wq_manager_wait

The workqueue code has it's internal spinlock (pool::lock) and also
implicit spinlock usage in the wq_manager waitqueue. These spinlocks
are converted to 'sleeping' spinlocks on a RT-kernel.

Workqueue functions can be invoked from contexts which are truly atomic
even on a PREEMPT_RT enabled kernel. Taking sleeping locks from such
contexts is forbidden.

pool::lock can be converted to a raw spinlock as the lock held times
are short. But the workqueue manager waitqueue is handled inside of
pool::lock held regions which again violates the lock nesting rules
of raw and regular spinlocks.

The manager waitqueue has no special requirements like custom wakeup
callbacks or mass wakeups. While it does not use exclusive wait mode
explicitly there is no strict requirement to queue the waiters in a
particular order as there is only one waiter at a time.

This allows to replace the waitqueue with rcuwait which solves the
locking problem because rcuwait relies on existing locking.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Tejun Heo <tj@kernel.org>
kernel/workqueue.c