2013/3/18 Viresh Kumar viresh.kumar@linaro.org:
In order to save power, it would be useful to schedule light weight work on cpus that aren't IDLE instead of waking up an IDLE one.
By idle cpu (from scheduler's perspective) we mean:
- Current task is idle task
- nr_running == 0
- wake_list is empty
This is already implemented for timers as get_nohz_timer_target(). We can figure out few more users of this feature, like workqueues.
This patch converts get_nohz_timer_target() into a generic API sched_select_cpu() so that other frameworks (like workqueue) can also use it.
This routine returns the cpu which is non-idle. It accepts a bitwise OR of SD_* flags present in linux/sched.h. If the local CPU isn't idle OR all cpus are idle, local cpu is returned back. If local cpu is idle, then we must look for another CPU which have all the flags passed as argument as set and isn't idle.
This patch reuses the code from get_nohz_timer_target() routine, which had similar implementation.
Signed-off-by: Viresh Kumar viresh.kumar@linaro.org
include/linux/sched.h | 21 +++++++++++++++-- kernel/sched/core.c | 63 +++++++++++++++++++++++++++++---------------------- 2 files changed, 55 insertions(+), 29 deletions(-)
diff --git a/include/linux/sched.h b/include/linux/sched.h index e20580d..216fa0d 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -230,14 +230,31 @@ extern void init_idle_bootup_task(struct task_struct *idle);
extern int runqueue_is_locked(int cpu);
-#if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ) +#ifdef CONFIG_SMP +extern int sched_select_cpu(unsigned int sd_flags);
+#ifdef CONFIG_NO_HZ extern void nohz_balance_enter_idle(int cpu); extern void set_cpu_sd_state_idle(void); -extern int get_nohz_timer_target(void); +/*
- In the semi idle case, use the nearest busy cpu for migrating timers
- from an idle cpu. This is good for power-savings.
- We don't do similar optimization for completely idle system, as
- selecting an idle cpu will add more delays to the timers than intended
- (as that cpu's timer base may not be uptodate wrt jiffies etc).
- */
+#define get_nohz_timer_target() sched_select_cpu(0) #else static inline void nohz_balance_enter_idle(int cpu) { } static inline void set_cpu_sd_state_idle(void) { }
+static inline int sched_select_cpu(unsigned int sd_flags) +{
return raw_smp_processor_id();
I feel this should be symetric with the requirement of having preemption disabled as in the CONFIG_NO_HZ version. This should be smp_processor_id().
[...]
@@ -648,6 +621,42 @@ void sched_avg_update(struct rq *rq) } }
+/*
- This routine returns the nearest non-idle cpu. It accepts a bitwise OR of
- SD_* flags present in linux/sched.h. If the local CPU isn't idle, it is
- returned back. If it is idle, then we must look for another CPU which have
- all the flags passed as argument as set.
- */
+int sched_select_cpu(unsigned int sd_flags)
It would be nice to have some more precise naming. sched_select_busy_cpu() ?