Hi, Daniel & Vincent,
Do you like to give a quick testing for this direction on ARM boards? It should be worth have a try. :)
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.
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; + } + 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; }
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
On 08/26/2015 09:13 PM, Vincent Guittot wrote:
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
Thanks! Waiting for your good news. :)
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
That depends on the different cpus. For general type, the exit from wfi is usually several hundreds ms. do you have data for how long time a usual interrupt needed?
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.
Yes, I omitted this point.
On 26 August 2015 at 15:35, Alex Shi alex.shi@linaro.org wrote:
On 08/26/2015 09:13 PM, Vincent Guittot wrote:
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
Thanks! Waiting for your good news. :)
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
That depends on the different cpus. For general type, the exit from wfi is usually several hundreds ms. do you have data for how long time a
several hundreds of ms for wfi (Wait For Interrupt) ? it should be more in the range of few micro seconds. At the opposite, waking up from a cluster power down state could take some ms but
Which platform have you got in mind that needs several hundreds of ms to leave WFI or another power down state ?
Regards, Vincent
usual interrupt needed?
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.
Yes, I omitted this point.
On 08/26/2015 09:50 PM, Vincent Guittot wrote:
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
That depends on the different cpus. For general type, the exit from wfi is usually several hundreds ms. do you have data for how long time a
several hundreds of ms for wfi (Wait For Interrupt) ? it should be more in the range of few micro seconds. At the opposite, waking up from a cluster power down state could take some ms but
Which platform have you got in mind that needs several hundreds of ms to leave WFI or another power down state ?
Uh, my mistaken, the usual idle exit_latency unit is us, not ms. but its span is so big, from 10us to 5000us (exynos coupled idle) or 10000us(one of intel cpu).
Uh, seems it need to check if there some latency lost on this patch.
linaro-kernel@lists.linaro.org