]> rtime.felk.cvut.cz Git - linux-imx.git/commitdiff
workqueues: Introduce new flag WQ_POWER_EFFICIENT for power oriented workqueues
authorViresh Kumar <viresh.kumar@linaro.org>
Mon, 8 Apr 2013 11:15:40 +0000 (16:45 +0530)
committerTejun Heo <tj@kernel.org>
Tue, 14 May 2013 17:50:06 +0000 (10:50 -0700)
Workqueues can be performance or power-oriented. Currently, most workqueues are
bound to the CPU they were created on. This gives good performance (due to cache
effects) at the cost of potentially waking up otherwise idle cores (Idle from
scheduler's perspective. Which may or may not be physically idle) just to
process some work. To save power, we can allow the work to be rescheduled on a
core that is already awake.

Workqueues created with the WQ_UNBOUND flag will allow some power savings.
However, we don't change the default behaviour of the system.  To enable
power-saving behaviour, a new config option CONFIG_WQ_POWER_EFFICIENT needs to
be turned on. This option can also be overridden by the
workqueue.power_efficient boot parameter.

tj: Updated config description and comments.  Renamed
    CONFIG_WQ_POWER_EFFICIENT to CONFIG_WQ_POWER_EFFICIENT_DEFAULT.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Reviewed-by: Amit Kucheria <amit.kucheria@linaro.org>
Signed-off-by: Tejun Heo <tj@kernel.org>
Documentation/kernel-parameters.txt
include/linux/workqueue.h
kernel/power/Kconfig
kernel/workqueue.c

index c3bfacb92910dc8d044bec88122c4a85328ed8d5..37dfd720de792d20ec8e4684102ce861c36ccb85 100644 (file)
@@ -3320,6 +3320,21 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        that this also can be controlled per-workqueue for
                        workqueues visible under /sys/bus/workqueue/.
 
+       workqueue.power_efficient
+                       Per-cpu workqueues are generally preferred because
+                       they show better performance thanks to cache
+                       locality; unfortunately, per-cpu workqueues tend to
+                       be more power hungry than unbound workqueues.
+
+                       Enabling this makes the per-cpu workqueues which
+                       were observed to contribute significantly to power
+                       consumption unbound, leading to measurably lower
+                       power usage at the cost of small performance
+                       overhead.
+
+                       The default value of this parameter is determined by
+                       the config option CONFIG_WQ_POWER_EFFICIENT_DEFAULT.
+
        x2apic_phys     [X86-64,APIC] Use x2apic physical mode instead of
                        default x2apic cluster mode on platforms
                        supporting x2apic.
index 623488fdc1f5ee6cf24f3745902c4b95c1f5417d..fc0136b604f2b01dd30303f8ead3605ebc0017fd 100644 (file)
@@ -303,6 +303,33 @@ enum {
        WQ_CPU_INTENSIVE        = 1 << 5, /* cpu instensive workqueue */
        WQ_SYSFS                = 1 << 6, /* visible in sysfs, see wq_sysfs_register() */
 
+       /*
+        * Per-cpu workqueues are generally preferred because they tend to
+        * show better performance thanks to cache locality.  Per-cpu
+        * workqueues exclude the scheduler from choosing the CPU to
+        * execute the worker threads, which has an unfortunate side effect
+        * of increasing power consumption.
+        *
+        * The scheduler considers a CPU idle if it doesn't have any task
+        * to execute and tries to keep idle cores idle to conserve power;
+        * however, for example, a per-cpu work item scheduled from an
+        * interrupt handler on an idle CPU will force the scheduler to
+        * excute the work item on that CPU breaking the idleness, which in
+        * turn may lead to more scheduling choices which are sub-optimal
+        * in terms of power consumption.
+        *
+        * Workqueues marked with WQ_POWER_EFFICIENT are per-cpu by default
+        * but become unbound if workqueue.power_efficient kernel param is
+        * specified.  Per-cpu workqueues which are identified to
+        * contribute significantly to power-consumption are identified and
+        * marked with this flag and enabling the power_efficient mode
+        * leads to noticeable power saving at the cost of small
+        * performance disadvantage.
+        *
+        * http://thread.gmane.org/gmane.linux.kernel/1480396
+        */
+       WQ_POWER_EFFICIENT      = 1 << 7,
+
        __WQ_DRAINING           = 1 << 16, /* internal: workqueue is draining */
        __WQ_ORDERED            = 1 << 17, /* internal: workqueue is ordered */
 
index 5dfdc9ea180b8ac497ed915c45b809fb65799261..46455961a88fb75c3ce4e426c4f9b8ff022ecbcc 100644 (file)
@@ -263,6 +263,26 @@ config PM_GENERIC_DOMAINS
        bool
        depends on PM
 
+config WQ_POWER_EFFICIENT_DEFAULT
+       bool "Enable workqueue power-efficient mode by default"
+       depends on PM
+       default n
+       help
+         Per-cpu workqueues are generally preferred because they show
+         better performance thanks to cache locality; unfortunately,
+         per-cpu workqueues tend to be more power hungry than unbound
+         workqueues.
+
+         Enabling workqueue.power_efficient kernel parameter makes the
+         per-cpu workqueues which were observed to contribute
+         significantly to power consumption unbound, leading to measurably
+         lower power usage at the cost of small performance overhead.
+
+         This config option determines whether workqueue.power_efficient
+         is enabled by default.
+
+         If in doubt, say N.
+
 config PM_GENERIC_DOMAINS_SLEEP
        def_bool y
        depends on PM_SLEEP && PM_GENERIC_DOMAINS
index 4aa9f5bc6b2dfdd9f152f5d20bf06c15f070aa21..8068d97ce141c7138881d8b17fca8f0096de5703 100644 (file)
@@ -272,6 +272,15 @@ static cpumask_var_t *wq_numa_possible_cpumask;
 static bool wq_disable_numa;
 module_param_named(disable_numa, wq_disable_numa, bool, 0444);
 
+/* see the comment above the definition of WQ_POWER_EFFICIENT */
+#ifdef CONFIG_WQ_POWER_EFFICIENT_DEFAULT
+static bool wq_power_efficient = true;
+#else
+static bool wq_power_efficient;
+#endif
+
+module_param_named(power_efficient, wq_power_efficient, bool, 0444);
+
 static bool wq_numa_enabled;           /* unbound NUMA affinity enabled */
 
 /* buf for wq_update_unbound_numa_attrs(), protected by CPU hotplug exclusion */
@@ -4085,6 +4094,10 @@ struct workqueue_struct *__alloc_workqueue_key(const char *fmt,
        struct workqueue_struct *wq;
        struct pool_workqueue *pwq;
 
+       /* see the comment above the definition of WQ_POWER_EFFICIENT */
+       if ((flags & WQ_POWER_EFFICIENT) && wq_power_efficient)
+               flags |= WQ_UNBOUND;
+
        /* allocate wq and format name */
        if (flags & WQ_UNBOUND)
                tbl_size = wq_numa_tbl_len * sizeof(wq->numa_pwq_tbl[0]);