Hi Alex,
On 26 August 2015 at 14:26, Alex Shi alex.shi@linaro.org wrote:
Hi, Daniel & Vincent,
Do you like to give a quick testing for this direction on ARM boards? It should be worth have a try. :)
I can give it a try when i will have some spare time
Regards Alex
From d095e6ad805576451c1b6396de99f440a66c342d Mon Sep 17 00:00:00 2001 From: Alex Shi alex.shi@linaro.org Date: Wed, 26 Aug 2015 17:39:37 +0800 Subject: [PATCH] sched: find interrupted idle cpu
Currently we just try to find least idle cpu. If we can get the interrupted idle cpu, we can use it to get benefit from both latency and power side, since the interrupted cpu don't need time to wakeup.
I agree to this could save power but i don't agree with latency. We have to wait for the end of interruption which can be far longer than an exit from wfi
Signed-off-by: Alex Shi alex.shi@linaro.org
include/linux/cpuidle.h | 1 + kernel/sched/fair.c | 9 ++++++++- kernel/sched/sched.h | 18 ++++++++++++++---- 3 files changed, 23 insertions(+), 5 deletions(-)
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index d075d34..2a4521a 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -44,6 +44,7 @@ struct cpuidle_state { int power_usage; /* in mW */ unsigned int target_residency; /* in US */ bool disabled; /* disabled on all CPUs */
int in_irq; int (*enter) (struct cpuidle_device *dev, struct cpuidle_driver *drv,
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 6e2e348..094c815 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -4740,7 +4740,14 @@ find_idlest_cpu(struct sched_group *group, struct task_struct *p, int this_cpu) for_each_cpu_and(i, sched_group_cpus(group), tsk_cpus_allowed(p)) { if (idle_cpu(i)) { struct rq *rq = cpu_rq(i);
struct cpuidle_state *idle = idle_get_state(rq);
struct cpuidle_state *idle = idle_get_state(rq, i);
/* TODO: consider the RT and IRQ load? */
if (idle && idle->in_irq) {
shallowest_idle_cpu = i;
break;
}
find_idlest_cpu is mainly used for new task but it's not in the main call path of a waking up task.
Regards, Vincent
if (idle && idle->exit_latency < min_exit_latency) { /* * We give priority to a CPU whose idle state
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 68cda11..ee336fd 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -9,13 +9,14 @@ #include <linux/irq_work.h> #include <linux/tick.h> #include <linux/slab.h> +#include <linux/cpuidle.h> /* for struct cpuidle_state */
#include "cpupri.h" #include "cpudeadline.h" #include "cpuacct.h" +#include "../time/tick-sched.h"
struct rq; -struct cpuidle_state;
/* task_struct::on_rq states: */ #define TASK_ON_RQ_QUEUED 1 @@ -1271,10 +1272,19 @@ static inline void idle_set_state(struct rq *rq, rq->idle_state = idle_state; }
-static inline struct cpuidle_state *idle_get_state(struct rq *rq) +static inline struct cpuidle_state *idle_get_state(struct rq *rq, int cpu) {
struct cpuidle_state *idle = rq->idle_state;
+#ifdef CONFIG_NO_HZ_COMMON
struct tick_sched *ts = tick_get_tick_sched(cpu);
/* the cpu is interrupted in idle */
if (idle && ts->inidle && !ts->idle_active)
idle->in_irq = 1;
+#endif WARN_ON(!rcu_read_lock_held());
return rq->idle_state;
return idle;
} #else static inline void idle_set_state(struct rq *rq, @@ -1282,7 +1292,7 @@ static inline void idle_set_state(struct rq *rq, { }
-static inline struct cpuidle_state *idle_get_state(struct rq *rq) +static inline struct cpuidle_state *idle_get_state(struct rq *rq, int cpu) { return NULL; } -- 2.3.3