From: Daniel Wagner <wagi@monom.org>
To: LKML <linux-kernel@vger.kernel.org>,
linux-rt-users <linux-rt-users@vger.kernel.org>,
Steven Rostedt <rostedt@goodmis.org>,
Thomas Gleixner <tglx@linutronix.de>,
Carsten Emde <C.Emde@osadl.org>, John Kacur <jkacur@redhat.com>,
Sebastian Andrzej Siewior <bigeasy@linutronix.de>,
Tom Zanussi <tom.zanussi@linux.intel.com>,
Clark Williams <williams@redhat.com>,
Pavel Machek <pavel@denx.de>
Cc: Tejun Heo <tj@kernel.org>, Daniel Wagner <wagi@monom.org>
Subject: [PATCH RT 8/9] workqueue: Use rcuwait for wq_manager_wait
Date: Mon, 24 Oct 2022 12:44:24 +0200 [thread overview]
Message-ID: <20221024104425.16423-9-wagi@monom.org> (raw)
In-Reply-To: <20221024104425.16423-1-wagi@monom.org>
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
v4.19.255-rt114-rc1 stable review patch.
If anyone has any objections, please let me know.
-----------
Upstream commit d8bb65ab70f702531aaaa11d9710f9450078e295
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>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
[wagi: Updated context as v4.19-rt was using swait]
Signed-off-by: Daniel Wagner <wagi@monom.org>
---
kernel/workqueue.c | 24 ++++++++++++++++++++----
1 file changed, 20 insertions(+), 4 deletions(-)
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index d97c2ad8dc08..a3777fe1e224 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -50,6 +50,7 @@
#include <linux/sched/isolation.h>
#include <linux/nmi.h>
#include <linux/kvm_para.h>
+#include <linux/rcuwait.h>
#include "workqueue_internal.h"
@@ -299,7 +300,8 @@ static struct workqueue_attrs *wq_update_unbound_numa_attrs_buf;
static DEFINE_MUTEX(wq_pool_mutex); /* protects pools and workqueues list */
static DEFINE_MUTEX(wq_pool_attach_mutex); /* protects worker attach/detach */
static DEFINE_RAW_SPINLOCK(wq_mayday_lock); /* protects wq->maydays list */
-static DECLARE_SWAIT_QUEUE_HEAD(wq_manager_wait); /* wait for manager to go away */
+/* wait for manager to go away */
+static struct rcuwait manager_wait = __RCUWAIT_INITIALIZER(manager_wait);
static LIST_HEAD(workqueues); /* PR: list of all workqueues */
static bool workqueue_freezing; /* PL: have wqs started freezing? */
@@ -2023,7 +2025,7 @@ static bool manage_workers(struct worker *worker)
pool->manager = NULL;
pool->flags &= ~POOL_MANAGER_ACTIVE;
- swake_up_one(&wq_manager_wait);
+ rcuwait_wake_up(&manager_wait);
return true;
}
@@ -3344,6 +3346,18 @@ static void rcu_free_pool(struct rcu_head *rcu)
kfree(pool);
}
+/* This returns with the lock held on success (pool manager is inactive). */
+static bool wq_manager_inactive(struct worker_pool *pool)
+{
+ raw_spin_lock_irq(&pool->lock);
+
+ if (pool->flags & POOL_MANAGER_ACTIVE) {
+ raw_spin_unlock_irq(&pool->lock);
+ return false;
+ }
+ return true;
+}
+
/**
* put_unbound_pool - put a worker_pool
* @pool: worker_pool to put
@@ -3379,10 +3393,12 @@ static void put_unbound_pool(struct worker_pool *pool)
* Become the manager and destroy all workers. This prevents
* @pool's workers from blocking on attach_mutex. We're the last
* manager and @pool gets freed with the flag set.
+ * Because of how wq_manager_inactive() works, we will hold the
+ * spinlock after a successful wait.
*/
raw_spin_lock_irq(&pool->lock);
- swait_event_lock_irq(wq_manager_wait,
- !(pool->flags & POOL_MANAGER_ACTIVE), pool->lock);
+ rcuwait_wait_event(&manager_wait, wq_manager_inactive(pool),
+ TASK_UNINTERRUPTIBLE);
pool->flags |= POOL_MANAGER_ACTIVE;
while ((worker = first_idle_worker(pool)))
--
2.38.0
next prev parent reply other threads:[~2022-10-24 10:55 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-10-24 10:44 [PATCH RT 0/9] Linux v4.19.255-rt114-rc1 Daniel Wagner
2022-10-24 10:44 ` [PATCH RT 1/9] Revert "random: Use local locks for crng context access" Daniel Wagner
2022-10-24 10:44 ` [PATCH RT 2/9] random: Bring back the local_locks Daniel Wagner
2022-10-24 10:44 ` [PATCH RT 3/9] local_lock: Provide INIT_LOCAL_LOCK() Daniel Wagner
2022-10-24 10:44 ` [PATCH RT 4/9] Revert "workqueue: Use local irq lock instead of irq disable regions" Daniel Wagner
2022-10-24 10:44 ` [PATCH RT 5/9] timers: Keep interrupts disabled for TIMER_IRQSAFE timer Daniel Wagner
2022-10-24 10:44 ` [PATCH RT 6/9] timers: Don't block on ->expiry_lock for TIMER_IRQSAFE timers Daniel Wagner
2022-10-24 10:44 ` [PATCH RT 7/9] rcu: Update rcuwait Daniel Wagner
2022-10-24 10:44 ` Daniel Wagner [this message]
2022-10-24 10:44 ` [PATCH RT 9/9] Linux 4.19.255-rt114-rc1 Daniel Wagner
2022-10-24 10:54 ` [PATCH RT 0/9] Linux v4.19.255-rt114-rc1 Daniel Wagner
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20221024104425.16423-9-wagi@monom.org \
--to=wagi@monom.org \
--cc=C.Emde@osadl.org \
--cc=bigeasy@linutronix.de \
--cc=jkacur@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rt-users@vger.kernel.org \
--cc=pavel@denx.de \
--cc=rostedt@goodmis.org \
--cc=tglx@linutronix.de \
--cc=tj@kernel.org \
--cc=tom.zanussi@linux.intel.com \
--cc=williams@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®