From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1161517AbbKFMEf (ORCPT ); Fri, 6 Nov 2015 07:04:35 -0500 Received: from mailout4.w1.samsung.com ([210.118.77.14]:51938 "EHLO mailout4.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1161413AbbKFMDq (ORCPT ); Fri, 6 Nov 2015 07:03:46 -0500 X-AuditID: cbfec7f5-f794b6d000001495-ed-563c971f5efb From: Arseniy Krasnov To: linux@arm.linux.org.uk, mingo@redhat.com, peterz@infradead.org Cc: a.krasnov@samsung.com, v.tyrtov@samsung.com, s.rogachev@samsung.com, linux-kernel@vger.kernel.org, Tarek Dakhran , Sergey Dyasly , Dmitriy Safonov , Ilya Maximets Subject: [PATCH 11/13] hperf_hmp: task CPU selection logic. Date: Fri, 06 Nov 2015 15:02:45 +0300 Message-id: <1446811367-23783-12-git-send-email-a.krasnov@samsung.com> X-Mailer: git-send-email 1.9.1 In-reply-to: <1446811367-23783-1-git-send-email-a.krasnov@samsung.com> References: <1446811367-23783-1-git-send-email-a.krasnov@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFlrBLMWRmVeSWpSXmKPExsVy+t/xK7ry023CDC4/0bOY91nQ4tPKp2wW V9p/sltc3jWHzeL2ZV6LSwcWMFkc7z3AZDF5tpTFu63XWC3WPz/FaDF1xg92B26PluYeNo/N K7Q8Dr7bw+Txft9VNo++LasYPT5vkgtgi+KySUnNySxLLdK3S+DK+HvwEmvBWo2K/kk5DYy/ 5boYOTkkBEwkdm/Zxw5hi0lcuLeerYuRi0NIYCmjxLotG5ggnHYmiX8Lf7GBVLEJ6Er83LgF zBYRcJLoeXaWEcRmFpjMJLHhaxqILSxgLfFuwTywqSwCqhI3r29gBbF5BdwkLs/exAqxTU7i 5LHJYDYnULyj6zZYvZCAq0TH2XcsExh5FzAyrGIUTS1NLihOSs810itOzC0uzUvXS87P3cQI Cb+vOxiXHrM6xCjAwajEw2uw3DpMiDWxrLgy9xCjBAezkgivHLNNmBBvSmJlVWpRfnxRaU5q 8SFGaQ4WJXHembvehwgJpCeWpGanphakFsFkmTg4pRoYF/J/F5nJ3XLj0R9uLd7Wyzris3/P fflwSt/Fx3m7RZenvAxImqMTnLJ9+uufuwtuBYpH73uYtFz1KbvfY4OZLTNWRtVuLFm/zMjv 0QqGDTP+dfHuSDG51vRuvW6mxbT5S5O8z7tXmlpO3hB3yfDI7kNqE82y3575XtogtWm7+bPU jwZC/7j/VyixFGckGmoxFxUnAgDDKSsYOwIAAA== Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Adds new runqueue selection logic. If task is newly woken(fork or exec) or it is not WF_SYNC wakeup, idlest CPU from both clusters is selected. Else, default wake up logic is used('want_affine'). If it fails, idlest CPU from both clusters is selected. Signed-off-by: Tarek Dakhran Signed-off-by: Sergey Dyasly Signed-off-by: Dmitriy Safonov Signed-off-by: Arseniy Krasnov Signed-off-by: Ilya Maximets --- kernel/sched/fair.c | 132 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 101 insertions(+), 31 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index fd16729..79be023 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -4798,6 +4798,62 @@ static int wake_affine(struct sched_domain *sd, struct task_struct *p, int sync) return 1; } +#ifdef CONFIG_HPERF_HMP +/** + * hmp_select_task_rq_fair(): selects cpu for task. + * @p: task which needs cpu + * + * Returns cpu for task. + * + * Selects idlest cpu for task @p. + */ +static int +hmp_select_task_rq_fair(struct task_struct *p) +{ + int cpu; + int new_cpu; + unsigned long load; + unsigned long scaled_load; + + new_cpu = task_cpu(p); + + load = ULONG_MAX; + /* First check primary cpus */ + for_each_cpu_and(cpu, cpu_online_mask, cpu_fastest_mask) { + if (cpumask_test_cpu(cpu, tsk_cpus_allowed(p))) { + /* Select idle cpu if it exists */ + if (idle_cpu(cpu)) + return cpu; + /* Otherwise select the least loaded cpu */ + scaled_load = (weighted_cpuload(cpu) * + SCHED_CAPACITY_SCALE) / + freq_scale_cpu_power[cpu]; + if (scaled_load < load) { + new_cpu = cpu; + load = scaled_load; + } + } + } + + /* Then check secondary cpus */ + for_each_cpu_and(cpu, cpu_online_mask, cpu_slowest_mask) { + if (cpumask_test_cpu(cpu, tsk_cpus_allowed(p))) { + if (idle_cpu(cpu)) + return cpu; + scaled_load = (weighted_cpuload(cpu) * + SCHED_CAPACITY_SCALE) / + freq_scale_cpu_power[cpu]; + if (scaled_load < load) { + new_cpu = cpu; + load = scaled_load; + } + } + } + + return new_cpu; +} + +#else /* CONFIG_HPERF_HMP */ /* * find_idlest_group finds and returns the least busy CPU group within the * domain. @@ -4905,6 +4961,7 @@ find_idlest_cpu(struct sched_group *group, struct task_struct *p, int this_cpu) return shallowest_idle_cpu != -1 ? shallowest_idle_cpu : least_loaded_cpu; } +#endif /* CONFIG_HPERF_HMP */ /* * Try and locate an idle CPU in the sched_domain. */ @@ -4998,6 +5055,11 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int sd_flag, int wake_f int want_affine = 0; int sync = wake_flags & WF_SYNC; +#ifdef CONFIG_HPERF_HMP + if (!(sd_flag & SD_BALANCE_WAKE) || !sync) + return hmp_select_task_rq_fair(p); +#endif + if (sd_flag & SD_BALANCE_WAKE) want_affine = !wake_wide(p) && cpumask_test_cpu(cpu, tsk_cpus_allowed(p)); @@ -5030,41 +5092,49 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int sd_flag, int wake_f if (!sd) { if (sd_flag & SD_BALANCE_WAKE) /* XXX always ? */ - new_cpu = select_idle_sibling(p, new_cpu); - - } else while (sd) { - struct sched_group *group; - int weight; + if (IS_ENABLED(CONFIG_HPERF_HMP) && sync) + new_cpu = prev_cpu; + else + new_cpu = select_idle_sibling(p, prev_cpu); + } else { +#ifdef CONFIG_HPERF_HMP + new_cpu = hmp_select_task_rq_fair(p); +#else + while (sd) { + struct sched_group *group; + int weight; - if (!(sd->flags & sd_flag)) { - sd = sd->child; - continue; - } + if (!(sd->flags & sd_flag)) { + sd = sd->child; + continue; + } - group = find_idlest_group(sd, p, cpu, sd_flag); - if (!group) { - sd = sd->child; - continue; - } + group = find_idlest_group(sd, p, cpu, sd_flag); + if (!group) { + sd = sd->child; + continue; + } - new_cpu = find_idlest_cpu(group, p, cpu); - if (new_cpu == -1 || new_cpu == cpu) { - /* Now try balancing at a lower domain level of cpu */ - sd = sd->child; - continue; - } + new_cpu = find_idlest_cpu(group, p, cpu); + if (new_cpu == -1 || new_cpu == cpu) { + /* Now try balancing at a lower domain level of cpu */ + sd = sd->child; + continue; + } - /* Now try balancing at a lower domain level of new_cpu */ - cpu = new_cpu; - weight = sd->span_weight; - sd = NULL; - for_each_domain(cpu, tmp) { - if (weight <= tmp->span_weight) - break; - if (tmp->flags & sd_flag) - sd = tmp; - } - /* while loop will break here if sd == NULL */ + /* Now try balancing at a lower domain level of new_cpu */ + cpu = new_cpu; + weight = sd->span_weight; + sd = NULL; + for_each_domain(cpu, tmp) { + if (weight <= tmp->span_weight) + break; + if (tmp->flags & sd_flag) + sd = tmp; + } + /* while loop will break here if sd == NULL */ + } +#endif } rcu_read_unlock(); -- 1.9.1