From patchwork Tue Nov 20 04:41:51 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: preeti X-Patchwork-Id: 1770431 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork1.kernel.org (Postfix) with ESMTP id 98BAE3FCAE for ; Tue, 20 Nov 2012 04:44:28 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TaffZ-0000EC-T0; Tue, 20 Nov 2012 04:42:45 +0000 Received: from e23smtp07.au.ibm.com ([202.81.31.140]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1TaffU-0000DM-Jq for linux-arm-kernel@lists.infradead.org; Tue, 20 Nov 2012 04:42:42 +0000 Received: from /spool/local by e23smtp07.au.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 20 Nov 2012 14:38:21 +1000 Received: from d23relay04.au.ibm.com (202.81.31.246) by e23smtp07.au.ibm.com (202.81.31.204) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Tue, 20 Nov 2012 14:38:13 +1000 Received: from d23av03.au.ibm.com (d23av03.au.ibm.com [9.190.234.97]) by d23relay04.au.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id qAK4VtxM38863098 for ; Tue, 20 Nov 2012 15:31:55 +1100 Received: from d23av03.au.ibm.com (loopback [127.0.0.1]) by d23av03.au.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id qAK4gOLb008451 for ; Tue, 20 Nov 2012 15:42:25 +1100 Received: from [9.124.35.27] (preeti.in.ibm.com [9.124.35.27]) by d23av03.au.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id qAK4gIRk008364; Tue, 20 Nov 2012 15:42:19 +1100 Message-ID: <50AB0A0F.8070802@linux.vnet.ibm.com> Date: Tue, 20 Nov 2012 10:11:51 +0530 From: Preeti U Murthy User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:14.0) Gecko/20120717 Thunderbird/14.0 MIME-Version: 1.0 To: paulmck@linux.vnet.ibm.com, vincent.guittot@linaro.org, a.p.zijlstra@chello.nl, viresh.kumar@linaro.org, linux-kernel@vger.kernel.org, amit.kucheria@linaro.org, Morten.Rasmussen@arm.com, paul.mckenney@linaro.org, akpm@linux-foundation.org, svaidy@linux.vnet.ibm.com, arjan@linux.intel.com, mingo@kernel.org, pjt@google.com Subject: [PATCH] sched: Explicit division calls on 64-bit integers References: <20121115164730.17426.36051.stgit@preeti.in.ibm.com> In-Reply-To: <20121115164730.17426.36051.stgit@preeti.in.ibm.com> x-cbid: 12112004-0260-0000-0000-000002301BE7 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20121119_234241_400672_C1F7FE5D X-CRM114-Status: GOOD ( 18.78 ) X-Spam-Score: -1.9 (-) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-1.9 points) pts rule name description ---- ---------------------- -------------------------------------------------- 3.0 KHOP_BIG_TO_CC Sent to 10+ recipients instaed of Bcc or a list -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at http://www.dnswl.org/, medium trust [202.81.31.140 listed in list.dnswl.org] -0.7 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: venki@google.com, robin.randhawa@arm.com, linaro-dev@lists.linaro.org, suresh.b.siddha@intel.com, deepthi@linux.vnet.ibm.com, mjg59@srcf.ucam.org, srivatsa.bhat@linux.vnet.ibm.com, Arvind.Chauhan@arm.com, linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Certain gcc tool chains convert the division on a 64-bit dividend into a __aeabi_uldivmod call which does unnecessary 64-bit by 64-bit divides although the divisor is 32-bit.This 64 by 64 bit division is not implemented in the kernel for reasons of efficiency,which results in undefined reference errors during link time.Hence perform the division on 64-bit dividends using do_div() function. The below use case is the integration of Per-entity-Load-Tracking metric with the load balancer,where cfs_rq->runnable_load_avg, a 64 bit unsigned integer is used to as the base metric for load balancing. Signed-off-by: Preeti U Murthy --- kernel/sched/fair.c | 51 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index f8f3a29..7cd3096 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -2982,9 +2982,13 @@ static u64 cpu_avg_load_per_task(int cpu) { struct rq *rq = cpu_rq(cpu); unsigned long nr_running = ACCESS_ONCE(rq->nr_running); + u64 cfs_avg_load_per_task; - if (nr_running) - return rq->cfs.runnable_load_avg / nr_running; + if (nr_running) { + cfs_avg_load_per_task = rq->cfs.runnable_load_avg; + do_div(cfs_avg_load_per_task, nr_running); + return cfs_avg_load_per_task; + } return 0; } @@ -3249,7 +3253,8 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p, } /* Adjust by relative CPU power of the group */ - avg_load = (avg_load * SCHED_POWER_SCALE) / group->sgp->power; + avg_load = (avg_load * SCHED_POWER_SCALE); + do_div(avg_load, group->sgp->power); if (local_group) { this_load = avg_load; @@ -4756,7 +4761,8 @@ static inline void update_sg_lb_stats(struct lb_env *env, } /* Adjust by relative CPU power of the group */ - sgs->avg_load = (sgs->group_load*SCHED_POWER_SCALE) / group->sgp->power; + sgs->avg_load = (sgs->group_load*SCHED_POWER_SCALE); + do_div(sgs->avg_load, group->sgp->power); /* * Consider the group unbalanced when the imbalance is larger @@ -4767,8 +4773,10 @@ static inline void update_sg_lb_stats(struct lb_env *env, * normalized nr_running number somewhere that negates * the hierarchy? */ - if (sgs->sum_nr_running) - avg_load_per_task = sgs->sum_weighted_load / sgs->sum_nr_running; + if (sgs->sum_nr_running) { + avg_load_per_task = sgs->sum_weighted_load; + do_div(avg_load_per_task, sgs->sum_nr_running); + } if ((max_cpu_load - min_cpu_load) >= avg_load_per_task && (max_nr_running - min_nr_running) > 1) @@ -4953,7 +4961,7 @@ void fix_small_imbalance(struct lb_env *env, struct sd_lb_stats *sds) u64 scaled_busy_load_per_task; if (sds->this_nr_running) { - sds->this_load_per_task /= sds->this_nr_running; + do_div(sds->this_load_per_task, sds->this_nr_running); if (sds->busiest_load_per_task > sds->this_load_per_task) imbn = 1; @@ -4964,7 +4972,7 @@ void fix_small_imbalance(struct lb_env *env, struct sd_lb_stats *sds) scaled_busy_load_per_task = sds->busiest_load_per_task * SCHED_POWER_SCALE; - scaled_busy_load_per_task /= sds->busiest->sgp->power; + do_div(scaled_busy_load_per_task, sds->busiest->sgp->power); if (sds->max_load - sds->this_load + scaled_busy_load_per_task >= (scaled_busy_load_per_task * imbn)) { @@ -4985,20 +4993,21 @@ void fix_small_imbalance(struct lb_env *env, struct sd_lb_stats *sds) pwr_now /= SCHED_POWER_SCALE; /* Amount of load we'd subtract */ - tmp = (sds->busiest_load_per_task * SCHED_POWER_SCALE) / - sds->busiest->sgp->power; + tmp = (sds->busiest_load_per_task * SCHED_POWER_SCALE); + do_div(tmp, sds->busiest->sgp->power); if (sds->max_load > tmp) pwr_move += sds->busiest->sgp->power * min(sds->busiest_load_per_task, sds->max_load - tmp); /* Amount of load we'd add */ if (sds->max_load * sds->busiest->sgp->power < - sds->busiest_load_per_task * SCHED_POWER_SCALE) - tmp = (sds->max_load * sds->busiest->sgp->power) / - sds->this->sgp->power; - else - tmp = (sds->busiest_load_per_task * SCHED_POWER_SCALE) / - sds->this->sgp->power; + sds->busiest_load_per_task * SCHED_POWER_SCALE) { + tmp = (sds->max_load * sds->busiest->sgp->power); + do_div(tmp, sds->this->sgp->power); + } else { + tmp = (sds->busiest_load_per_task * SCHED_POWER_SCALE); + do_div(tmp, sds->this->sgp->power); + } pwr_move += sds->this->sgp->power * min(sds->this_load_per_task, sds->this_load + tmp); pwr_move /= SCHED_POWER_SCALE; @@ -5018,7 +5027,7 @@ static inline void calculate_imbalance(struct lb_env *env, struct sd_lb_stats *s { u64 max_pull, load_above_capacity = ~0ULL; - sds->busiest_load_per_task /= sds->busiest_nr_running; + do_div(sds->busiest_load_per_task, sds->busiest_nr_running); if (sds->group_imb) { sds->busiest_load_per_task = min(sds->busiest_load_per_task, sds->avg_load); @@ -5043,7 +5052,7 @@ static inline void calculate_imbalance(struct lb_env *env, struct sd_lb_stats *s load_above_capacity *= (SCHED_LOAD_SCALE * SCHED_POWER_SCALE); - load_above_capacity /= sds->busiest->sgp->power; + do_div(load_above_capacity, sds->busiest->sgp->power); } /* @@ -5123,7 +5132,8 @@ find_busiest_group(struct lb_env *env, int *balance) if (!sds.busiest || sds.busiest_nr_running == 0) goto ret; - sds.avg_load = (SCHED_POWER_SCALE * sds.total_load) / sds.total_pwr; + sds.avg_load = (SCHED_POWER_SCALE * sds.total_load); + do_div(sds.avg_load, sds.total_pwr); /* * If the busiest group is imbalanced the below checks don't @@ -5223,7 +5233,8 @@ static struct rq *find_busiest_queue(struct lb_env *env, * the load can be moved away from the cpu that is potentially * running at a lower capacity. */ - wl = (wl * SCHED_POWER_SCALE) / power; + wl = (wl * SCHED_POWER_SCALE); + do_div(wl, power); if (wl > max_load) { max_load = wl;