From: Breno Leitao <leitao@debian.org>
To: Tejun Heo <tj@kernel.org>, Lai Jiangshan <jiangshanlai@gmail.com>
Cc: marco.crivellari@suse.com, linux-kernel@vger.kernel.org,
Breno Leitao <leitao@debian.org>,
kernel-team@meta.com
Subject: [PATCH wq/for-7.4 2/2] workqueue: derive the standard attrs from the workqueue flags
Date: Thu, 10 Sep 2026 07:54:13 -0700 [thread overview]
Message-ID: <20260910-realsplit_last_v2-v1-2-464d64b71b29@debian.org> (raw)
In-Reply-To: <20260910-realsplit_last_v2-v1-0-464d64b71b29@debian.org>
alloc_and_link_pwqs() picks one of three static attrs arrays indexed by
WQ_HIGHPRI, and branches to a separate apply_workqueue_attrs_locked()
call for percpu, ordered and unbound workqueues. The arrays differ only
in the nice level and the ordered bit, which the flags already say.
Build the attrs from the flags instead. alloc_wq_std_attrs() sets nice
for WQ_HIGHPRI and ordered for __WQ_ORDERED, which collapses the three
branches into one call and drops the three arrays along with their
workqueue_init_early() loop.
The ordering WARN now sits behind its own __WQ_ORDERED test rather than
the unbound branch. __WQ_ORDERED is internal and every macro that sets it
pairs it with WQ_UNBOUND, so the WARN covers the same workqueues as
before.
The attrs are allocated per creation now. apply_wqattrs_prepare() already
allocates one on the same path, including in workqueue_init_early(), so
that is not a new constraint, and it only copies what it is given, so the
caller can free them once apply_workqueue_attrs_locked() returns.
Signed-off-by: Breno Leitao <leitao@debian.org>
---
kernel/workqueue.c | 76 +++++++++++++++++++++++-------------------------------
1 file changed, 32 insertions(+), 44 deletions(-)
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 8232a60e107cf7..39187f424c34e7 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -533,15 +533,6 @@ static DEFINE_IDR(worker_pool_idr); /* PR: idr of all pools */
/* PL: hash of all unbound pools keyed by pool->attrs */
static DEFINE_HASHTABLE(unbound_pool_hash, UNBOUND_POOL_HASH_ORDER);
-/* I: attributes used when instantiating standard unbound pools on demand */
-static struct workqueue_attrs *unbound_std_wq_attrs[NR_STD_WORKER_POOLS];
-
-/* I: attributes used when instantiating ordered pools on demand */
-static struct workqueue_attrs *ordered_wq_attrs[NR_STD_WORKER_POOLS];
-
-/* I: attributes of percpu workqueues, which are backed by the static pools */
-static struct workqueue_attrs *percpu_std_wq_attrs[NR_STD_WORKER_POOLS];
-
/*
* I: kthread_worker to release pwq's. pwq release needs to be bounced to a
* process context while holding a pool lock. Bounce to a dedicated kthread
@@ -5920,9 +5911,27 @@ static void unbound_wq_update_pwq(struct workqueue_struct *wq, int cpu)
put_pwq_unlocked(old_pwq);
}
+/* the attrs @wq asked for, as spelled by its flags */
+static struct workqueue_attrs *alloc_wq_std_attrs(struct workqueue_struct *wq)
+{
+ struct workqueue_attrs *attrs;
+
+ attrs = alloc_workqueue_attrs();
+ if (!attrs)
+ return NULL;
+
+ if (wq->flags & WQ_HIGHPRI)
+ attrs->nice = HIGHPRI_NICE_LEVEL;
+
+ if (wq->flags & __WQ_ORDERED)
+ attrs->ordered = true;
+
+ return attrs;
+}
+
static int alloc_and_link_pwqs(struct workqueue_struct *wq)
{
- bool highpri = wq->flags & WQ_HIGHPRI;
+ struct workqueue_attrs *attrs;
int ret;
lockdep_assert_held(&wq_pool_mutex);
@@ -5931,23 +5940,24 @@ static int alloc_and_link_pwqs(struct workqueue_struct *wq)
if (!wq->cpu_pwq)
goto enomem;
- if (!(wq->flags & WQ_UNBOUND)) {
- ret = apply_workqueue_attrs_locked(wq, percpu_std_wq_attrs[highpri]);
- } else if (wq->flags & __WQ_ORDERED) {
- struct pool_workqueue *dfl_pwq;
+ attrs = alloc_wq_std_attrs(wq);
+ if (!attrs)
+ goto enomem;
+
+ ret = apply_workqueue_attrs_locked(wq, attrs);
+ free_workqueue_attrs(attrs);
+ if (ret)
+ goto enomem;
+
+ if (wq->flags & __WQ_ORDERED) {
+ struct pool_workqueue *dfl_pwq = rcu_access_pointer(wq->dfl_pwq);
- ret = apply_workqueue_attrs_locked(wq, ordered_wq_attrs[highpri]);
/* there should only be single pwq for ordering guarantee */
- dfl_pwq = rcu_access_pointer(wq->dfl_pwq);
- WARN(!ret && (wq->pwqs.next != &dfl_pwq->pwqs_node ||
- wq->pwqs.prev != &dfl_pwq->pwqs_node),
+ WARN(wq->pwqs.next != &dfl_pwq->pwqs_node ||
+ wq->pwqs.prev != &dfl_pwq->pwqs_node,
"ordering guarantee broken for workqueue %s\n", wq->name);
- } else {
- ret = apply_workqueue_attrs_locked(wq, unbound_std_wq_attrs[highpri]);
}
- if (ret)
- goto enomem;
return 0;
enomem:
@@ -8378,28 +8388,6 @@ void __init workqueue_init_early(void)
init_cpu_worker_pool(pool, cpu, std_nice[i++]);
}
- /* create default unbound, ordered and percpu wq attrs */
- for (i = 0; i < NR_STD_WORKER_POOLS; i++) {
- struct workqueue_attrs *attrs;
-
- BUG_ON(!(attrs = alloc_workqueue_attrs()));
- attrs->nice = std_nice[i];
- unbound_std_wq_attrs[i] = attrs;
-
- /*
- * An ordered wq should have only one pwq as ordering is
- * guaranteed by max_active which is enforced by pwqs.
- */
- BUG_ON(!(attrs = alloc_workqueue_attrs()));
- attrs->nice = std_nice[i];
- attrs->ordered = true;
- ordered_wq_attrs[i] = attrs;
-
- BUG_ON(!(attrs = alloc_workqueue_attrs()));
- attrs->nice = std_nice[i];
- percpu_std_wq_attrs[i] = attrs;
- }
-
system_wq = alloc_workqueue("events", WQ_PERCPU | __WQ_DEPRECATED, 0);
system_percpu_wq = alloc_workqueue("events", WQ_PERCPU, 0);
system_highpri_wq = alloc_workqueue("events_highpri",
--
2.53.0-Meta
next prev parent reply other threads:[~2026-09-10 14:55 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-10 14:54 [PATCH wq/for-7.4 0/2] workqueue: give percpu its own max_active and derive attrs from flags Breno Leitao
2026-09-10 14:54 ` [PATCH wq/for-7.4 1/2] workqueue: give percpu workqueues their own max_active Breno Leitao
2026-09-10 14:54 ` Breno Leitao [this message]
2026-09-10 22:53 ` [PATCH wq/for-7.4 0/2] workqueue: give percpu its own max_active and derive attrs from flags Tejun Heo
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=20260910-realsplit_last_v2-v1-2-464d64b71b29@debian.org \
--to=leitao@debian.org \
--cc=jiangshanlai@gmail.com \
--cc=kernel-team@meta.com \
--cc=linux-kernel@vger.kernel.org \
--cc=marco.crivellari@suse.com \
--cc=tj@kernel.org \
/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®