Received: by 2002:a05:7412:b995:b0:f9:9502:5bb8 with SMTP id it21csp743919rdb; Fri, 22 Dec 2023 03:59:13 -0800 (PST) X-Google-Smtp-Source: AGHT+IHaTaz3/SJ/LnO1z4PfZgczRPY49v4eKDx6NnLhK8jcYxAy1JB1n9UrSxCJ3/px2yYvs/Ep X-Received: by 2002:a17:902:d2cf:b0:1d0:6ffd:9e1e with SMTP id n15-20020a170902d2cf00b001d06ffd9e1emr1047449plc.112.1703246353539; Fri, 22 Dec 2023 03:59:13 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1703246353; cv=none; d=google.com; s=arc-20160816; b=JIs5FigL5jV9v8t7gUQJyOyQtr6Ito/n53sfIXjt7jWIL0omCYmJmFbsv1cp/XtwS+ qo5hb1Qk9NHXLNC2xxeNVHPeG7BjfaYWiYDBQA64GnJCGfj5AmQwJgRVCZ9R1XSYEK3n wIxKV6AL47/h5Cmc1MXVwej6GAnkmhXg3IedSzTE1Q+ETxCmn1iAW0smctsDfwNroGL6 eX5MTj8nSIvcHfI2cuZEE/HF6mnm6dMAdctas/P+nPtBbkHGX/2sbvcYZnh2cdtKpKRN PGSpCbhwUg9xKZDza4zlx1u7pHKB8i+mYvV+3C/e0Xd3mC7ilwPfX8jVhTztkYLcnigA pA8Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:in-reply-to:from:references:cc:to :content-language:subject:user-agent:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:date:message-id; bh=d6gDyoQr7KmwliXJ/C0yOpygpmX4uQ5fHiaWvGGKqDw=; fh=IIn5181kkf6eV43uezdjLqEXV63ArwY//WIorpexdA4=; b=dUU4wDPM4kTweN6yDomScz1AOk988Np129fh9Ka4KLwmLfYv+vmrBhyjlsshANoeQW vPXQAROvvwLKT8JORVQ8J2uVjazjkBXTUOR6TbLRofmqdVzkW5xi9HtCRM3WCQPKJAAa h8qK8MvQf26QdvXIULRNCouyRvbr40vwSAc9DWL06mNKe1i8mcdA/UinNXyffDryPCUk ZRyjV1ae9ulUcaDMaT55Sa3ZAad/yokbCC4KppOnTbFV9SfVLYrW20VKlKiS5BoSDjGI khYqDnCrBwBYavDq8tQahrHXeksIf1opyP+GoZUV7T8TvsmKFQpSHYI+6bPSBAbAzGFq JOZA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel+bounces-9683-linux.lists.archive=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) smtp.mailfrom="linux-kernel+bounces-9683-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Return-Path: Received: from sy.mirrors.kernel.org (sy.mirrors.kernel.org. [147.75.48.161]) by mx.google.com with ESMTPS id g1-20020a170902fe0100b001d372875c31si3057179plj.41.2023.12.22.03.59.12 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 22 Dec 2023 03:59:13 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-9683-linux.lists.archive=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) client-ip=147.75.48.161; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel+bounces-9683-linux.lists.archive=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) smtp.mailfrom="linux-kernel+bounces-9683-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sy.mirrors.kernel.org (Postfix) with ESMTPS id 48101B22C71 for ; Fri, 22 Dec 2023 11:59:12 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id B2673179B2; Fri, 22 Dec 2023 11:57:37 +0000 (UTC) X-Original-To: linux-kernel@vger.kernel.org Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id EB83821A1E for ; Fri, 22 Dec 2023 11:57:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 6B98A2F4; Fri, 22 Dec 2023 03:58:19 -0800 (PST) Received: from [10.57.87.46] (unknown [10.57.87.46]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id E9D583F64C; Fri, 22 Dec 2023 03:57:30 -0800 (PST) Message-ID: <4a137164-0a4a-4f7e-806e-ef532fa86ece@arm.com> Date: Fri, 22 Dec 2023 11:57:24 +0000 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH v7 21/23] sched: Add find_exec_ctx helper Content-Language: en-US To: John Stultz , LKML Cc: Joel Fernandes , Qais Yousef , Ingo Molnar , Peter Zijlstra , Juri Lelli , Vincent Guittot , Dietmar Eggemann , Valentin Schneider , Steven Rostedt , Ben Segall , Zimuzo Ezeozue , Youssef Esmat , Mel Gorman , Daniel Bristot de Oliveira , Will Deacon , Waiman Long , Boqun Feng , "Paul E. McKenney" , Xuewen Yan , K Prateek Nayak , Thomas Gleixner , kernel-team@android.com References: <20231220001856.3710363-1-jstultz@google.com> <20231220001856.3710363-22-jstultz@google.com> From: Metin Kaya In-Reply-To: <20231220001856.3710363-22-jstultz@google.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit On 20/12/2023 12:18 am, John Stultz wrote: > From: Connor O'Brien > > Add a helper to find the runnable owner down a chain of blocked waiters > > This patch was broken out from a larger chain migration > patch originally by Connor O'Brien. > > Cc: Joel Fernandes > Cc: Qais Yousef > Cc: Ingo Molnar > Cc: Peter Zijlstra > Cc: Juri Lelli > Cc: Vincent Guittot > Cc: Dietmar Eggemann > Cc: Valentin Schneider > Cc: Steven Rostedt > Cc: Ben Segall > Cc: Zimuzo Ezeozue > Cc: Youssef Esmat > Cc: Mel Gorman > Cc: Daniel Bristot de Oliveira > Cc: Will Deacon > Cc: Waiman Long > Cc: Boqun Feng > Cc: "Paul E. McKenney" > Cc: Metin Kaya > Cc: Xuewen Yan > Cc: K Prateek Nayak > Cc: Thomas Gleixner > Cc: kernel-team@android.com > Signed-off-by: Connor O'Brien > [jstultz: split out from larger chain migration patch] > Signed-off-by: John Stultz > --- > kernel/sched/core.c | 42 +++++++++++++++++++++++++++++++++++++++++ > kernel/sched/cpupri.c | 11 ++++++++--- > kernel/sched/deadline.c | 15 +++++++++++++-- > kernel/sched/rt.c | 9 ++++++++- > kernel/sched/sched.h | 10 ++++++++++ > 5 files changed, 81 insertions(+), 6 deletions(-) > > diff --git a/kernel/sched/core.c b/kernel/sched/core.c > index 0c212dcd4b7a..77a79d5f829a 100644 > --- a/kernel/sched/core.c > +++ b/kernel/sched/core.c > @@ -3896,6 +3896,48 @@ static void activate_blocked_entities(struct rq *target_rq, > } > raw_spin_unlock_irqrestore(&owner->blocked_lock, flags); > } > + > +static inline bool task_queued_on_rq(struct rq *rq, struct task_struct *task) > +{ > + if (!task_on_rq_queued(task)) > + return false; > + smp_rmb(); > + if (task_rq(task) != rq) > + return false; > + smp_rmb(); > + if (!task_on_rq_queued(task)) > + return false; * Super-nit: we may want to have empty lines between `if` blocks and before/after `smp_rmb()` calls. * I did not understand why we call `task_on_rq_queued(task)` twice. Should we have an explanatory comment before the function definition? > + return true; > +} > + > +/* > + * Returns the unblocked task at the end of the blocked chain starting with p > + * if that chain is composed entirely of tasks enqueued on rq, or NULL otherwise. > + */ > +struct task_struct *find_exec_ctx(struct rq *rq, struct task_struct *p) > +{ > + struct task_struct *exec_ctx, *owner; > + struct mutex *mutex; > + > + if (!sched_proxy_exec()) > + return p; > + > + lockdep_assert_rq_held(rq); > + > + for (exec_ctx = p; task_is_blocked(exec_ctx) && !task_on_cpu(rq, exec_ctx); > + exec_ctx = owner) { > + mutex = exec_ctx->blocked_on; > + owner = __mutex_owner(mutex); > + if (owner == exec_ctx) > + break; > + > + if (!task_queued_on_rq(rq, owner) || task_current_selected(rq, owner)) { > + exec_ctx = NULL; > + break; > + } > + } > + return exec_ctx; > +} > #else /* !CONFIG_SCHED_PROXY_EXEC */ > static inline void do_activate_task(struct rq *rq, struct task_struct *p, > int en_flags) > diff --git a/kernel/sched/cpupri.c b/kernel/sched/cpupri.c > index 15e947a3ded7..53be78afdd07 100644 > --- a/kernel/sched/cpupri.c > +++ b/kernel/sched/cpupri.c > @@ -96,12 +96,17 @@ static inline int __cpupri_find(struct cpupri *cp, struct task_struct *p, > if (skip) > return 0; > > - if (cpumask_any_and(&p->cpus_mask, vec->mask) >= nr_cpu_ids) > + if ((p && cpumask_any_and(&p->cpus_mask, vec->mask) >= nr_cpu_ids) || > + (!p && cpumask_any(vec->mask) >= nr_cpu_ids)) > return 0; > > if (lowest_mask) { > - cpumask_and(lowest_mask, &p->cpus_mask, vec->mask); > - cpumask_and(lowest_mask, lowest_mask, cpu_active_mask); > + if (p) { > + cpumask_and(lowest_mask, &p->cpus_mask, vec->mask); > + cpumask_and(lowest_mask, lowest_mask, cpu_active_mask); > + } else { > + cpumask_copy(lowest_mask, vec->mask); > + } I think changes in `cpupri.c` should be part of previous (`sched: Push execution and scheduler context split into deadline and rt paths`) patch. Because they don't seem to be related with find_exec_ctx()? > > /* > * We have to ensure that we have at least one bit > diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c > index 999bd17f11c4..21e56ac58e32 100644 > --- a/kernel/sched/deadline.c > +++ b/kernel/sched/deadline.c > @@ -1866,6 +1866,8 @@ static void migrate_task_rq_dl(struct task_struct *p, int new_cpu __maybe_unused > > static void check_preempt_equal_dl(struct rq *rq, struct task_struct *p) > { > + struct task_struct *exec_ctx; > + > /* > * Current can't be migrated, useless to reschedule, > * let's hope p can move out. > @@ -1874,12 +1876,16 @@ static void check_preempt_equal_dl(struct rq *rq, struct task_struct *p) > !cpudl_find(&rq->rd->cpudl, rq_selected(rq), rq->curr, NULL)) > return; > > + exec_ctx = find_exec_ctx(rq, p); > + if (task_current(rq, exec_ctx)) > + return; > + > /* > * p is migratable, so let's not schedule it and > * see if it is pushed or pulled somewhere else. > */ > if (p->nr_cpus_allowed != 1 && > - cpudl_find(&rq->rd->cpudl, p, p, NULL)) > + cpudl_find(&rq->rd->cpudl, p, exec_ctx, NULL)) > return; > > resched_curr(rq); > @@ -2169,12 +2175,17 @@ static int find_later_rq(struct task_struct *sched_ctx, struct task_struct *exec > /* Locks the rq it finds */ > static struct rq *find_lock_later_rq(struct task_struct *task, struct rq *rq) > { > + struct task_struct *exec_ctx; > struct rq *later_rq = NULL; > int tries; > int cpu; > > for (tries = 0; tries < DL_MAX_TRIES; tries++) { > - cpu = find_later_rq(task, task); > + exec_ctx = find_exec_ctx(rq, task); > + if (!exec_ctx) > + break; > + > + cpu = find_later_rq(task, exec_ctx); > Super-nit: this empty line should be removed to keep logically connected lines closer. The same for find_lock_lowest_rq(). > if ((cpu == -1) || (cpu == rq->cpu)) > break; > diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c > index 6371b0fca4ad..f8134d062fa3 100644 > --- a/kernel/sched/rt.c > +++ b/kernel/sched/rt.c > @@ -1640,6 +1640,11 @@ static void check_preempt_equal_prio(struct rq *rq, struct task_struct *p) > !cpupri_find(&rq->rd->cpupri, rq_selected(rq), rq->curr, NULL)) > return; > > + /* No reason to preempt since rq->curr wouldn't change anyway */ > + exec_ctx = find_exec_ctx(rq, p); > + if (task_current(rq, exec_ctx)) > + return; > + > /* > * p is migratable, so let's not schedule it and > * see if it is pushed or pulled somewhere else. > @@ -1933,12 +1938,14 @@ static int find_lowest_rq(struct task_struct *sched_ctx, struct task_struct *exe > /* Will lock the rq it finds */ > static struct rq *find_lock_lowest_rq(struct task_struct *task, struct rq *rq) > { > + struct task_struct *exec_ctx; > struct rq *lowest_rq = NULL; > int tries; > int cpu; > > for (tries = 0; tries < RT_MAX_TRIES; tries++) { > - cpu = find_lowest_rq(task, task); > + exec_ctx = find_exec_ctx(rq, task); > + cpu = find_lowest_rq(task, exec_ctx); > > if ((cpu == -1) || (cpu == rq->cpu)) > break; > diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h > index ef3d327e267c..6cd473224cfe 100644 > --- a/kernel/sched/sched.h > +++ b/kernel/sched/sched.h > @@ -3564,6 +3564,16 @@ int task_is_pushable(struct rq *rq, struct task_struct *p, int cpu) > > return 0; > } > + > +#ifdef CONFIG_SCHED_PROXY_EXEC > +struct task_struct *find_exec_ctx(struct rq *rq, struct task_struct *p); > +#else /* !CONFIG_SCHED_PROXY_EXEC */ > +static inline > +struct task_struct *find_exec_ctx(struct rq *rq, struct task_struct *p) > +{ > + return p; > +} > +#endif /* CONFIG_SCHED_PROXY_EXEC */ > #endif Nit: `#ifdef CONFIG_SMP` block becomes bigger after this hunk. We should append `/* CONFIG_SMP */` to this line, IMHO. > > #endif /* _KERNEL_SCHED_SCHED_H */