On Fri, 2012-10-12 at 10:35 +0100, Jon Medhurst (Tixy) wrote:
On Fri, 2012-10-12 at 14:46 +0530, Viresh Kumar wrote:
Hi Andrey,
Please PULL b.L MP V10 branch from my tree.
I've been testing with the v10 branch and with "Enable HMP priority filter by default" I have get a crash in select_task_rq_fair() on vexpress A9, busy investigating this at the moment...
I've now got to the bottom of the problem...
On homogeneous (non-heterogeneous) systems, arch_get_hmp_domains() still adds two HMP domains, but the second one is empty. This means that when CONFIG_SCHED_HMP_PRIO_FILTER is enabled and hmp_down_migration() unconditionally returns true, then hmp_select_slower_cpu() is called to select a cpu from this empty domain and returns the value NR_CPUS, which makes subsequent code blow up.
One question is should hmp_down_migration() return true even when it hasn't checked there are slower CPUs available?
The attached patch fixes the immediate problem by avoiding the empty domain (which is probably a good thing anyway), however I wonder if there are other circumstances in which hmp_select_{slower,fater}_cpu() can fail? E.g. can tsk_cpus_allowed() ever not intersect with the domain cpus?
I.e. do we need something like...
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index e9dd53c..d3968a6 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -3217,8 +3217,9 @@ static inline struct hmp_domain *hmp_faster_domain(int cpu) static inline unsigned int hmp_select_faster_cpu(struct task_struct *tsk, int cpu) { - return cpumask_any_and(&hmp_faster_domain(cpu)->cpus, - tsk_cpus_allowed(tsk)); + unsigned int new_cpu = cpumask_any_and(&hmp_faster_domain(cpu)->cpus, + tsk_cpus_allowed(tsk)); + return new_cpu < NR_CPUS ? new_cpu : cpu; }
/* @@ -3228,8 +3229,9 @@ static inline unsigned int hmp_select_faster_cpu(struct task_struct *tsk, static inline unsigned int hmp_select_slower_cpu(struct task_struct *tsk, int cpu) { - return cpumask_any_and(&hmp_slower_domain(cpu)->cpus, - tsk_cpus_allowed(tsk)); + unsigned int new_cpu = cpumask_any_and(&hmp_slower_domain(cpu)->cpus, + tsk_cpus_allowed(tsk)); + return new_cpu < NR_CPUS ? new_cpu : cpu; }
static inline void hmp_next_up_delay(struct sched_entity *se, int cpu)