From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1161552AbbKFMFz (ORCPT ); Fri, 6 Nov 2015 07:05:55 -0500 Received: from mailout1.w1.samsung.com ([210.118.77.11]:48820 "EHLO mailout1.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1161363AbbKFMDk (ORCPT ); Fri, 6 Nov 2015 07:03:40 -0500 X-AuditID: cbfec7f5-f794b6d000001495-d4-563c9719ce23 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 05/13] hperf_hmp: introduce druntime metric. Date: Fri, 06 Nov 2015 15:02:39 +0300 Message-id: <1446811367-23783-6-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/xK7qS023CDDZMUraY91nQ4tPKp2wW V9p/sltc3jWHzeL2ZV6LSwcWMFkc7z3AZDF5tpTFu63XWC3WPz/FaDF1xg92B26PluYeNo/N K7Q8Dr7bw+Txft9VNo++LasYPT5vkgtgi+KySUnNySxLLdK3S+DKuD9zC3PBA52KCROOsDUw /lPpYuTkkBAwkVh0ei4zhC0mceHeerYuRi4OIYGljBLff9xjBUkICbQzSfRsCgKx2QR0JX5u 3MIGYosIOEn0PDvLCGIzC0xmktjwNQ3EFhawkTjQtxUsziKgKjFtegvYHF4BV4lZX58zQiyT kzh5bDJYnFPATaKj6zY7xC5XiY6z71gmMPIuYGRYxSiaWppcUJyUnmukV5yYW1yal66XnJ+7 iRESfl93MC49ZnWIUYCDUYmH12C5dZgQa2JZcWXuIUYJDmYlEV45ZpswId6UxMqq1KL8+KLS nNTiQ4zSHCxK4rwzd70PERJITyxJzU5NLUgtgskycXBKNTAuucmT53Aq5KR4mubTLh/+ptmZ wrvcJji+j77QlCnlPnmpFtOvzjmzLl0SXVyxref5VjfvsMXHVk4KPL7k+9uPC+97cB+daDZn 4XYH2eY3u142XOWQ9tDVj7xtsuDhpwqf7z6Ztsf3KL+1d51351r3x/k81lb31s7zv3vIxjKT la/y0Pbq7HI1JZbijERDLeai4kQAlw02OzsCAAA= Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This patch adds special per-task metric to look for candidate for migration between HMP domains(clusters). 'druntime' grows up when task runs on A7 cluster, and goes down on A15 cluster. Also druntime is scaled according load on little cluster in order to align its value with big cluster's total druntime. For migration from big/little to little/big cluster task with lowest/highest 'druntime' chosen. 'druntime' is used to execute each task on each cluster approximately same amount of time. 'druntime' is calculated each call of default 'update_curr' function. 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 --- include/linux/sched.h | 3 ++ kernel/sched/core.c | 3 ++ kernel/sched/fair.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 121 insertions(+) diff --git a/include/linux/sched.h b/include/linux/sched.h index aa72125..89c1bf3 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1257,6 +1257,9 @@ struct sched_entity { struct list_head group_node; unsigned int on_rq; +#ifdef CONFIG_HPERF_HMP + long druntime; +#endif u64 exec_start; u64 sum_exec_runtime; u64 vruntime; diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 8747e06..6883a00 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -2085,6 +2085,9 @@ static void __sched_fork(unsigned long clone_flags, struct task_struct *p) p->se.prev_sum_exec_runtime = 0; p->se.nr_migrations = 0; p->se.vruntime = 0; +#ifdef CONFIG_HPERF_HMP + p->se.druntime = 0; +#endif INIT_LIST_HEAD(&p->se.group_node); #ifdef CONFIG_SCHEDSTATS diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index c57007f..e94fab4 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -102,6 +102,10 @@ unsigned int __read_mostly sysctl_sched_shares_window = 10000000UL; #ifdef CONFIG_HPERF_HMP extern void hmp_set_cpu_masks(struct cpumask *, struct cpumask *); +static atomic_t a15_nr_hmp_busy = ATOMIC_INIT(0); +static atomic_t a7_nr_hmp_busy = ATOMIC_INIT(0); +static atomic_t hmp_imbalance = ATOMIC_INIT(0); + static unsigned int freq_scale_cpu_power[CONFIG_NR_CPUS]; #endif /* CONFIG_HPERF_HMP */ @@ -660,6 +664,115 @@ static u64 sched_vslice(struct cfs_rq *cfs_rq, struct sched_entity *se) return calc_delta_fair(sched_slice(cfs_rq, se), se); } +#ifdef CONFIG_HPERF_HMP +static bool +is_task_hmp(struct task_struct *task, const struct cpumask *task_cpus) +{ + if (!task_cpus) + task_cpus = tsk_cpus_allowed(task); + + /* + * Check if a task has cpus_allowed only for one CPU domain (A15 or A7) + */ + return !(cpumask_intersects(task_cpus, cpu_fastest_mask) ^ + cpumask_intersects(task_cpus, cpu_slowest_mask)); +} + +#ifdef CONFIG_HPERF_HMP_DEBUG +static inline void check_druntime_sum(struct rq *rq, long druntime_sum) +{ + BUG_ON(rq->cfs.h_nr_running == 0 && druntime_sum != 0); + + if (cpu_is_fastest(rq->cpu)) + BUG_ON(druntime_sum > 0); + else + BUG_ON(druntime_sum < 0); +} +#else +static inline void check_druntime_sum(struct rq *rq, long druntime_sum) +{ +} +#endif + +static inline void add_druntime_sum(struct rq *rq, long delta) +{ + rq->druntime_sum += delta; + check_druntime_sum(rq, rq->druntime_sum); +} +/* Updates druntime for a task */ +static inline void +update_hmp_stat(struct cfs_rq *cfs_rq, struct sched_entity *curr, + unsigned long delta_exec) +{ + long to_add; + unsigned int hmp_fairness_threshold = 240; + struct rq *rq = rq_of(cfs_rq); + int a7_nr_hmp_busy_tmp; + + if (atomic_read(&hmp_imbalance) == 0) + return; + + if (!curr->on_rq) + return; + + if (!entity_is_task(curr)) + return; + + if (!task_of(curr)->on_rq) + return; + + if (!cfs_rq->h_nr_running) + return; + + if (!is_task_hmp(task_of(curr), NULL)) + return; + + delta_exec = delta_exec >> 10; + + if (cpu_is_fastest(rq->cpu)) + to_add = -delta_exec; + else + to_add = delta_exec; + + to_add -= curr->druntime; + + /* Avoid values with the different sign */ + if ((cpu_is_fastest(rq->cpu) && to_add >= 0) || + (!cpu_is_fastest(rq->cpu) && to_add <= 0)) + return; + + to_add /= (long)(2 + 4 * hmp_fairness_threshold / + (cfs_rq->h_nr_running + 1)); + + a7_nr_hmp_busy_tmp = atomic_read(&a7_nr_hmp_busy); + /* druntime balancing between the domains */ + if (!cpu_is_fastest(rq->cpu) && a7_nr_hmp_busy_tmp) { + to_add *= atomic_read(&a15_nr_hmp_busy); + to_add /= a7_nr_hmp_busy_tmp; + } + + if (cpu_is_fastest(rq->cpu)) { + if (curr->druntime < 0) + add_druntime_sum(rq, to_add); + else if ((curr->druntime + to_add) < 0) + add_druntime_sum(rq, curr->druntime + to_add); + } else { + if (curr->druntime > 0) + add_druntime_sum(rq, to_add); + else if ((curr->druntime + to_add) > 0) + add_druntime_sum(rq, curr->druntime + to_add); + } + + curr->druntime += to_add; +} +#else +static inline void +update_hmp_stat(struct cfs_rq *cfs_rq, struct sched_entity *curr, + unsigned long delta_exec) +{ +} +#endif /* CONFIG_HPERF_HMP */ + #ifdef CONFIG_SMP static int select_idle_sibling(struct task_struct *p, int cpu); static unsigned long task_h_load(struct task_struct *p); @@ -735,6 +848,8 @@ static void update_curr(struct cfs_rq *cfs_rq) } account_cfs_rq_runtime(cfs_rq, delta_exec); + + update_hmp_stat(cfs_rq, curr, delta_exec); } static void update_curr_fair(struct rq *rq) -- 1.9.1