Skip to content

Commit 523a301

Browse files
committed
workqueue: Make default affinity_scope dynamically updatable
While workqueue.default_affinity_scope is writable, it only affects workqueues which are created afterwards and isn't very useful. Instead, let's introduce explicit "default" scope and update the effective scope dynamically when workqueue.default_affinity_scope is changed. Signed-off-by: Tejun Heo <[email protected]>
1 parent 7dbf15c commit 523a301

File tree

4 files changed

+52
-13
lines changed

4 files changed

+52
-13
lines changed

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7014,10 +7014,10 @@
70147014
information, see the Affinity Scopes section in
70157015
Documentation/core-api/workqueue.rst.
70167016

7017-
This can be updated after boot through the matching
7018-
file under /sys/module/workqueue/parameters.
7019-
However, the changed default will only apply to
7020-
unbound workqueues created afterwards.
7017+
This can be changed after boot by writing to the
7018+
matching /sys/module/workqueue/parameters file. All
7019+
workqueues with the "default" affinity scope will be
7020+
updated accordignly.
70217021

70227022
workqueue.debug_force_rr_cpu
70237023
Workqueue used to implicitly guarantee that work

Documentation/core-api/workqueue.rst

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,11 @@ on one of the CPUs which share the last level cache with the issuing CPU.
358358
Once started, the worker may or may not be allowed to move outside the scope
359359
depending on the ``affinity_strict`` setting of the scope.
360360

361-
Workqueue currently supports the following five affinity scopes.
361+
Workqueue currently supports the following affinity scopes.
362+
363+
``default``
364+
Use the scope in module parameter ``workqueue.default_affinity_scope``
365+
which is always set to one of the scopes below.
362366

363367
``cpu``
364368
CPUs are not grouped. A work item issued on one CPU is processed by a
@@ -392,6 +396,9 @@ directory.
392396
``affinity_scope``
393397
Read to see the current affinity scope. Write to change.
394398

399+
When default is the current scope, reading this file will also show the
400+
current effective scope in parentheses, for example, ``default (cache)``.
401+
395402
``affinity_strict``
396403
0 by default indicating that affinity scopes are not strict. When a work
397404
item starts execution, workqueue makes a best-effort attempt to ensure

include/linux/workqueue.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,15 +126,14 @@ struct rcu_work {
126126
};
127127

128128
enum wq_affn_scope {
129+
WQ_AFFN_DFL, /* use system default */
129130
WQ_AFFN_CPU, /* one pod per CPU */
130131
WQ_AFFN_SMT, /* one pod poer SMT */
131132
WQ_AFFN_CACHE, /* one pod per LLC */
132133
WQ_AFFN_NUMA, /* one pod per NUMA node */
133134
WQ_AFFN_SYSTEM, /* one pod across the whole system */
134135

135136
WQ_AFFN_NR_TYPES,
136-
137-
WQ_AFFN_DFL = WQ_AFFN_CACHE,
138137
};
139138

140139
/**

kernel/workqueue.c

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -339,9 +339,10 @@ struct wq_pod_type {
339339
};
340340

341341
static struct wq_pod_type wq_pod_types[WQ_AFFN_NR_TYPES];
342-
static enum wq_affn_scope wq_affn_dfl = WQ_AFFN_DFL;
342+
static enum wq_affn_scope wq_affn_dfl = WQ_AFFN_CACHE;
343343

344344
static const char *wq_affn_names[WQ_AFFN_NR_TYPES] = {
345+
[WQ_AFFN_DFL] = "default",
345346
[WQ_AFFN_CPU] = "cpu",
346347
[WQ_AFFN_SMT] = "smt",
347348
[WQ_AFFN_CACHE] = "cache",
@@ -3734,7 +3735,7 @@ struct workqueue_attrs *alloc_workqueue_attrs(void)
37343735
goto fail;
37353736

37363737
cpumask_copy(attrs->cpumask, cpu_possible_mask);
3737-
attrs->affn_scope = wq_affn_dfl;
3738+
attrs->affn_scope = WQ_AFFN_DFL;
37383739
return attrs;
37393740
fail:
37403741
free_workqueue_attrs(attrs);
@@ -3815,7 +3816,18 @@ static void wqattrs_actualize_cpumask(struct workqueue_attrs *attrs,
38153816
static const struct wq_pod_type *
38163817
wqattrs_pod_type(const struct workqueue_attrs *attrs)
38173818
{
3818-
struct wq_pod_type *pt = &wq_pod_types[attrs->affn_scope];
3819+
enum wq_affn_scope scope;
3820+
struct wq_pod_type *pt;
3821+
3822+
/* to synchronize access to wq_affn_dfl */
3823+
lockdep_assert_held(&wq_pool_mutex);
3824+
3825+
if (attrs->affn_scope == WQ_AFFN_DFL)
3826+
scope = wq_affn_dfl;
3827+
else
3828+
scope = attrs->affn_scope;
3829+
3830+
pt = &wq_pod_types[scope];
38193831

38203832
if (!WARN_ON_ONCE(attrs->affn_scope == WQ_AFFN_NR_TYPES) &&
38213833
likely(pt->nr_pods))
@@ -5847,13 +5859,29 @@ static int parse_affn_scope(const char *val)
58475859

58485860
static int wq_affn_dfl_set(const char *val, const struct kernel_param *kp)
58495861
{
5850-
int affn;
5862+
struct workqueue_struct *wq;
5863+
int affn, cpu;
58515864

58525865
affn = parse_affn_scope(val);
58535866
if (affn < 0)
58545867
return affn;
5868+
if (affn == WQ_AFFN_DFL)
5869+
return -EINVAL;
5870+
5871+
cpus_read_lock();
5872+
mutex_lock(&wq_pool_mutex);
58555873

58565874
wq_affn_dfl = affn;
5875+
5876+
list_for_each_entry(wq, &workqueues, list) {
5877+
for_each_online_cpu(cpu) {
5878+
wq_update_pod(wq, cpu, cpu, true);
5879+
}
5880+
}
5881+
5882+
mutex_unlock(&wq_pool_mutex);
5883+
cpus_read_unlock();
5884+
58575885
return 0;
58585886
}
58595887

@@ -6033,8 +6061,13 @@ static ssize_t wq_affn_scope_show(struct device *dev,
60336061
int written;
60346062

60356063
mutex_lock(&wq->mutex);
6036-
written = scnprintf(buf, PAGE_SIZE, "%s\n",
6037-
wq_affn_names[wq->unbound_attrs->affn_scope]);
6064+
if (wq->unbound_attrs->affn_scope == WQ_AFFN_DFL)
6065+
written = scnprintf(buf, PAGE_SIZE, "%s (%s)\n",
6066+
wq_affn_names[WQ_AFFN_DFL],
6067+
wq_affn_names[wq_affn_dfl]);
6068+
else
6069+
written = scnprintf(buf, PAGE_SIZE, "%s\n",
6070+
wq_affn_names[wq->unbound_attrs->affn_scope]);
60386071
mutex_unlock(&wq->mutex);
60396072

60406073
return written;

0 commit comments

Comments
 (0)