Received: by 2002:a25:4158:0:0:0:0:0 with SMTP id o85csp1163714yba; Tue, 2 Apr 2019 03:43:24 -0700 (PDT) X-Google-Smtp-Source: APXvYqxO/j1nV2gIdtIjzxflBbsnUfJPWlsYROiH93/e4sNGxWGdmPdkxIav028/cD5QYFYFLZ5m X-Received: by 2002:a63:78ce:: with SMTP id t197mr53056454pgc.314.1554201804771; Tue, 02 Apr 2019 03:43:24 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1554201804; cv=none; d=google.com; s=arc-20160816; b=ijO7hcPE0kRzUQgfAEKeTAuPMH3f8re1+Ez9eNVS+CLS0xeadx92UrIGcL1+3O4xvf IyAX1E3wd37rp6Bo88rYXyyIRdd9XKekR4BTvU+Ao1zpyfUahiPTXyPazW4XC5Q7qHUC hDufYrB33jnMCagGV1d0SvNAma2EXqgAl5UHrg5I40irfrLF1qEKo+nnf6fW3taQ2GJZ rsCeUvmnNe5ytMfTG/tGzYrcJ/OhCApGZWZkLOwzidBp3bOXICiO1xOlJe1ra+ID+CUd A7qGzOtRerRXitNDOx444gIYrf6JIZ7GLaoxPz7GlWJVd7Iep8GC4n9te/jkSAA+ip/S 8Dyg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=IuMI0tbJ8hahc1cXNJtSHjISgI2wTqcIfvqEznAIu8A=; b=0orazHmGA6toWzuKifSlqjUd4M1tS02sxkGdEFyFN1RIdo0FdQ9MjenhnWSpPTJt4M UYB79WTMPMuINRbg1opTnoYkHXxjopHdPC9XVHtk/MrGblju9O2aDhQ/Z1u4iAaGINVK c2yHANEobIoIPGx9ycznUkJPFxIgA4ukJm93o9uj7W8S3ORj/m/Sj+TyM/7cMugxhCZX WpsUx9Fx71gbuLd2i37XZeZbHsZsDNW0zlI5MP+wxESFrX0uE7txXs/e0Bf1bO7Gtfhu /N7honc0NQUONtdhJw6WT3CkOoGJvFRbz1YcssEmFU64lk++8li0Vn0ufZSgrCePSM9w c+qw== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id l69si11226717plb.272.2019.04.02.03.43.09; Tue, 02 Apr 2019 03:43:24 -0700 (PDT) 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; 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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729576AbfDBKm0 (ORCPT + 99 others); Tue, 2 Apr 2019 06:42:26 -0400 Received: from foss.arm.com ([217.140.101.70]:48312 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726193AbfDBKmZ (ORCPT ); Tue, 2 Apr 2019 06:42:25 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 84AF01688; Tue, 2 Apr 2019 03:42:24 -0700 (PDT) Received: from e110439-lin.cambridge.arm.com (e110439-lin.cambridge.arm.com [10.1.194.43]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 6D5EC3F59C; Tue, 2 Apr 2019 03:42:21 -0700 (PDT) From: Patrick Bellasi To: linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, linux-api@vger.kernel.org Cc: Ingo Molnar , Peter Zijlstra , Tejun Heo , "Rafael J . Wysocki" , Vincent Guittot , Viresh Kumar , Paul Turner , Quentin Perret , Dietmar Eggemann , Morten Rasmussen , Juri Lelli , Todd Kjos , Joel Fernandes , Steve Muckle , Suren Baghdasaryan Subject: [PATCH v8 02/16] sched/core: Add bucket local max tracking Date: Tue, 2 Apr 2019 11:41:38 +0100 Message-Id: <20190402104153.25404-3-patrick.bellasi@arm.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190402104153.25404-1-patrick.bellasi@arm.com> References: <20190402104153.25404-1-patrick.bellasi@arm.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Because of bucketization, different task-specific clamp values are tracked in the same bucket. For example, with 20% bucket size and assuming to have: Task1: util_min=25% Task2: util_min=35% both tasks will be refcounted in the [20..39]% bucket and always boosted only up to 20% thus implementing a simple floor aggregation normally used in histograms. In systems with only few and well-defined clamp values, it would be useful to track the exact clamp value required by a task whenever possible. For example, if a system requires only 23% and 47% boost values then it's possible to track the exact boost required by each task using only 3 buckets of ~33% size each. Introduce a mechanism to max aggregate the requested clamp values of RUNNABLE tasks in the same bucket. Keep it simple by resetting the bucket value to its base value only when a bucket becomes inactive. Allow a limited and controlled overboosting margin for tasks recounted in the same bucket. In systems where the boost values are not known in advance, it is still possible to control the maximum acceptable overboosting margin by tuning the number of clamp groups. For example, 20 groups ensure a 5% maximum overboost. Remove the rq bucket initialization code since a correct bucket value is now computed when a task is refcounted into a CPU's rq. Signed-off-by: Patrick Bellasi Cc: Ingo Molnar Cc: Peter Zijlstra -- Changes in v8: Message-ID: <20190313193916.GQ2482@worktop.programming.kicks-ass.net> - split this code out from the previous patch --- kernel/sched/core.c | 46 ++++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 032211b72110..6e1beae5f348 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -778,6 +778,11 @@ unsigned int uclamp_rq_max_value(struct rq *rq, unsigned int clamp_id) * When a task is enqueued on a rq, the clamp bucket currently defined by the * task's uclamp::bucket_id is refcounted on that rq. This also immediately * updates the rq's clamp value if required. + * + * Tasks can have a task-specific value requested from user-space, track + * within each bucket the maximum value for tasks refcounted in it. + * This "local max aggregation" allows to track the exact "requested" value + * for each bucket when all its RUNNABLE tasks require the same clamp. */ static inline void uclamp_rq_inc_id(struct task_struct *p, struct rq *rq, unsigned int clamp_id) @@ -789,8 +794,15 @@ static inline void uclamp_rq_inc_id(struct task_struct *p, struct rq *rq, bucket = &uc_rq->bucket[uc_se->bucket_id]; bucket->tasks++; + /* + * Local max aggregation: rq buckets always track the max + * "requested" clamp value of its RUNNABLE tasks. + */ + if (uc_se->value > bucket->value) + bucket->value = uc_se->value; + if (uc_se->value > READ_ONCE(uc_rq->value)) - WRITE_ONCE(uc_rq->value, bucket->value); + WRITE_ONCE(uc_rq->value, uc_se->value); } /* @@ -815,6 +827,12 @@ static inline void uclamp_rq_dec_id(struct task_struct *p, struct rq *rq, if (likely(bucket->tasks)) bucket->tasks--; + /* + * Keep "local max aggregation" simple and accept to (possibly) + * overboost some RUNNABLE tasks in the same bucket. + * The rq clamp bucket value is reset to its base value whenever + * there are no more RUNNABLE tasks refcounting it. + */ if (likely(bucket->tasks)) return; @@ -824,8 +842,14 @@ static inline void uclamp_rq_dec_id(struct task_struct *p, struct rq *rq, * e.g. due to future modification, warn and fixup the expected value. */ SCHED_WARN_ON(bucket->value > rq_clamp); - if (bucket->value >= rq_clamp) + if (bucket->value >= rq_clamp) { + /* + * Reset clamp bucket value to its nominal value whenever + * there are anymore RUNNABLE tasks refcounting it. + */ + bucket->value = uclamp_bucket_base_value(bucket->value); WRITE_ONCE(uc_rq->value, uclamp_rq_max_value(rq, clamp_id)); + } } static inline void uclamp_rq_inc(struct rq *rq, struct task_struct *p) @@ -855,25 +879,9 @@ static void __init init_uclamp(void) unsigned int clamp_id; int cpu; - for_each_possible_cpu(cpu) { - struct uclamp_bucket *bucket; - struct uclamp_rq *uc_rq; - unsigned int bucket_id; - + for_each_possible_cpu(cpu) memset(&cpu_rq(cpu)->uclamp, 0, sizeof(struct uclamp_rq)); - for (clamp_id = 0; clamp_id < UCLAMP_CNT; ++clamp_id) { - uc_rq = &cpu_rq(cpu)->uclamp[clamp_id]; - - bucket_id = 1; - while (bucket_id < UCLAMP_BUCKETS) { - bucket = &uc_rq->bucket[bucket_id]; - bucket->value = bucket_id * UCLAMP_BUCKET_DELTA; - ++bucket_id; - } - } - } - for (clamp_id = 0; clamp_id < UCLAMP_CNT; ++clamp_id) { struct uclamp_se *uc_se = &init_task.uclamp[clamp_id]; -- 2.20.1