Skip to content

Commit af5b261

Browse files
committed
Merge tag 'wq-for-6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq
Pull workqueue updates from Tejun Heo: - Prepare for defaulting to unbound workqueue. A separate branch was created to ease pulling in from other trees but none of the conversions have landed yet - Memory allocation profiling support added - Misc changes * tag 'wq-for-6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq: workqueue: Use atomic_try_cmpxchg_relaxed() in tryinc_node_nr_active() workqueue: Remove unused work_on_cpu_safe workqueue: Add new WQ_PERCPU flag workqueue: Add system_percpu_wq and system_dfl_wq workqueue: Basic memory allocation profiling support workqueue: fix opencoded cpumask_next_and_wrap() in wq_select_unbound_cpu()
2 parents beace86 + df316ab commit af5b261

File tree

3 files changed

+44
-70
lines changed

3 files changed

+44
-70
lines changed

Documentation/core-api/workqueue.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,12 @@ resources, scheduled and executed.
183183
BH work items cannot sleep. All other features such as delayed queueing,
184184
flushing and canceling are supported.
185185

186+
``WQ_PERCPU``
187+
Work items queued to a per-cpu wq are bound to a specific CPU.
188+
This flag is the right choice when cpu locality is important.
189+
190+
This flag is the complement of ``WQ_UNBOUND``.
191+
186192
``WQ_UNBOUND``
187193
Work items queued to an unbound wq are served by the special
188194
worker-pools which host workers which are not bound to any

include/linux/workqueue.h

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#ifndef _LINUX_WORKQUEUE_H
77
#define _LINUX_WORKQUEUE_H
88

