From patchwork Wed Jan 16 09:43:09 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vincent Guittot X-Patchwork-Id: 155703 Delivered-To: patch@linaro.org Received: by 2002:a02:48:0:0:0:0:0 with SMTP id 69csp443542jaa; Wed, 16 Jan 2019 01:43:27 -0800 (PST) X-Google-Smtp-Source: ALg8bN54UVoiuB+Ek2MtLTT0JDNJgWA8OqOQ2XAUmc2QC0y0vWKs1ZFowdT/meHXfjqD8MfBK8Hc X-Received: by 2002:a62:29c3:: with SMTP id p186mr8953968pfp.117.1547631807746; Wed, 16 Jan 2019 01:43:27 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1547631807; cv=none; d=google.com; s=arc-20160816; b=qxZznmpwrcEDul6q7xymRGzllfr95A+fCCYU9a0py1RahIw+wUD91bn4IwhoJmI6PA r7HP4+iO+D0bfCp2wEiMO2h6uQf5k7zWrVSIIjvw83037BzEEY6QStuNDEQc/xyVGTe3 D0fWT/Q/kJgaXProCA62Wf+/loUhrKE4iaG3EXE3Mtse956S+nbiqfrrfbDb9G2ruS9G nsB7u71QR+qCiNNp5mjgN2mdng7X0JbpjTzK6g1uhrS7SrQrhUB6dlduxfYRUF/D26EC 85B83Ercvd28UxOF6eC7NhMjmBL7H1vbn4f9SIno4U8tid5XTLAseaEsotSaSeWP/jrv 5Fpg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature; bh=U3BNDRrIiDC9gX+eckawILhRIOf/eDTHG1vkELYvYtE=; b=W9BAahzaBqfTr44G1nC1BR7o3BDBlItuCEwZmUBOuM+6BzynGsPiRX3DqtoO05O02x hDnCPFa3wb+kRf+n9bxYwCAlBBPJOKbUPvxR7jENepE48B4dXDOM+3cSYSnZQAhgjwlo kg9tkcunqw0myfmubufKgnxiprKYYfrHnPTfLW6nDiU0VCiR9x6ewEQnCzZMqLoutE8A sNvYxbg9nSQNsy68DJy6I5Yb1BNTluTq14WjPbULce1Y7kuNIXXvqBwEm06EMVtAsJuS kU5GMFnnfsNs5zBF7edxYq9oKHbdVMnIq638P1osZUgbWO8ocBv31dbBEXTLXxVWVZ3d KhuA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="Wc/OT1Rq"; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id g7si5726105plt.212.2019.01.16.01.43.27; Wed, 16 Jan 2019 01:43:27 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="Wc/OT1Rq"; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2391788AbfAPJn0 (ORCPT + 30 others); Wed, 16 Jan 2019 04:43:26 -0500 Received: from mail-wr1-f65.google.com ([209.85.221.65]:33794 "EHLO mail-wr1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2391771AbfAPJnY (ORCPT ); Wed, 16 Jan 2019 04:43:24 -0500 Received: by mail-wr1-f65.google.com with SMTP id j2so6164457wrw.1 for ; Wed, 16 Jan 2019 01:43:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=U3BNDRrIiDC9gX+eckawILhRIOf/eDTHG1vkELYvYtE=; b=Wc/OT1Rq9Z3sW5vUlpQ/umlnkUWXtuD2H+KzVh4GKumNG4/BFGDcD87QvGq8gl4Oa8 WztWfx0ma2sUnte08FjSNBLrHXOnS5uhZuzRzKKlL89Hr4orhwMsPH7s5uGiv9VOFQZ+ Ib+51fAQKrbrxRoH7EGlyAmpSfMO/LrwT9H0Q= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=U3BNDRrIiDC9gX+eckawILhRIOf/eDTHG1vkELYvYtE=; b=bCUt5wM9lyd4FYTu8zCM6NOKS5HIr0PMSQ5kKplvh59DLcev42chw4zAF59ohqKUAw xS9cjyK04kTMXVl3MDomLlZwX7HmOI56yDDyz1Ofwq/xGSDHnfYcQBddSSNIhI4AsUkv vxGegqg6VJ1l9/mWBQLowZqE2Xf9uU62Jw6/72leJbPfQKhSj+3WXjVSadknbCHR1Xry eD5V/jnjHY+fh7g3XmQ7mp6B3A/m417KoxxVSuIoZNM2D67yp4uKaK07rc2ZgwQ39CjM ZK6Ow2PzEGVHt84iDFZRfJVQwnztfRor0+fBgqrWsJmX0j790tqQilYv+HQ89USV+zeX sfcw== X-Gm-Message-State: AJcUukdzy14neBJz4JHZGTJQadonRlUWygP03dHcVjwQhez1QV7bwgee n7oDgV6kGk/m00L+fF0ZR1VELA== X-Received: by 2002:adf:8b4d:: with SMTP id v13mr6490941wra.282.1547631802479; Wed, 16 Jan 2019 01:43:22 -0800 (PST) Received: from localhost.localdomain ([2a01:e0a:f:6020:596d:a8c4:e914:fdde]) by smtp.gmail.com with ESMTPSA id k19sm115996304wre.5.2019.01.16.01.43.21 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 16 Jan 2019 01:43:21 -0800 (PST) From: Vincent Guittot To: peterz@infradead.org, mingo@kernel.org, linux-kernel@vger.kernel.org Cc: rjw@rjwysocki.net, dietmar.eggemann@arm.com, Morten.Rasmussen@arm.com, patrick.bellasi@arm.com, pjt@google.com, bsegall@google.com, thara.gopinath@linaro.org, pkondeti@codeaurora.org, quentin.perret@arm.com, srinivas.pandruvada@linux.intel.com, Vincent Guittot Subject: [PATCH v8 1/3] sched/fair: move rq_of helper function Date: Wed, 16 Jan 2019 10:43:09 +0100 Message-Id: <1547631791-16018-2-git-send-email-vincent.guittot@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1547631791-16018-1-git-send-email-vincent.guittot@linaro.org> References: <1547631791-16018-1-git-send-email-vincent.guittot@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Move rq_of() helper function so it can be used in pelt.c Signed-off-by: Vincent Guittot --- kernel/sched/fair.c | 13 ------------- kernel/sched/sched.h | 16 ++++++++++++++++ 2 files changed, 16 insertions(+), 13 deletions(-) -- 2.7.4 diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index ca46964..63b9151 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -248,13 +248,6 @@ const struct sched_class fair_sched_class; */ #ifdef CONFIG_FAIR_GROUP_SCHED - -/* cpu runqueue to which this cfs_rq is attached */ -static inline struct rq *rq_of(struct cfs_rq *cfs_rq) -{ - return cfs_rq->rq; -} - static inline struct task_struct *task_of(struct sched_entity *se) { SCHED_WARN_ON(!entity_is_task(se)); @@ -411,12 +404,6 @@ static inline struct task_struct *task_of(struct sched_entity *se) return container_of(se, struct task_struct, se); } -static inline struct rq *rq_of(struct cfs_rq *cfs_rq) -{ - return container_of(cfs_rq, struct rq, cfs); -} - - #define for_each_sched_entity(se) \ for (; se; se = NULL) diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 0ba0892..fd1bad2 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -951,6 +951,22 @@ struct rq { #endif }; +#ifdef CONFIG_FAIR_GROUP_SCHED + +/* cpu runqueue to which this cfs_rq is attached */ +static inline struct rq *rq_of(struct cfs_rq *cfs_rq) +{ + return cfs_rq->rq; +} + +#else /* !CONFIG_FAIR_GROUP_SCHED */ + +static inline struct rq *rq_of(struct cfs_rq *cfs_rq) +{ + return container_of(cfs_rq, struct rq, cfs); +} +#endif + static inline int cpu_of(struct rq *rq) { #ifdef CONFIG_SMP From patchwork Wed Jan 16 09:43:10 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vincent Guittot X-Patchwork-Id: 155705 Delivered-To: patch@linaro.org Received: by 2002:a02:48:0:0:0:0:0 with SMTP id 69csp443663jaa; Wed, 16 Jan 2019 01:43:37 -0800 (PST) X-Google-Smtp-Source: ALg8bN4+btNkjmH2yyafMX8ksYKznqogVdjdHVotS0Bes7y8ekzQ1RWIO7US4TAwohs2pt0+FNed X-Received: by 2002:a17:902:8d8e:: with SMTP id v14mr8847001plo.133.1547631817455; Wed, 16 Jan 2019 01:43:37 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1547631817; cv=none; d=google.com; s=arc-20160816; b=wPuxKSJy5ksNJMDt2VpQ8p+WyDEvRdspAwfKvwt91QyQ1NLZqtxdzvdre4nDYsDVVr jHF8klEdEn7lGnzbUtFMHkEw/zhkmErFxOovUWuGA8uKujOB1xKn/H65Lxzw/yM/769T wPmvh+LWaal++x7ARUZSMly6wpT9a0Nvq163UbG83QPOo6CJj+H1S9JDyvx85GgMqOmU vrhPtOWBUNWx20qeO8IlThQNU+TooxEdg9nFzCdHHC6P2WrAS+h5VNPnzh0cqP9VqqOq 8nkK++qBuvWRlOk8BAjvnDJB27NMHIOrrffu1nGD4htUiclY2/lZaZBgDBgXYER4vV70 9+mg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature; bh=lzerroMR+8QbJDnlrCcwidRAZqofWbx0gXAFW6Zcjfo=; b=Q4RMZ04M3TFsC1Aj9Ceop7f2WgfRAkMuE3SbgL/YT8FzS/AY06B6t/YRokiQto3k7h k15XHwB+lYubZHfa3lscwDNVyjIWX4uEFvdTK30O6ZkQmTqTTj42p2ZA6qorau/Ek/W7 XbRZnh3IyE5n/7F2lGjXyRtL+E7Jdkxk52tImoOqwMkDEszvP7fam4fxohfKHSYirbVC iTMWmP7eClEC7KzWCKUe0wiYKIPZIAQm4a0Goh0+cqxYFFB1gtm7J+TAQuBzsI1oLuiZ jjdmUMKVsddYfFYfOrtl0Eir/j94mocoKHK7+6bHMVoLeNFNWRWVPGUEDMPjx3jH8ehL 9xFg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=ghn0UODN; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id n18si5835718pfj.30.2019.01.16.01.43.36; Wed, 16 Jan 2019 01:43:37 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=ghn0UODN; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2391807AbfAPJnf (ORCPT + 30 others); Wed, 16 Jan 2019 04:43:35 -0500 Received: from mail-wm1-f66.google.com ([209.85.128.66]:37592 "EHLO mail-wm1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731835AbfAPJnb (ORCPT ); Wed, 16 Jan 2019 04:43:31 -0500 Received: by mail-wm1-f66.google.com with SMTP id g67so1241925wmd.2 for ; Wed, 16 Jan 2019 01:43:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=lzerroMR+8QbJDnlrCcwidRAZqofWbx0gXAFW6Zcjfo=; b=ghn0UODNbH/4qdVDIn6r+28l+iTctMtsfS7YumQY6eeAPjKI0LVsRHMl9FBcN29Jhg QDqnCj4SQP6Iuu/gYIzGuIA1CM2kpqsA5cO4FqR+RAhjTfdLk5ZqdneREj3zlfjdti3Z 96qBryY07sl3FnX8BJYxcVebEcPt1OO/9Fxv4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=lzerroMR+8QbJDnlrCcwidRAZqofWbx0gXAFW6Zcjfo=; b=htJv7Pr7ObHZI1FuuvHIm2HyWWaGKbNv6HuC6tqnxob7EOuWDliv57sXEdiuJ+B0Qc kTapr7cWDGZuUpR1CrfIbtPsmlKkoX3u+WFIkga120Y6BlN3thENz4kcTypzmOsKIkd7 ZBBfx9kj6vtlklMUqQVTVsWQVaNUsWbkqhTXAAkCJsIAdveFGPnvcXHwgECXANM7vS2l Ce4/dq2yz+1ky6RaymRmugdbIwaE3Rh1EJxTF597WN98hE8uCV8DRVdpMj8RgT6s1Auf 1/WUNGLlUoaT19YJUZtexyrpXifRbyo13f6DngimdK9Ah4WzuYjLXglb8+LLVvKimmrn gT6A== X-Gm-Message-State: AJcUukcGEUSsMn6YF/u7vDpyTk9ZLfq5vvb+Tf0dqub6MgiFtF1HTvEQ EbvsuAjj3d5ObTe7f+Zj6B1iXg== X-Received: by 2002:a1c:1b4f:: with SMTP id b76mr6792233wmb.147.1547631803844; Wed, 16 Jan 2019 01:43:23 -0800 (PST) Received: from localhost.localdomain ([2a01:e0a:f:6020:596d:a8c4:e914:fdde]) by smtp.gmail.com with ESMTPSA id k19sm115996304wre.5.2019.01.16.01.43.22 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 16 Jan 2019 01:43:22 -0800 (PST) From: Vincent Guittot To: peterz@infradead.org, mingo@kernel.org, linux-kernel@vger.kernel.org Cc: rjw@rjwysocki.net, dietmar.eggemann@arm.com, Morten.Rasmussen@arm.com, patrick.bellasi@arm.com, pjt@google.com, bsegall@google.com, thara.gopinath@linaro.org, pkondeti@codeaurora.org, quentin.perret@arm.com, srinivas.pandruvada@linux.intel.com, Vincent Guittot Subject: [PATCH v8 2/3] sched/fair: update scale invariance of PELT Date: Wed, 16 Jan 2019 10:43:10 +0100 Message-Id: <1547631791-16018-3-git-send-email-vincent.guittot@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1547631791-16018-1-git-send-email-vincent.guittot@linaro.org> References: <1547631791-16018-1-git-send-email-vincent.guittot@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The current implementation of load tracking invariance scales the contribution with current frequency and uarch performance (only for utilization) of the CPU. One main result of this formula is that the figures are capped by current capacity of CPU. Another one is that the load_avg is not invariant because not scaled with uarch. The util_avg of a periodic task that runs r time slots every p time slots varies in the range : U * (1-y^r)/(1-y^p) * y^i < Utilization < U * (1-y^r)/(1-y^p) with U is the max util_avg value = SCHED_CAPACITY_SCALE At a lower capacity, the range becomes: U * C * (1-y^r')/(1-y^p) * y^i' < Utilization < U * C * (1-y^r')/(1-y^p) with C reflecting the compute capacity ratio between current capacity and max capacity. so C tries to compensate changes in (1-y^r') but it can't be accurate. Instead of scaling the contribution value of PELT algo, we should scale the running time. The PELT signal aims to track the amount of computation of tasks and/or rq so it seems more correct to scale the running time to reflect the effective amount of computation done since the last update. In order to be fully invariant, we need to apply the same amount of running time and idle time whatever the current capacity. Because running at lower capacity implies that the task will run longer, we have to ensure that the same amount of idle time will be applied when system becomes idle and no idle time has been "stolen". But reaching the maximum utilization value (SCHED_CAPACITY_SCALE) means that the task is seen as an always-running task whatever the capacity of the CPU (even at max compute capacity). In this case, we can discard this "stolen" idle times which becomes meaningless. In order to achieve this time scaling, a new clock_pelt is created per rq. The increase of this clock scales with current capacity when something is running on rq and synchronizes with clock_task when rq is idle. With this mechanism, we ensure the same running and idle time whatever the current capacity. This also enables to simplify the pelt algorithm by removing all references of uarch and frequency and applying the same contribution to utilization and loads. Furthermore, the scaling is done only once per update of clock (update_rq_clock_task()) instead of during each update of sched_entities and cfs/rt/dl_rq of the rq like the current implementation. This is interesting when cgroup are involved as shown in the results below: On a hikey (octo Arm64 platform). Performance cpufreq governor and only shallowest c-state to remove variance generated by those power features so we only track the impact of pelt algo. each test runs 16 times ./perf bench sched pipe (higher is better) kernel tip/sched/core + patch ops/seconds ops/seconds diff cgroup root 59652(+/- 0.18%) 59876(+/- 0.24%) +0.38% level1 55608(+/- 0.27%) 55923(+/- 0.24%) +0.57% level2 52115(+/- 0.29%) 52564(+/- 0.22%) +0.86% hackbench -l 1000 (lower is better) kernel tip/sched/core + patch duration(sec) duration(sec) diff cgroup root 4.453(+/- 2.37%) 4.383(+/- 2.88%) -1.57% level1 4.859(+/- 8.50%) 4.830(+/- 7.07%) -0.60% level2 5.063(+/- 9.83%) 4.928(+/- 9.66%) -2.66% Then, the responsiveness of PELT is improved when CPU is not running at max capacity with this new algorithm. I have put below some examples of duration to reach some typical load values according to the capacity of the CPU with current implementation and with this patch. These values has been computed based on the geometric series and the half period value: Util (%) max capacity half capacity(mainline) half capacity(w/ patch) 972 (95%) 138ms not reachable 276ms 486 (47.5%) 30ms 138ms 60ms 256 (25%) 13ms 32ms 26ms On my hikey (octo Arm64 platform) with schedutil governor, the time to reach max OPP when starting from a null utilization, decreases from 223ms with current scale invariance down to 121ms with the new algorithm. Signed-off-by: Vincent Guittot --- include/linux/sched.h | 23 +++------- kernel/sched/core.c | 1 + kernel/sched/deadline.c | 6 +-- kernel/sched/fair.c | 45 +++++++++++--------- kernel/sched/pelt.c | 45 +++++++++++--------- kernel/sched/pelt.h | 111 ++++++++++++++++++++++++++++++++++++++++++++++-- kernel/sched/rt.c | 6 +-- kernel/sched/sched.h | 5 ++- 8 files changed, 174 insertions(+), 68 deletions(-) -- 2.7.4 diff --git a/include/linux/sched.h b/include/linux/sched.h index b8c7ba0..fbea56f 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -356,12 +356,6 @@ struct util_est { * For cfs_rq, it is the aggregated load_avg of all runnable and * blocked sched_entities. * - * load_avg may also take frequency scaling into account: - * - * load_avg = runnable% * scale_load_down(load) * freq% - * - * where freq% is the CPU frequency normalized to the highest frequency. - * * [util_avg definition] * * util_avg = running% * SCHED_CAPACITY_SCALE @@ -370,17 +364,14 @@ struct util_est { * a CPU. For cfs_rq, it is the aggregated util_avg of all runnable * and blocked sched_entities. * - * util_avg may also factor frequency scaling and CPU capacity scaling: - * - * util_avg = running% * SCHED_CAPACITY_SCALE * freq% * capacity% - * - * where freq% is the same as above, and capacity% is the CPU capacity - * normalized to the greatest capacity (due to uarch differences, etc). + * load_avg and util_avg don't direcly factor frequency scaling and CPU + * capacity scaling. The scaling is done through the rq_clock_pelt that + * is used for computing those signals (see update_rq_clock_pelt()) * - * N.B., the above ratios (runnable%, running%, freq%, and capacity%) - * themselves are in the range of [0, 1]. To do fixed point arithmetics, - * we therefore scale them to as large a range as necessary. This is for - * example reflected by util_avg's SCHED_CAPACITY_SCALE. + * N.B., the above ratios (runnable% and running%) themselves are in the + * range of [0, 1]. To do fixed point arithmetics, we therefore scale them + * to as large a range as necessary. This is for example reflected by + * util_avg's SCHED_CAPACITY_SCALE. * * [Overflow issue] * diff --git a/kernel/sched/core.c b/kernel/sched/core.c index e4ca15d..c597dda 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -180,6 +180,7 @@ static void update_rq_clock_task(struct rq *rq, s64 delta) if ((irq_delta + steal) && sched_feat(NONTASK_CAPACITY)) update_irq_load_avg(rq, irq_delta + steal); #endif + update_rq_clock_pelt(rq, delta); } void update_rq_clock(struct rq *rq) diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c index fb8b7b5..6a73e41 100644 --- a/kernel/sched/deadline.c +++ b/kernel/sched/deadline.c @@ -1767,7 +1767,7 @@ pick_next_task_dl(struct rq *rq, struct task_struct *prev, struct rq_flags *rf) deadline_queue_push_tasks(rq); if (rq->curr->sched_class != &dl_sched_class) - update_dl_rq_load_avg(rq_clock_task(rq), rq, 0); + update_dl_rq_load_avg(rq_clock_pelt(rq), rq, 0); return p; } @@ -1776,7 +1776,7 @@ static void put_prev_task_dl(struct rq *rq, struct task_struct *p) { update_curr_dl(rq); - update_dl_rq_load_avg(rq_clock_task(rq), rq, 1); + update_dl_rq_load_avg(rq_clock_pelt(rq), rq, 1); if (on_dl_rq(&p->dl) && p->nr_cpus_allowed > 1) enqueue_pushable_dl_task(rq, p); } @@ -1793,7 +1793,7 @@ static void task_tick_dl(struct rq *rq, struct task_struct *p, int queued) { update_curr_dl(rq); - update_dl_rq_load_avg(rq_clock_task(rq), rq, 1); + update_dl_rq_load_avg(rq_clock_pelt(rq), rq, 1); /* * Even when we have runtime, update_curr_dl() might have resulted in us * not being the leftmost task anymore. In that case NEED_RESCHED will diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 63b9151..9332863 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -674,9 +674,8 @@ 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_SMP #include "pelt.h" -#include "sched-pelt.h" +#ifdef CONFIG_SMP static int select_idle_sibling(struct task_struct *p, int prev_cpu, int cpu); static unsigned long task_h_load(struct task_struct *p); @@ -764,7 +763,7 @@ void post_init_entity_util_avg(struct sched_entity *se) * such that the next switched_to_fair() has the * expected state. */ - se->avg.last_update_time = cfs_rq_clock_task(cfs_rq); + se->avg.last_update_time = cfs_rq_clock_pelt(cfs_rq); return; } } @@ -3110,7 +3109,7 @@ void set_task_rq_fair(struct sched_entity *se, p_last_update_time = prev->avg.last_update_time; n_last_update_time = next->avg.last_update_time; #endif - __update_load_avg_blocked_se(p_last_update_time, cpu_of(rq_of(prev)), se); + __update_load_avg_blocked_se(p_last_update_time, se); se->avg.last_update_time = n_last_update_time; } @@ -3245,11 +3244,11 @@ update_tg_cfs_runnable(struct cfs_rq *cfs_rq, struct sched_entity *se, struct cf /* * runnable_sum can't be lower than running_sum - * As running sum is scale with CPU capacity wehreas the runnable sum - * is not we rescale running_sum 1st + * Rescale running sum to be in the same range as runnable sum + * running_sum is in [0 : LOAD_AVG_MAX << SCHED_CAPACITY_SHIFT] + * runnable_sum is in [0 : LOAD_AVG_MAX] */ - running_sum = se->avg.util_sum / - arch_scale_cpu_capacity(NULL, cpu_of(rq_of(cfs_rq))); + running_sum = se->avg.util_sum >> SCHED_CAPACITY_SHIFT; runnable_sum = max(runnable_sum, running_sum); load_sum = (s64)se_weight(se) * runnable_sum; @@ -3352,7 +3351,7 @@ static inline void add_tg_cfs_propagate(struct cfs_rq *cfs_rq, long runnable_sum /** * update_cfs_rq_load_avg - update the cfs_rq's load/util averages - * @now: current time, as per cfs_rq_clock_task() + * @now: current time, as per cfs_rq_clock_pelt() * @cfs_rq: cfs_rq to update * * The cfs_rq avg is the direct sum of all its entities (blocked and runnable) @@ -3397,7 +3396,7 @@ update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq) decayed = 1; } - decayed |= __update_load_avg_cfs_rq(now, cpu_of(rq_of(cfs_rq)), cfs_rq); + decayed |= __update_load_avg_cfs_rq(now, cfs_rq); #ifndef CONFIG_64BIT smp_wmb(); @@ -3487,9 +3486,7 @@ static void detach_entity_load_avg(struct cfs_rq *cfs_rq, struct sched_entity *s /* Update task and its cfs_rq load average */ static inline void update_load_avg(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags) { - u64 now = cfs_rq_clock_task(cfs_rq); - struct rq *rq = rq_of(cfs_rq); - int cpu = cpu_of(rq); + u64 now = cfs_rq_clock_pelt(cfs_rq); int decayed; /* @@ -3497,7 +3494,7 @@ static inline void update_load_avg(struct cfs_rq *cfs_rq, struct sched_entity *s * track group sched_entity load average for task_h_load calc in migration */ if (se->avg.last_update_time && !(flags & SKIP_AGE_LOAD)) - __update_load_avg_se(now, cpu, cfs_rq, se); + __update_load_avg_se(now, cfs_rq, se); decayed = update_cfs_rq_load_avg(now, cfs_rq); decayed |= propagate_entity_load_avg(se); @@ -3549,7 +3546,7 @@ void sync_entity_load_avg(struct sched_entity *se) u64 last_update_time; last_update_time = cfs_rq_last_update_time(cfs_rq); - __update_load_avg_blocked_se(last_update_time, cpu_of(rq_of(cfs_rq)), se); + __update_load_avg_blocked_se(last_update_time, se); } /* @@ -7014,6 +7011,12 @@ done: __maybe_unused; if (new_tasks > 0) goto again; + /* + * rq is about to be idle, check if we need to update the + * lost_idle_time of clock_pelt + */ + update_idle_rq_clock_pelt(rq); + return NULL; } @@ -7673,7 +7676,7 @@ static void update_blocked_averages(int cpu) if (throttled_hierarchy(cfs_rq)) continue; - if (update_cfs_rq_load_avg(cfs_rq_clock_task(cfs_rq), cfs_rq)) + if (update_cfs_rq_load_avg(cfs_rq_clock_pelt(cfs_rq), cfs_rq)) update_tg_load_avg(cfs_rq, 0); /* Propagate pending load changes to the parent, if any: */ @@ -7694,8 +7697,8 @@ static void update_blocked_averages(int cpu) } curr_class = rq->curr->sched_class; - update_rt_rq_load_avg(rq_clock_task(rq), rq, curr_class == &rt_sched_class); - update_dl_rq_load_avg(rq_clock_task(rq), rq, curr_class == &dl_sched_class); + update_rt_rq_load_avg(rq_clock_pelt(rq), rq, curr_class == &rt_sched_class); + update_dl_rq_load_avg(rq_clock_pelt(rq), rq, curr_class == &dl_sched_class); update_irq_load_avg(rq, 0); /* Don't need periodic decay once load/util_avg are null */ if (others_have_blocked(rq)) @@ -7765,11 +7768,11 @@ static inline void update_blocked_averages(int cpu) rq_lock_irqsave(rq, &rf); update_rq_clock(rq); - update_cfs_rq_load_avg(cfs_rq_clock_task(cfs_rq), cfs_rq); + update_cfs_rq_load_avg(cfs_rq_clock_pelt(cfs_rq), cfs_rq); curr_class = rq->curr->sched_class; - update_rt_rq_load_avg(rq_clock_task(rq), rq, curr_class == &rt_sched_class); - update_dl_rq_load_avg(rq_clock_task(rq), rq, curr_class == &dl_sched_class); + update_rt_rq_load_avg(rq_clock_pelt(rq), rq, curr_class == &rt_sched_class); + update_dl_rq_load_avg(rq_clock_pelt(rq), rq, curr_class == &dl_sched_class); update_irq_load_avg(rq, 0); #ifdef CONFIG_NO_HZ_COMMON rq->last_blocked_load_update_tick = jiffies; diff --git a/kernel/sched/pelt.c b/kernel/sched/pelt.c index 90fb5bc..befce29 100644 --- a/kernel/sched/pelt.c +++ b/kernel/sched/pelt.c @@ -26,7 +26,6 @@ #include #include "sched.h" -#include "sched-pelt.h" #include "pelt.h" /* @@ -106,16 +105,12 @@ static u32 __accumulate_pelt_segments(u64 periods, u32 d1, u32 d3) * n=1 */ static __always_inline u32 -accumulate_sum(u64 delta, int cpu, struct sched_avg *sa, +accumulate_sum(u64 delta, struct sched_avg *sa, unsigned long load, unsigned long runnable, int running) { - unsigned long scale_freq, scale_cpu; u32 contrib = (u32)delta; /* p == 0 -> delta < 1024 */ u64 periods; - scale_freq = arch_scale_freq_capacity(cpu); - scale_cpu = arch_scale_cpu_capacity(NULL, cpu); - delta += sa->period_contrib; periods = delta / 1024; /* A period is 1024us (~1ms) */ @@ -137,13 +132,12 @@ accumulate_sum(u64 delta, int cpu, struct sched_avg *sa, } sa->period_contrib = delta; - contrib = cap_scale(contrib, scale_freq); if (load) sa->load_sum += load * contrib; if (runnable) sa->runnable_load_sum += runnable * contrib; if (running) - sa->util_sum += contrib * scale_cpu; + sa->util_sum += contrib << SCHED_CAPACITY_SHIFT; return periods; } @@ -177,7 +171,7 @@ accumulate_sum(u64 delta, int cpu, struct sched_avg *sa, * = u_0 + u_1*y + u_2*y^2 + ... [re-labeling u_i --> u_{i+1}] */ static __always_inline int -___update_load_sum(u64 now, int cpu, struct sched_avg *sa, +___update_load_sum(u64 now, struct sched_avg *sa, unsigned long load, unsigned long runnable, int running) { u64 delta; @@ -221,7 +215,7 @@ ___update_load_sum(u64 now, int cpu, struct sched_avg *sa, * Step 1: accumulate *_sum since last_update_time. If we haven't * crossed period boundaries, finish. */ - if (!accumulate_sum(delta, cpu, sa, load, runnable, running)) + if (!accumulate_sum(delta, sa, load, runnable, running)) return 0; return 1; @@ -267,9 +261,9 @@ ___update_load_avg(struct sched_avg *sa, unsigned long load, unsigned long runna * runnable_load_avg = \Sum se->avg.runable_load_avg */ -int __update_load_avg_blocked_se(u64 now, int cpu, struct sched_entity *se) +int __update_load_avg_blocked_se(u64 now, struct sched_entity *se) { - if (___update_load_sum(now, cpu, &se->avg, 0, 0, 0)) { + if (___update_load_sum(now, &se->avg, 0, 0, 0)) { ___update_load_avg(&se->avg, se_weight(se), se_runnable(se)); return 1; } @@ -277,9 +271,9 @@ int __update_load_avg_blocked_se(u64 now, int cpu, struct sched_entity *se) return 0; } -int __update_load_avg_se(u64 now, int cpu, struct cfs_rq *cfs_rq, struct sched_entity *se) +int __update_load_avg_se(u64 now, struct cfs_rq *cfs_rq, struct sched_entity *se) { - if (___update_load_sum(now, cpu, &se->avg, !!se->on_rq, !!se->on_rq, + if (___update_load_sum(now, &se->avg, !!se->on_rq, !!se->on_rq, cfs_rq->curr == se)) { ___update_load_avg(&se->avg, se_weight(se), se_runnable(se)); @@ -290,9 +284,9 @@ int __update_load_avg_se(u64 now, int cpu, struct cfs_rq *cfs_rq, struct sched_e return 0; } -int __update_load_avg_cfs_rq(u64 now, int cpu, struct cfs_rq *cfs_rq) +int __update_load_avg_cfs_rq(u64 now, struct cfs_rq *cfs_rq) { - if (___update_load_sum(now, cpu, &cfs_rq->avg, + if (___update_load_sum(now, &cfs_rq->avg, scale_load_down(cfs_rq->load.weight), scale_load_down(cfs_rq->runnable_weight), cfs_rq->curr != NULL)) { @@ -317,7 +311,7 @@ int __update_load_avg_cfs_rq(u64 now, int cpu, struct cfs_rq *cfs_rq) int update_rt_rq_load_avg(u64 now, struct rq *rq, int running) { - if (___update_load_sum(now, rq->cpu, &rq->avg_rt, + if (___update_load_sum(now, &rq->avg_rt, running, running, running)) { @@ -340,7 +334,7 @@ int update_rt_rq_load_avg(u64 now, struct rq *rq, int running) int update_dl_rq_load_avg(u64 now, struct rq *rq, int running) { - if (___update_load_sum(now, rq->cpu, &rq->avg_dl, + if (___update_load_sum(now, &rq->avg_dl, running, running, running)) { @@ -365,22 +359,31 @@ int update_dl_rq_load_avg(u64 now, struct rq *rq, int running) int update_irq_load_avg(struct rq *rq, u64 running) { int ret = 0; + + /* + * We can't use clock_pelt because irq time is not accounted in + * clock_task. Instead we directly scale the running time to + * reflect the real amount of computation + */ + running = cap_scale(running, arch_scale_freq_capacity(cpu_of(rq))); + running = cap_scale(running, arch_scale_cpu_capacity(NULL, cpu_of(rq))); + /* * We know the time that has been used by interrupt since last update * but we don't when. Let be pessimistic and assume that interrupt has * happened just before the update. This is not so far from reality * because interrupt will most probably wake up task and trig an update - * of rq clock during which the metric si updated. + * of rq clock during which the metric is updated. * We start to decay with normal context time and then we add the * interrupt context time. * We can safely remove running from rq->clock because * rq->clock += delta with delta >= running */ - ret = ___update_load_sum(rq->clock - running, rq->cpu, &rq->avg_irq, + ret = ___update_load_sum(rq->clock - running, &rq->avg_irq, 0, 0, 0); - ret += ___update_load_sum(rq->clock, rq->cpu, &rq->avg_irq, + ret += ___update_load_sum(rq->clock, &rq->avg_irq, 1, 1, 1); diff --git a/kernel/sched/pelt.h b/kernel/sched/pelt.h index 7e56b48..ae269ba 100644 --- a/kernel/sched/pelt.h +++ b/kernel/sched/pelt.h @@ -1,8 +1,9 @@ #ifdef CONFIG_SMP +#include "sched-pelt.h" -int __update_load_avg_blocked_se(u64 now, int cpu, struct sched_entity *se); -int __update_load_avg_se(u64 now, int cpu, struct cfs_rq *cfs_rq, struct sched_entity *se); -int __update_load_avg_cfs_rq(u64 now, int cpu, struct cfs_rq *cfs_rq); +int __update_load_avg_blocked_se(u64 now, struct sched_entity *se); +int __update_load_avg_se(u64 now, struct cfs_rq *cfs_rq, struct sched_entity *se); +int __update_load_avg_cfs_rq(u64 now, struct cfs_rq *cfs_rq); int update_rt_rq_load_avg(u64 now, struct rq *rq, int running); int update_dl_rq_load_avg(u64 now, struct rq *rq, int running); @@ -42,6 +43,98 @@ static inline void cfs_se_util_change(struct sched_avg *avg) WRITE_ONCE(avg->util_est.enqueued, enqueued); } +/* + * The clock_pelt scales the time to reflect the effective amount of + * computation done during the running delta time but then sync back to + * clock_task when rq is idle. + * + * + * absolute time | 1| 2| 3| 4| 5| 6| 7| 8| 9|10|11|12|13|14|15|16 + * @ max capacity ------******---------------******--------------- + * @ half capacity ------************---------************--------- + * clock pelt | 1| 2| 3| 4| 7| 8| 9| 10| 11|14|15|16 + * + */ +static inline void update_rq_clock_pelt(struct rq *rq, s64 delta) +{ + if (unlikely(is_idle_task(rq->curr))) { + /* The rq is idle, we can sync to clock_task */ + rq->clock_pelt = rq_clock_task(rq); + return; + } + + /* + * When a rq runs at a lower compute capacity, it will need + * more time to do the same amount of work than at max + * capacity. In order to be invariant, we scale the delta to + * reflect how much work has been really done. + * Running longer results in stealing idle time that will + * disturb the load signal compared to max capacity. This + * stolen idle time will be automatically reflected when the + * rq will be idle and the clock will be synced with + * rq_clock_task. + */ + + /* + * Scale the elapsed time to reflect the real amount of + * computation + */ + delta = cap_scale(delta, arch_scale_cpu_capacity(NULL, cpu_of(rq))); + delta = cap_scale(delta, arch_scale_freq_capacity(cpu_of(rq))); + + rq->clock_pelt += delta; +} + +/* + * When rq becomes idle, we have to check if it has lost idle time + * because it was fully busy. A rq is fully used when the /Sum util_sum + * is greater or equal to: + * (LOAD_AVG_MAX - 1024 + rq->cfs.avg.period_contrib) << SCHED_CAPACITY_SHIFT; + * For optimization and computing rounding purpose, we don't take into account + * the position in the current window (period_contrib) and we use the higher + * bound of util_sum to decide. + */ +static inline void update_idle_rq_clock_pelt(struct rq *rq) +{ + u32 divider = ((LOAD_AVG_MAX - 1024) << SCHED_CAPACITY_SHIFT) - LOAD_AVG_MAX; + u32 util_sum = rq->cfs.avg.util_sum; + util_sum += rq->avg_rt.util_sum; + util_sum += rq->avg_dl.util_sum; + + /* + * Reflecting stolen time makes sense only if the idle + * phase would be present at max capacity. As soon as the + * utilization of a rq has reached the maximum value, it is + * considered as an always runnig rq without idle time to + * steal. This potential idle time is considered as lost in + * this case. We keep track of this lost idle time compare to + * rq's clock_task. + */ + if (util_sum >= divider) + rq->lost_idle_time += rq_clock_task(rq) - rq->clock_pelt; +} + +static inline u64 rq_clock_pelt(struct rq *rq) +{ + return rq->clock_pelt - rq->lost_idle_time; +} + +#ifdef CONFIG_CFS_BANDWIDTH +/* rq->task_clock normalized against any time this cfs_rq has spent throttled */ +static inline u64 cfs_rq_clock_pelt(struct cfs_rq *cfs_rq) +{ + if (unlikely(cfs_rq->throttle_count)) + return cfs_rq->throttled_clock_task - cfs_rq->throttled_clock_task_time; + + return rq_clock_pelt(rq_of(cfs_rq)) - cfs_rq->throttled_clock_task_time; +} +#else +static inline u64 cfs_rq_clock_pelt(struct cfs_rq *cfs_rq) +{ + return rq_clock_pelt(rq_of(cfs_rq)); +} +#endif + #else static inline int @@ -67,6 +160,18 @@ update_irq_load_avg(struct rq *rq, u64 running) { return 0; } + +static inline u64 rq_clock_pelt(struct rq *rq) +{ + return rq_clock_task(rq); +} + +static inline void +update_rq_clock_pelt(struct rq *rq, s64 delta) { } + +static inline void +update_idle_rq_clock_pelt(struct rq *rq) { } + #endif diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c index e4f398a..90fa23d 100644 --- a/kernel/sched/rt.c +++ b/kernel/sched/rt.c @@ -1587,7 +1587,7 @@ pick_next_task_rt(struct rq *rq, struct task_struct *prev, struct rq_flags *rf) * rt task */ if (rq->curr->sched_class != &rt_sched_class) - update_rt_rq_load_avg(rq_clock_task(rq), rq, 0); + update_rt_rq_load_avg(rq_clock_pelt(rq), rq, 0); return p; } @@ -1596,7 +1596,7 @@ static void put_prev_task_rt(struct rq *rq, struct task_struct *p) { update_curr_rt(rq); - update_rt_rq_load_avg(rq_clock_task(rq), rq, 1); + update_rt_rq_load_avg(rq_clock_pelt(rq), rq, 1); /* * The previous task needs to be made eligible for pushing @@ -2325,7 +2325,7 @@ static void task_tick_rt(struct rq *rq, struct task_struct *p, int queued) struct sched_rt_entity *rt_se = &p->rt; update_curr_rt(rq); - update_rt_rq_load_avg(rq_clock_task(rq), rq, 1); + update_rt_rq_load_avg(rq_clock_pelt(rq), rq, 1); watchdog(rq, p); diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index fd1bad2..4c506ea 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -861,7 +861,10 @@ struct rq { unsigned int clock_update_flags; u64 clock; - u64 clock_task; + /* Ensure that all clocks are in the same cache line */ + u64 clock_task ____cacheline_aligned; + u64 clock_pelt; + unsigned long lost_idle_time; atomic_t nr_iowait; From patchwork Wed Jan 16 09:43:11 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vincent Guittot X-Patchwork-Id: 155704 Delivered-To: patch@linaro.org Received: by 2002:a02:48:0:0:0:0:0 with SMTP id 69csp443580jaa; Wed, 16 Jan 2019 01:43:31 -0800 (PST) X-Google-Smtp-Source: ALg8bN5wl4JZcT+L7vRNxNdLB8kasufiCCasQymff4KOYF9Qgrb26SZ1LbrmTbRzPQlD2c/zSrlx X-Received: by 2002:a17:902:96a:: with SMTP id 97mr8677839plm.45.1547631811138; Wed, 16 Jan 2019 01:43:31 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1547631811; cv=none; d=google.com; s=arc-20160816; b=PWkIzADBqlhkGEP8ACj8iy/Cyg1KjWg7FgnkoVpzoAnI/ilZGVOMCcvmYXLFVIyRJu d7qiAs5SFmuIniqdFxMi3DC2fPXYInhCGMsRQn9O+ZWJBD0jDSdWWK+GYStTKuD26ev9 6nADdXCEXvP4VyJNPCcA5yluE4CZG5zKNZFuSDsMKC5Oh/kQr2yorzjhq4XQxtLIf5AH UKdULSSqmS6Fap10cOCBFDrZAMUml7YE8lSIeartJvMFkT3Vr+94XakWECvhATW8ZMJB jgOebhlKy02NYD5///oxGBziAn4YlhrS+ZKhZekKVQr1lGXWNkyBdQLe59OWm+fwQotA NRUg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature; bh=IF8O5IB660i5uISr2+XWnKBaqatYQfBFmBwhpEAXDiM=; b=szLrE6XEdBPtHXzSi20kKnbDWml2wVEv+ECpewtwUpDaJUwO6Flw/psUWiNvgWjF1M GM9lU9fQr2yQBi3ZG3KmS9+IlJFmH/h6OvKTex3hs/WodyrsVfNmup/5SpyjhCUA/DL2 yGMZ1kGJdRVirp6mU83CvOxVdkZAqHUTmK7TFbt6YP5vmzTfY4jP5XGpyRbLcQ9QZ7kJ 2mnQTmRlTwqjYQZuKFnRjbD0NO3IDYLM/p6NKJPZYW8iu0kui2+9iB2o//jyDzIA/b0i oX9B5Isq8AIHG0HoFl/b3vIwQ0kqrWsbbBar7X+NsoktqXmijsHjxTo15nCt7DEz6GNl pIRg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=B+w4gOfS; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id c64si5640523pfg.239.2019.01.16.01.43.30; Wed, 16 Jan 2019 01:43:31 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=B+w4gOfS; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2391795AbfAPJna (ORCPT + 30 others); Wed, 16 Jan 2019 04:43:30 -0500 Received: from mail-wm1-f67.google.com ([209.85.128.67]:38741 "EHLO mail-wm1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2391777AbfAPJn2 (ORCPT ); Wed, 16 Jan 2019 04:43:28 -0500 Received: by mail-wm1-f67.google.com with SMTP id m22so1251731wml.3 for ; Wed, 16 Jan 2019 01:43:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=IF8O5IB660i5uISr2+XWnKBaqatYQfBFmBwhpEAXDiM=; b=B+w4gOfSUmQtZBFsM9IOmNkQO7DxVOMJyoV+4sBrlbm9rsCUJNAEzXtwr+Xu7H306r aGJOXOcC3i5MTCSupFRmglXycFAP41w2nHWTU2VlnyA9vEBWY3Aq6DlULyszojdEO3ex xSc2wnF7RHLAjAsSM7qUDBwIivPfvQ6ymnFvk= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=IF8O5IB660i5uISr2+XWnKBaqatYQfBFmBwhpEAXDiM=; b=QjSmQCFfp2OVKfnlEkZJNTilQYwHmGLYYPQlolYi3jeTGoreALotbs3Cx3bdNB/bI4 pXMPHA3b4zsHxMvSkCzIQw757CUOSJUyFm3PIKxzrp/OcRbNr4FzgWhQjyZGQxPDCQLK bGiuEHiX/nq1KJg7GDpPJqsXFOF4Gj3JxF83yI4PNjxqjN12yaoZjV5mPb3D+XhLnaIu Yu3j5NbN+JJsdlKKJpfexeJ800NnX0rXwhVNZBveAsGsWGAb08fKnWe0NNCs9jCAKrIV JFx1WafNBW78n3KXcF8OE1h2N+JyEY02QNQzQoCcOecPbiQWfCBhOAQnMTrA6K/mThDG hwrw== X-Gm-Message-State: AJcUukd6HC5mC0ZQSzpFqWKPl6Ou+31rsEjxM9hGhRaeQ21PIyT8cdB/ ItV4uj47QUiNYDb/YG9LfDt9484XC1lStg== X-Received: by 2002:a1c:9d57:: with SMTP id g84mr6899437wme.16.1547631805375; Wed, 16 Jan 2019 01:43:25 -0800 (PST) Received: from localhost.localdomain ([2a01:e0a:f:6020:596d:a8c4:e914:fdde]) by smtp.gmail.com with ESMTPSA id k19sm115996304wre.5.2019.01.16.01.43.23 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 16 Jan 2019 01:43:24 -0800 (PST) From: Vincent Guittot To: peterz@infradead.org, mingo@kernel.org, linux-kernel@vger.kernel.org Cc: rjw@rjwysocki.net, dietmar.eggemann@arm.com, Morten.Rasmussen@arm.com, patrick.bellasi@arm.com, pjt@google.com, bsegall@google.com, thara.gopinath@linaro.org, pkondeti@codeaurora.org, quentin.perret@arm.com, srinivas.pandruvada@linux.intel.com, Vincent Guittot Subject: [PATCH v8 3/3] sched/pelt: skip updating util_est when utilization is higher than cpu's capacity Date: Wed, 16 Jan 2019 10:43:11 +0100 Message-Id: <1547631791-16018-4-git-send-email-vincent.guittot@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1547631791-16018-1-git-send-email-vincent.guittot@linaro.org> References: <1547631791-16018-1-git-send-email-vincent.guittot@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org util_est is mainly meant to be a lower-bound for tasks utilization. That's why task_util_est() returns the actual util_avg when it's higher than the estimated utilization. With new invaraince signal and without any special check on samples collection, if a task is limited because of thermal capping for example, we could end up overestimating its utilization and thus perhaps generating an unwanted frequency spike when the capping is relaxed... and (even worst) it will take some more activations for the estimated utilization to converge back to the actual utilization. Since we cannot easily know if there is idle time in a CPU when a task completes an activation with a utilization higher then the CPU capacity, we skip the sampling when utilization is higher than cpu's capacity. Suggested-by: Patrick Bellasi Signed-off-by: Vincent Guittot --- kernel/sched/fair.c | 14 +++++++++----- kernel/sched/sched.h | 7 +++++++ 2 files changed, 16 insertions(+), 5 deletions(-) -- 2.7.4 diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 9332863..2262c8a 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -3639,6 +3639,7 @@ util_est_dequeue(struct cfs_rq *cfs_rq, struct task_struct *p, bool task_sleep) { long last_ewma_diff; struct util_est ue; + int cpu; if (!sched_feat(UTIL_EST)) return; @@ -3673,6 +3674,14 @@ util_est_dequeue(struct cfs_rq *cfs_rq, struct task_struct *p, bool task_sleep) return; /* + * To avoid overestimation of actual task utilization, skip updates if + * we cannot grant there is idle time in this CPU. + */ + cpu = cpu_of(rq_of(cfs_rq)); + if (task_util(p) > capacity_orig_of(cpu)) + return; + + /* * Update Task's estimated utilization * * When *p completes an activation we can consolidate another sample @@ -5541,11 +5550,6 @@ static unsigned long capacity_of(int cpu) return cpu_rq(cpu)->cpu_capacity; } -static unsigned long capacity_orig_of(int cpu) -{ - return cpu_rq(cpu)->cpu_capacity_orig; -} - static unsigned long cpu_avg_load_per_task(int cpu) { struct rq *rq = cpu_rq(cpu); diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 4c506ea..455745e 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -2230,6 +2230,13 @@ static inline void cpufreq_update_util(struct rq *rq, unsigned int flags) {} # define arch_scale_freq_invariant() false #endif +#ifdef CONFIG_SMP +static inline unsigned long capacity_orig_of(int cpu) +{ + return cpu_rq(cpu)->cpu_capacity_orig; +} +#endif + #ifdef CONFIG_CPU_FREQ_GOV_SCHEDUTIL /** * enum schedutil_type - CPU utilization type