diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-02 22:53:30 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-02 22:53:30 -0400 |
commit | f317ff9eed763e99bd226a447f93d42509434f43 (patch) | |
tree | d77edfcdb1e7c32c30327f50dce04bcff8ec1531 /kernel | |
parent | 13cc56013842a847a0f6ff805d9ed9181e753ef8 (diff) | |
parent | a85f1a41f020bc2c97611060bcfae6f48a1db28d (diff) |
Merge branch 'for-3.11' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq
Pull workqueue changes from Tejun Heo:
"Surprisingly, Lai and I didn't break too many things implementing
custom pools and stuff last time around and there aren't any follow-up
changes necessary at this point.
The only change in this pull request is Viresh's patches to make some
per-cpu workqueues to behave as unbound workqueues dependent on a boot
param whose default can be configured via a config option. This leads
to higher processing overhead / lower bandwidth as more work items are
bounced across CPUs; however, it can lead to noticeable powersave in
certain configurations - ~10% w/ idlish constant workload on a
big.LITTLE configuration according to Viresh.
This is because per-cpu workqueues interfere with how the scheduler
perceives whether or not each CPU is idle by forcing pinned tasks on
them, which makes the scheduler's power-aware scheduling decisions
less effective.
Its effectiveness is likely less pronounced on homogenous
configurations and this type of optimization can probably be made
automatic; however, the changes are pretty minimal and the affected
workqueues are clearly marked, so it's an easy gain for some
configurations for the time being with pretty unintrusive changes."
* 'for-3.11' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq:
fbcon: queue work on power efficient wq
block: queue work on power efficient wq
PHYLIB: queue work on system_power_efficient_wq
workqueue: Add system wide power_efficient workqueues
workqueues: Introduce new flag WQ_POWER_EFFICIENT for power oriented workqueues
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/power/Kconfig | 20 | ||||
-rw-r--r-- | kernel/workqueue.c | 26 |
2 files changed, 45 insertions, 1 deletions
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index 9c39de095ba9..d444c4e834f4 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig | |||
@@ -262,6 +262,26 @@ config PM_GENERIC_DOMAINS | |||
262 | bool | 262 | bool |
263 | depends on PM | 263 | depends on PM |
264 | 264 | ||
265 | config WQ_POWER_EFFICIENT_DEFAULT | ||
266 | bool "Enable workqueue power-efficient mode by default" | ||
267 | depends on PM | ||
268 | default n | ||
269 | help | ||
270 | Per-cpu workqueues are generally preferred because they show | ||
271 | better performance thanks to cache locality; unfortunately, | ||
272 | per-cpu workqueues tend to be more power hungry than unbound | ||
273 | workqueues. | ||
274 | |||
275 | Enabling workqueue.power_efficient kernel parameter makes the | ||
276 | per-cpu workqueues which were observed to contribute | ||
277 | significantly to power consumption unbound, leading to measurably | ||
278 | lower power usage at the cost of small performance overhead. | ||
279 | |||
280 | This config option determines whether workqueue.power_efficient | ||
281 | is enabled by default. | ||
282 | |||
283 | If in doubt, say N. | ||
284 | |||
265 | config PM_GENERIC_DOMAINS_SLEEP | 285 | config PM_GENERIC_DOMAINS_SLEEP |
266 | def_bool y | 286 | def_bool y |
267 | depends on PM_SLEEP && PM_GENERIC_DOMAINS | 287 | depends on PM_SLEEP && PM_GENERIC_DOMAINS |
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index ee8e29a2320c..f02c4a4a0c3c 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c | |||
@@ -272,6 +272,15 @@ static cpumask_var_t *wq_numa_possible_cpumask; | |||
272 | static bool wq_disable_numa; | 272 | static bool wq_disable_numa; |
273 | module_param_named(disable_numa, wq_disable_numa, bool, 0444); | 273 | module_param_named(disable_numa, wq_disable_numa, bool, 0444); |
274 | 274 | ||
275 | /* see the comment above the definition of WQ_POWER_EFFICIENT */ | ||
276 | #ifdef CONFIG_WQ_POWER_EFFICIENT_DEFAULT | ||
277 | static bool wq_power_efficient = true; | ||
278 | #else | ||
279 | static bool wq_power_efficient; | ||
280 | #endif | ||
281 | |||
282 | module_param_named(power_efficient, wq_power_efficient, bool, 0444); | ||
283 | |||
275 | static bool wq_numa_enabled; /* unbound NUMA affinity enabled */ | 284 | static bool wq_numa_enabled; /* unbound NUMA affinity enabled */ |
276 | 285 | ||
277 | /* buf for wq_update_unbound_numa_attrs(), protected by CPU hotplug exclusion */ | 286 | /* buf for wq_update_unbound_numa_attrs(), protected by CPU hotplug exclusion */ |
@@ -305,6 +314,10 @@ struct workqueue_struct *system_unbound_wq __read_mostly; | |||
305 | EXPORT_SYMBOL_GPL(system_unbound_wq); | 314 | EXPORT_SYMBOL_GPL(system_unbound_wq); |
306 | struct workqueue_struct *system_freezable_wq __read_mostly; | 315 | struct workqueue_struct *system_freezable_wq __read_mostly; |
307 | EXPORT_SYMBOL_GPL(system_freezable_wq); | 316 | EXPORT_SYMBOL_GPL(system_freezable_wq); |
317 | struct workqueue_struct *system_power_efficient_wq __read_mostly; | ||
318 | EXPORT_SYMBOL_GPL(system_power_efficient_wq); | ||
319 | struct workqueue_struct *system_freezable_power_efficient_wq __read_mostly; | ||
320 | EXPORT_SYMBOL_GPL(system_freezable_power_efficient_wq); | ||
308 | 321 | ||
309 | static int worker_thread(void *__worker); | 322 | static int worker_thread(void *__worker); |
310 | static void copy_workqueue_attrs(struct workqueue_attrs *to, | 323 | static void copy_workqueue_attrs(struct workqueue_attrs *to, |
@@ -4086,6 +4099,10 @@ struct workqueue_struct *__alloc_workqueue_key(const char *fmt, | |||
4086 | struct workqueue_struct *wq; | 4099 | struct workqueue_struct *wq; |
4087 | struct pool_workqueue *pwq; | 4100 | struct pool_workqueue *pwq; |
4088 | 4101 | ||
4102 | /* see the comment above the definition of WQ_POWER_EFFICIENT */ | ||
4103 | if ((flags & WQ_POWER_EFFICIENT) && wq_power_efficient) | ||
4104 | flags |= WQ_UNBOUND; | ||
4105 | |||
4089 | /* allocate wq and format name */ | 4106 | /* allocate wq and format name */ |
4090 | if (flags & WQ_UNBOUND) | 4107 | if (flags & WQ_UNBOUND) |
4091 | tbl_size = wq_numa_tbl_len * sizeof(wq->numa_pwq_tbl[0]); | 4108 | tbl_size = wq_numa_tbl_len * sizeof(wq->numa_pwq_tbl[0]); |
@@ -4985,8 +5002,15 @@ static int __init init_workqueues(void) | |||
4985 | WQ_UNBOUND_MAX_ACTIVE); | 5002 | WQ_UNBOUND_MAX_ACTIVE); |
4986 | system_freezable_wq = alloc_workqueue("events_freezable", | 5003 | system_freezable_wq = alloc_workqueue("events_freezable", |
4987 | WQ_FREEZABLE, 0); | 5004 | WQ_FREEZABLE, 0); |
5005 | system_power_efficient_wq = alloc_workqueue("events_power_efficient", | ||
5006 | WQ_POWER_EFFICIENT, 0); | ||
5007 | system_freezable_power_efficient_wq = alloc_workqueue("events_freezable_power_efficient", | ||
5008 | WQ_FREEZABLE | WQ_POWER_EFFICIENT, | ||
5009 | 0); | ||
4988 | BUG_ON(!system_wq || !system_highpri_wq || !system_long_wq || | 5010 | BUG_ON(!system_wq || !system_highpri_wq || !system_long_wq || |
4989 | !system_unbound_wq || !system_freezable_wq); | 5011 | !system_unbound_wq || !system_freezable_wq || |
5012 | !system_power_efficient_wq || | ||
5013 | !system_freezable_power_efficient_wq); | ||
4990 | return 0; | 5014 | return 0; |
4991 | } | 5015 | } |
4992 | early_initcall(init_workqueues); | 5016 | early_initcall(init_workqueues); |