9+
#include <linux/alloc_tag.h>
910
#include <linux/timer.h>
1011
#include <linux/linkage.h>
1112
#include <linux/bitops.h>
@@ -401,6 +402,7 @@ enum wq_flags {
401402
* http://thread.gmane.org/gmane.linux.kernel/1480396
402403
*/
403404
WQ_POWER_EFFICIENT = 1 << 7,
405+
WQ_PERCPU = 1 << 8, /* bound to a specific cpu */
404406

405407
__WQ_DESTROYING = 1 << 15, /* internal: workqueue is destroying */
406408
__WQ_DRAINING = 1 << 16, /* internal: workqueue is draining */
@@ -427,7 +429,7 @@ enum wq_consts {
427429
/*
428430
* System-wide workqueues which are always present.
429431
*
430-
* system_wq is the one used by schedule[_delayed]_work[_on]().
432+
* system_percpu_wq is the one used by schedule[_delayed]_work[_on]().
431433
* Multi-CPU multi-threaded. There are users which expect relatively
432434
* short queue flush time. Don't queue works which can run for too
433435
* long.
@@ -438,7 +440,7 @@ enum wq_consts {
438440
* system_long_wq is similar to system_wq but may host long running
439441
* works. Queue flushing might take relatively long.
440442
*
441-
* system_unbound_wq is unbound workqueue. Workers are not bound to
443+
* system_dfl_wq is unbound workqueue. Workers are not bound to
442444
* any specific CPU, not concurrency managed, and all queued works are
443445
* executed immediately as long as max_active limit is not reached and
444446
* resources are available.
@@ -455,10 +457,12 @@ enum wq_consts {
455457
* system_bh[_highpri]_wq are convenience interface to softirq. BH work items
456458
* are executed in the queueing CPU's BH context in the queueing order.
457459
*/
458-
extern struct workqueue_struct *system_wq;
460+
extern struct workqueue_struct *system_wq; /* use system_percpu_wq, this will be removed */
461+
extern struct workqueue_struct *system_percpu_wq;
459462
extern struct workqueue_struct *system_highpri_wq;
460463
extern struct workqueue_struct *system_long_wq;
461464
extern struct workqueue_struct *system_unbound_wq;
465+
extern struct workqueue_struct *system_dfl_wq;
462466
extern struct workqueue_struct *system_freezable_wq;
463467
extern struct workqueue_struct *system_power_efficient_wq;
464468
extern struct workqueue_struct *system_freezable_power_efficient_wq;
@@ -505,7 +509,8 @@ void workqueue_softirq_dead(unsigned int cpu);
505509
* Pointer to the allocated workqueue on success, %NULL on failure.
506510
*/
507511
__printf(1, 4) struct workqueue_struct *
508-
alloc_workqueue(const char *fmt, unsigned int flags, int max_active, ...);
512+
alloc_workqueue_noprof(const char *fmt, unsigned int flags, int max_active, ...);
513+
#define alloc_workqueue(...) alloc_hooks(alloc_workqueue_noprof(__VA_ARGS__))
509514

510515
#ifdef CONFIG_LOCKDEP
511516
/**
@@ -544,8 +549,8 @@ alloc_workqueue_lockdep_map(const char *fmt, unsigned int flags, int max_active,
544549
* Pointer to the allocated workqueue on success, %NULL on failure.
545550
*/
546551
#define alloc_ordered_workqueue_lockdep_map(fmt, flags, lockdep_map, args...) \
547-
alloc_workqueue_lockdep_map(fmt, WQ_UNBOUND | __WQ_ORDERED | (flags), \
548-
1, lockdep_map, ##args)
552+
alloc_hooks(alloc_workqueue_lockdep_map(fmt, WQ_UNBOUND | __WQ_ORDERED | (flags),\
553+
1, lockdep_map, ##args))
549554
#endif
550555

551556
/**
@@ -577,7 +582,9 @@ alloc_workqueue_lockdep_map(const char *fmt, unsigned int flags, int max_active,
577582

578583
extern void destroy_workqueue(struct workqueue_struct *wq);
579584

580-
struct workqueue_attrs *alloc_workqueue_attrs(void);
585+
struct workqueue_attrs *alloc_workqueue_attrs_noprof(void);
586+
#define alloc_workqueue_attrs(...) alloc_hooks(alloc_workqueue_attrs_noprof(__VA_ARGS__))
587+
581588
void free_workqueue_attrs(struct workqueue_attrs *attrs);
582589
int apply_workqueue_attrs(struct workqueue_struct *wq,
583590
const struct workqueue_attrs *attrs);
@@ -840,19 +847,6 @@ long work_on_cpu_key(int cpu, long (*fn)(void *),
840847
work_on_cpu_key(_cpu, _fn, _arg, &__key); \
841848
})
842849

843-
long work_on_cpu_safe_key(int cpu, long (*fn)(void *),
844-
void *arg, struct lock_class_key *key);
845-
846-
/*
847-
* A new key is defined for each caller to make sure the work
848-
* associated with the function doesn't share its locking class.
849-
*/
850-
#define work_on_cpu_safe(_cpu, _fn, _arg) \
851-
({ \
852-
static struct lock_class_key __key; \
853-
\
854-
work_on_cpu_safe_key(_cpu, _fn, _arg, &__key); \
855-
})
856850
#endif /* CONFIG_SMP */
857851

858852
#ifdef CONFIG_FREEZER

kernel/workqueue.c

Lines changed: 24 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -505,12 +505,16 @@ static struct kthread_worker *pwq_release_worker __ro_after_init;
505505

506506
struct workqueue_struct *system_wq __ro_after_init;
507507
EXPORT_SYMBOL(system_wq);
508+
struct workqueue_struct *system_percpu_wq __ro_after_init;
509+
EXPORT_SYMBOL(system_percpu_wq);
508510
struct workqueue_struct *system_highpri_wq __ro_after_init;
509511
EXPORT_SYMBOL_GPL(system_highpri_wq);
510512
struct workqueue_struct *system_long_wq __ro_after_init;
511513
EXPORT_SYMBOL_GPL(system_long_wq);
512514
struct workqueue_struct *system_unbound_wq __ro_after_init;
513515
EXPORT_SYMBOL_GPL(system_unbound_wq);
516+
struct workqueue_struct *system_dfl_wq __ro_after_init;
517+
EXPORT_SYMBOL_GPL(system_dfl_wq);
514518
struct workqueue_struct *system_freezable_wq __ro_after_init;
515519
EXPORT_SYMBOL_GPL(system_freezable_wq);
516520
struct workqueue_struct *system_power_efficient_wq __ro_after_init;
@@ -1686,17 +1690,14 @@ static void __pwq_activate_work(struct pool_workqueue *pwq,
16861690
static bool tryinc_node_nr_active(struct wq_node_nr_active *nna)
16871691
{
16881692
int max = READ_ONCE(nna->max);
1693+
int old = atomic_read(&nna->nr);
16891694

1690-
while (true) {
1691-
int old, tmp;
1692-
1693-
old = atomic_read(&nna->nr);
1695+
do {
16941696
if (old >= max)
16951697
return false;
1696-
tmp = atomic_cmpxchg_relaxed(&nna->nr, old, old + 1);
1697-
if (tmp == old)
1698-
return true;
1699-
}
1698+
} while (!atomic_try_cmpxchg_relaxed(&nna->nr, &old, old + 1));
1699+
1700+
return true;
17001701
}
17011702

17021703
/**
@@ -2221,12 +2222,9 @@ static int wq_select_unbound_cpu(int cpu)
22212222
}
22222223

22232224
new_cpu = __this_cpu_read(wq_rr_cpu_last);
2224-
new_cpu = cpumask_next_and(new_cpu, wq_unbound_cpumask, cpu_online_mask);
2225-
if (unlikely(new_cpu >= nr_cpu_ids)) {
2226-
new_cpu = cpumask_first_and(wq_unbound_cpumask, cpu_online_mask);
2227-
if (unlikely(new_cpu >= nr_cpu_ids))
2228-
return cpu;
2229-
}
2225+
new_cpu = cpumask_next_and_wrap(new_cpu, wq_unbound_cpumask, cpu_online_mask);
2226+
if (unlikely(new_cpu >= nr_cpu_ids))
2227+
return cpu;
22302228
__this_cpu_write(wq_rr_cpu_last, new_cpu);
22312229

22322230
return new_cpu;
@@ -4629,7 +4627,7 @@ void free_workqueue_attrs(struct workqueue_attrs *attrs)
46294627
*
46304628
* Return: The allocated new workqueue_attr on success. %NULL on failure.
46314629
*/
4632-
struct workqueue_attrs *alloc_workqueue_attrs(void)
4630+
struct workqueue_attrs *alloc_workqueue_attrs_noprof(void)
46334631
{
46344632
struct workqueue_attrs *attrs;
46354633

@@ -5682,12 +5680,12 @@ static struct workqueue_struct *__alloc_workqueue(const char *fmt,
56825680
else
56835681
wq_size = sizeof(*wq);
56845682

5685-
wq = kzalloc(wq_size, GFP_KERNEL);
5683+
wq = kzalloc_noprof(wq_size, GFP_KERNEL);
56865684
if (!wq)
56875685
return NULL;
56885686

56895687
if (flags & WQ_UNBOUND) {
5690-
wq->unbound_attrs = alloc_workqueue_attrs();
5688+
wq->unbound_attrs = alloc_workqueue_attrs_noprof();
56915689
if (!wq->unbound_attrs)
56925690
goto err_free_wq;
56935691
}
@@ -5777,9 +5775,9 @@ static struct workqueue_struct *__alloc_workqueue(const char *fmt,
57775775
}
57785776

57795777
__printf(1, 4)
5780-
struct workqueue_struct *alloc_workqueue(const char *fmt,
5781-
unsigned int flags,
5782-
int max_active, ...)
5778+
struct workqueue_struct *alloc_workqueue_noprof(const char *fmt,
5779+
unsigned int flags,
5780+
int max_active, ...)
57835781
{
57845782
struct workqueue_struct *wq;
57855783
va_list args;
@@ -5794,7 +5792,7 @@ struct workqueue_struct *alloc_workqueue(const char *fmt,
57945792

57955793
return wq;
57965794
}
5797-
EXPORT_SYMBOL_GPL(alloc_workqueue);
5795+
EXPORT_SYMBOL_GPL(alloc_workqueue_noprof);
57985796

57995797
#ifdef CONFIG_LOCKDEP
58005798
__printf(1, 5)
@@ -6770,31 +6768,6 @@ long work_on_cpu_key(int cpu, long (*fn)(void *),
67706768
return wfc.ret;
67716769
}
67726770
EXPORT_SYMBOL_GPL(work_on_cpu_key);
6773-
6774-
/**
6775-
* work_on_cpu_safe_key - run a function in thread context on a particular cpu
6776-
* @cpu: the cpu to run on
6777-
* @fn: the function to run
6778-
* @arg: the function argument
6779-
* @key: The lock class key for lock debugging purposes
6780-
*
6781-
* Disables CPU hotplug and calls work_on_cpu(). The caller must not hold
6782-
* any locks which would prevent @fn from completing.
6783-
*
6784-
* Return: The value @fn returns.
6785-
*/
6786-
long work_on_cpu_safe_key(int cpu, long (*fn)(void *),
6787-
void *arg, struct lock_class_key *key)
6788-
{
6789-
long ret = -ENODEV;
6790-
6791-
cpus_read_lock();
6792-
if (cpu_online(cpu))
6793-
ret = work_on_cpu_key(cpu, fn, arg, key);
6794-
cpus_read_unlock();
6795-
return ret;
6796-
}
6797-
EXPORT_SYMBOL_GPL(work_on_cpu_safe_key);
67986771
#endif /* CONFIG_SMP */
67996772

68006773
#ifdef CONFIG_FREEZER
@@ -7830,10 +7803,11 @@ void __init workqueue_init_early(void)
78307803
}
78317804

78327805
system_wq = alloc_workqueue("events", 0, 0);
7806+
system_percpu_wq = alloc_workqueue("events", 0, 0);
78337807
system_highpri_wq = alloc_workqueue("events_highpri", WQ_HIGHPRI, 0);
78347808
system_long_wq = alloc_workqueue("events_long", 0, 0);
7835-
system_unbound_wq = alloc_workqueue("events_unbound", WQ_UNBOUND,
7836-
WQ_MAX_ACTIVE);
7809+
system_unbound_wq = alloc_workqueue("events_unbound", WQ_UNBOUND, WQ_MAX_ACTIVE);
7810+
system_dfl_wq = alloc_workqueue("events_unbound", WQ_UNBOUND, WQ_MAX_ACTIVE);
78377811
system_freezable_wq = alloc_workqueue("events_freezable",
78387812
WQ_FREEZABLE, 0);
78397813
system_power_efficient_wq = alloc_workqueue("events_power_efficient",
@@ -7844,8 +7818,8 @@ void __init workqueue_init_early(void)
78447818
system_bh_wq = alloc_workqueue("events_bh", WQ_BH, 0);
78457819
system_bh_highpri_wq = alloc_workqueue("events_bh_highpri",
78467820
WQ_BH | WQ_HIGHPRI, 0);
7847-
BUG_ON(!system_wq || !system_highpri_wq || !system_long_wq ||
7848-
!system_unbound_wq || !system_freezable_wq ||
7821+
BUG_ON(!system_wq || !system_percpu_wq|| !system_highpri_wq || !system_long_wq ||
7822+
!system_unbound_wq || !system_freezable_wq || !system_dfl_wq ||
78497823
!system_power_efficient_wq ||
78507824
!system_freezable_power_efficient_wq ||
78517825
!system_bh_wq || !system_bh_highpri_wq);

0 commit comments

Comments
 (0)