From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from SA9PR02CU001.outbound.protection.outlook.com (mail-southcentralusazon11013037.outbound.protection.outlook.com [40.93.196.37]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5B76D36308A for ; Fri, 10 Jul 2026 07:23:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.93.196.37 ARC-Seal:i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783668229; cv=fail; b=hAwVkFrgMgRW99ofFF0TtmgXfQtLCv5Pj3kOZGiHwryqIzBMQICG0A/aWMTuUL/80nRKqNYA17Kw6P1fdPTzTV8CtXhzyhDEEp1A+yC02w8dh6BssSJablqWIp9U7PzV23rewiC/9Q0MU3zmA3VMbZLgi97cF6I8hsAXEpHeD7g= ARC-Message-Signature:i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783668229; c=relaxed/simple; bh=JmHT4HI2e1zh+60rnXLfzRffjqC3j5OZUeYBwY5QyEA=; h=Message-ID:Date:MIME-Version:Subject:To:CC:References:From: In-Reply-To:Content-Type; b=tIwutUi0rzppWd3IQFdtXK3qfU7rLeY7q3KQNhWnJU7O2ey8TP6P8NCN6tQNY/BUDTw0Iky9AoHMFSjGjd3RP3uFhrfBUdJLpzNov6o3kWIhl1smQ7H81VzOAl9cLRkkaPFULATYKS98NMHKrWw/LKe/XGI2bJEvH7ErUzEzHms= ARC-Authentication-Results:i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com; spf=fail smtp.mailfrom=amd.com; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b=JRQYlKeV; arc=fail smtp.client-ip=40.93.196.37 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=amd.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b="JRQYlKeV" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=I/4GvZk+gPSSJstTo1l7TeWrY+mnz1/MDEhLNZN2QfgoveeK5mb4xP5jlX30TAXXgFCpTiM33a8uz/TO/HYlFEisxi9uWhEJ9Lr8dqTXh6vVKNXbIyFiASt3m0PcquctL15lFEhYibSFnJ/7+SDPePT/Qnj3fk56aAI/V1Nh1GUIPulPD8+ApbEw0uJVm9USVuDr2Ot2RuWq/BFVEpKDCp/rRZdXvtbVAYdoZlHDgB57tPdRoBVck7/MdVf55G4grPLTzxpznKpWUlhKd8J1fjgbPBKXb41sucjRnM+iV9gq96Lc4t8YlhaXia9CoNIeZE0ojt45c/dXpDIDORHfzw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=rPj3c51goFo3svKiLGEuzQLuz5RlPljsUiVJMXWMV94=; b=etzv/MIeRl8Pz2pFPbd2Tp0LeE6iC08gl4v0ffGIrUIF9MrXid8tOeFpeLA+jmbb9u2jtGTzW7mt7evXEqkPVk0RyCUJjPvcB3qBAnK1XfeNX/0xYRbtqfKbWCKAPk9SdiB1QPkokG/ogeH+F4C8LkaKo8PMnlWikXfSeLV1vjfVYuaBL7BR+ISVN4nUmvIbMJgOOdrt+99X2lYA/6iEYCroXjdsKFPbqWHoN6mi32GDB3Uu3ewRFGMsj9pWrM+XGqPxqiSNj3cQjlqMrlQXx79MzvN5Hsi302HuZqQZ22rabp/GRpHUSrzrmm4UngbC8gqt89u/1chQr1TsCtk6mg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=zohomail.com smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=rPj3c51goFo3svKiLGEuzQLuz5RlPljsUiVJMXWMV94=; b=JRQYlKeVBX6JYSHtBdCPBxNPNTQDOLma4eYo5EmHyNr9UUMGlyoWTyB4xQo4YnIz0wDLQ7sBzTJrhsA5qIFk/ek4dDAes9C/Uu2CVtozq/Q5JfB1Lg65k55lJ8gGIizGbsogVUWFBaev9ktONktvc3ne2PietJX3vKmZgM0A7MM= Received: from PH7P221CA0015.NAMP221.PROD.OUTLOOK.COM (2603:10b6:510:32a::11) by SA1PR12MB7344.namprd12.prod.outlook.com (2603:10b6:806:2b7::15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.181.17; Fri, 10 Jul 2026 07:23:42 +0000 Received: from SA2PEPF000015CC.namprd03.prod.outlook.com (2603:10b6:510:32a:cafe::61) by PH7P221CA0015.outlook.office365.com (2603:10b6:510:32a::11) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.21.202.12 via Frontend Transport; Fri, 10 Jul 2026 07:23:42 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=satlexmb08.amd.com; pr=C Received: from satlexmb08.amd.com (165.204.84.17) by SA2PEPF000015CC.mail.protection.outlook.com (10.167.241.202) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.181.6 via Frontend Transport; Fri, 10 Jul 2026 07:23:41 +0000 Received: from satlexmb10.amd.com (10.181.42.219) by satlexmb08.amd.com (10.181.42.217) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.41; Fri, 10 Jul 2026 02:23:41 -0500 Received: from satlexmb08.amd.com (10.181.42.217) by satlexmb10.amd.com (10.181.42.219) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.41; Fri, 10 Jul 2026 02:23:40 -0500 Received: from [10.136.35.241] (10.180.168.240) by satlexmb08.amd.com (10.181.42.217) with Microsoft SMTP Server id 15.2.2562.41 via Frontend Transport; Fri, 10 Jul 2026 02:23:37 -0500 Message-ID: Date: Fri, 10 Jul 2026 12:53:31 +0530 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 RFC] sched/proxy: Defer donor commit until after proxy resolution To: Xukai Wang , Ingo Molnar , "Peter Zijlstra" , Juri Lelli , "Vincent Guittot" , Dietmar Eggemann , Steven Rostedt , Ben Segall , Mel Gorman , Valentin Schneider CC: References: <20260707-sched-proxy-v1-0-5928bf6dedf0@zohomail.com> <20260707-sched-proxy-v1-1-5928bf6dedf0@zohomail.com> Content-Language: en-US From: K Prateek Nayak In-Reply-To: <20260707-sched-proxy-v1-1-5928bf6dedf0@zohomail.com> Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 7bit X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: SA2PEPF000015CC:EE_|SA1PR12MB7344:EE_ X-MS-Office365-Filtering-Correlation-Id: 34c23749-d9d0-46f9-f977-08dede542b20 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|23010399003|7416014|376014|1800799024|82310400026|36860700016|18002099003|22082099003|4143699003|11063799006|56012099006|921020; X-Microsoft-Antispam-Message-Info: /yyju2nfLMJ2rsyvwrCPxiThI8Ilbvj/nkw88g+5dtEuKlUaAomI2uUP9oO72Zu9xXguhW5z6wv59sG6y6o/3H0H38P3J9xBulHS7CgORcJyBIsD9XHD29LgJAh6yxWJD2V05cYdccLMr8n1sWrE0hTVBE/GoizIzO+LnqSrRujt/LBNmqJC3V4YJgKIXU+NFclpAsdmPV2AVWavEdcYOaeSaCadzGi2ctzdLEDEL9niOLiuT0n7W6NUQhi2RrXC+4ZIIbHXfX+xHEi6q6A+GcA4gcUJUhtecoaVnQcCH7uQyG8acstWVfE8CPcZ3Mx9eIywJgr8vbFs4dEzmDRV+6xQWR8BkdXYcuOntkyGuW3MYd9RIQHCKjVi7s4K0mqm1AvNR9hk5hStKw2QQhGloKaQOrT+5srcJSHmozUrhTgFkshCkyl4L/a9s6WTxJTjMvnE8LGofaPaxrNPjav9nr1K1XQkQNPOERcC6fAtfrRhupfdiJcpI/sWUJtXKOVsH7WiAQxnmelAu4qq+CU0532v1pa6Qu/6I3E3HsT/srN1UxBabqbRYy92iUVyCluDYq1puDeZAHCQbJSJoOZ+LuS6kk8QJ3DTCVqvXf/SOTyhjYE14up48CbFGLHXKTO6kIHnMkQ3V+cU47VYURbOiA+DWtHexgHFH/pQbj0B2lue+YgMuT0y1BzlSomMWzJArCYqDWaG3frFLxNFQkiTjvGwYTugljzuVj5FrSO10tHODq6egMYvf05dNv8ixHyy X-Forefront-Antispam-Report: CIP:165.204.84.17;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:satlexmb08.amd.com;PTR:InfoDomainNonexistent;CAT:NONE;SFS:(13230040)(23010399003)(7416014)(376014)(1800799024)(82310400026)(36860700016)(18002099003)(22082099003)(4143699003)(11063799006)(56012099006)(921020);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: ri4Flx+bb29KlJJXXDKfTfHNiQRP5YZh8aHRCrWFvcnrmkdXhWvPRxvUpMRPlh94WNNf2n6JllhXtlK3du9q/XCB6xHPOCeykGXc9kuEcG37XnPQlCPbWz2MByXHREahARBpbhkSSOFlWhtmROxn4ZwDrzJq8KXknKlIFAIQ3P9b+5jitPjAhuudkC3gMYsv3K2Kp7MRNFhocMrMJjuSxfY+OicWk9vvxQDYYURy423LMKKAL+woQi+L3mu/vM0ijFv7WfEWik2e78QKnIblx3FvtKpQKgahM1OGbKN3WZ0lD1ndB2CFvyAQQHkKA+fv5y7HRjwymr4YRAPNGGyosl+bMpQLQidP6becCSzz3tHe+HDlzokPtv6fVtmFQ8s80T0e52ou2IQhPKye6G2yOFr5RK42sRQnVzf+s6oFDwo+RM79aBjUdc3ZMmFjnbC8 X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 10 Jul 2026 07:23:41.4716 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 34c23749-d9d0-46f9-f977-08dede542b20 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d;Ip=[165.204.84.17];Helo=[satlexmb08.amd.com] X-MS-Exchange-CrossTenant-AuthSource: SA2PEPF000015CC.namprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: SA1PR12MB7344 Hello Xukai, On 7/7/2026 9:16 PM, Xukai Wang wrote: > pick_next_task() currently commits the selected task into the scheduling > class state before proxy execution has resolved whether that task should > really become the committed donor. > > With proxy execution enabled, the task returned by pick_next_task() may > be blocked. __schedule() then calls find_proxy_task() to resolve the > proxy chain. If find_proxy_task() returns NULL, __schedule() retries > through pick_again, but the picked donor has already gone through > put_prev_set_next_task(). In that case the class current state was > speculatively switched to a donor which is not the final scheduling > decision. As long as rq_lock is held, the pick will always select the same donor since there cannot be a wakeup / migration until the rq_lock is released. If there is a change in the proxy state, and the lock needs to be dropped, we do a proxy_resched_idle() and transiently switch to the idle task's accounting context. If we don't need to drop the rq_lock, we just retry the pick after dropping the blocked_lock and the pick will converge to the same donor unless ->balance() manages to pull something. Very often, it is the same donor task pick converges on. I don't see how this transient state is a big enough problem to see any noticeable overhead. > > Make pick_next_task() return only the selected candidate task. Move the > put_prev_set_next_task() call into __schedule(), next to rq_set_donor(), > so the class commit happens at the schedule level. > > For proxy execution, keep the picked donor separate from the actual task > to run: > > donor = task selected by pick_next_task() > next = task returned by find_proxy_task(), possibly the mutex owner > > Only commit the donor after proxy-chain resolution succeeds: > > put_prev_set_next_task(rq, prev_donor, donor); > rq_set_donor(rq, donor); > > If find_proxy_task() returns NULL, the candidate donor has not been > committed and __schedule() can retry without first undoing a speculative > set_next() on that donor. > > A proxy candidate is not necessarily the committed rq->donor anymore. > Update proxy_deactivate() accordingly. If the task being blocked is > still the committed donor, proxy_resched_idle() is needed to drop > rq/class current references before block_task() clears ->on_rq. If > it is only an uncommitted proxy candidate, it is still queued and can > be blocked directly. > > proxy_migrate_task() still switches the rq to idle before dropping the > rq lock. Migrating a task found in the proxy chain abandons the current > proxy pick attempt, and switching the committed donor to idle leaves > rq->donor and the class current state in a defined state while the chain > is modified and the task is attached elsewhere. > > This keeps the proxy donor accounting semantics intact: the scheduling > class state is committed to the donor, while the actual context switch > may still be to the proxy owner returned by find_proxy_task(). > > Signed-off-by: Xukai Wang > --- > kernel/sched/core.c | 70 ++++++++++++++++++++++++++++++----------------------- > 1 file changed, 40 insertions(+), 30 deletions(-) > > diff --git a/kernel/sched/core.c b/kernel/sched/core.c > index 2e7cde033a31..3c1a23a9c12c 100644 > --- a/kernel/sched/core.c > +++ b/kernel/sched/core.c > @@ -6146,7 +6146,6 @@ __pick_next_task(struct rq *rq, struct rq_flags *rf) > if (!p) > p = pick_task_idle(rq, rf); > > - put_prev_set_next_task(rq, rq->donor, p); > return p; > } > > @@ -6157,10 +6156,8 @@ __pick_next_task(struct rq *rq, struct rq_flags *rf) > p = class->pick_task(rq, rf); > if (unlikely(p == RETRY_TASK)) > goto restart; > - if (p) { > - put_prev_set_next_task(rq, rq->donor, p); > + if (p) > return p; > - } > } > > BUG(); /* The idle class should always have a runnable task. */ > @@ -6257,7 +6254,7 @@ pick_next_task(struct rq *rq, struct rq_flags *rf) > rq->dl_server = rq->core_dl_server; > rq->core_pick = NULL; > rq->core_dl_server = NULL; > - goto out_set_next; > + goto out_return_next; > } > > prev_balance(rq, rf); > @@ -6311,7 +6308,7 @@ pick_next_task(struct rq *rq, struct rq_flags *rf) > */ > WARN_ON_ONCE(fi_before); > task_vruntime_update(rq, next, false); > - goto out_set_next; > + goto out_return_next; > } > } > > @@ -6441,8 +6438,7 @@ pick_next_task(struct rq *rq, struct rq_flags *rf) > resched_curr(rq_i); > } > > -out_set_next: > - put_prev_set_next_task(rq, rq->donor, next); > +out_return_next: > if (rq->core->core_forceidle_count && next == rq->idle) > queue_core_balance(rq); > > @@ -6755,15 +6751,23 @@ static void proxy_deactivate(struct rq *rq, struct task_struct *donor) > WARN_ON_ONCE(state == TASK_RUNNING); > WARN_ON_ONCE(donor->blocked_on); > /* > - * Because we got donor from pick_next_task(), it is *crucial* > - * that we call proxy_resched_idle() before we deactivate it. > - * As once we deactivate donor, donor->on_rq is set to zero, > - * which allows ttwu() to immediately try to wake the task on > - * another rq. So we cannot use *any* references to donor > - * after that point. So things like cfs_rq->curr or rq->donor > - * need to be changed from next *before* we deactivate. > + * A proxy candidate is not necessarily the committed rq->donor. > + * pick_next_task() only selected it; the class current state is > + * updated later, after proxy-chain resolution. > + * > + * If @donor is still the committed donor, the rq and the scheduling > + * class may hold current references to it, such as rq->donor or > + * cfs_rq->curr/h_curr. Drop those references before block_task(), > + * because block_task() clears donor->on_rq and a concurrent wakeup > + * may then move the task elsewhere. > + * > + * If @donor is only an uncommitted proxy candidate, it is still a > + * queued task, not the class current task, so it can be blocked > + * directly. > */ > - proxy_resched_idle(rq); > + if (donor == rq->donor) > + proxy_resched_idle(rq); > + > block_task(rq, donor, state); > } > > @@ -6816,15 +6820,17 @@ static void proxy_migrate_task(struct rq *rq, struct rq_flags *rf, > lockdep_assert_rq_held(rq); > WARN_ON(p == rq->curr); > /* > - * Since we are migrating a blocked donor, it could be rq->donor, > - * and we want to make sure there aren't any references from this > - * rq to it before we drop the lock. This avoids another cpu > - * jumping in and grabbing the rq lock and referencing rq->donor > - * or cfs_rq->curr, etc after we have migrated it to another cpu, > - * and before we pick_again in __schedule. > + * Migrating a task found in the proxy chain abandons the current proxy > + * pick attempt and drops this rq's lock. > + * > + * The picked proxy candidate has not necessarily been committed, so > + * @p is not necessarily rq->donor. Switch the currently committed > + * donor to idle before dropping the lock, leaving rq->donor and the > + * class current state in a well-defined state while the chain is > + * modified and @p is attached elsewhere. > * > - * So call proxy_resched_idle() to drop the rq->donor references > - * before we release the lock. > + * If @p is rq->donor, this also drops the direct rq/class-current > + * references to @p before it leaves this rq. > */ > proxy_resched_idle(rq); > > @@ -7147,11 +7153,11 @@ static void __sched notrace __schedule(int sched_mode) > rq->next_class = next->sched_class; > if (sched_proxy_exec()) { > struct task_struct *prev_donor = rq->donor; > + struct task_struct *donor = next; > > - rq_set_donor(rq, next); > - next->blocked_donor = NULL; > - if (unlikely(next->is_blocked)) { > - next = find_proxy_task(rq, next, &rf); > + donor->blocked_donor = NULL; > + if (unlikely(donor->is_blocked)) { > + next = find_proxy_task(rq, donor, &rf); > if (!next) { > zap_balance_callbacks(rq); You don't need to zap any balance callbacks if you don't do a put_prev_set_next_task(). It should always be empty here. > goto pick_again; > @@ -7161,8 +7167,11 @@ static void __sched notrace __schedule(int sched_mode) > goto keep_resched; > } > } > - if (rq->donor == prev_donor && prev != next) { > - struct task_struct *donor = rq->donor; > + > + put_prev_set_next_task(rq, prev_donor, donor); > + rq_set_donor(rq, donor); Since the next condition only cares for donor == prev_donor, I think you can do this after the next block and unify the !sched_proxy_exec() case too like: diff --git a/kernel/sched/core.c b/kernel/sched/core.c index f13f53bd6d9d7..c6e37005a73c4 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -7171,9 +7171,6 @@ static void __sched notrace __schedule(int sched_mode) } } - put_prev_set_next_task(rq, prev_donor, donor); - rq_set_donor(rq, donor); - if (donor == prev_donor && prev != next) { /* * When transitioning like: @@ -7190,10 +7187,9 @@ static void __sched notrace __schedule(int sched_mode) donor->sched_class->put_prev_task(rq, donor, donor); donor->sched_class->set_next_task(rq, donor, true); } - } else { - put_prev_set_next_task(rq, rq->donor, next); - rq_set_donor(rq, next); } + put_prev_set_next_task(rq, rq->donor, next); + rq_set_donor(rq, next); picked: clear_tsk_need_resched(prev); --- > + > + if (donor == prev_donor && prev != next) { > /* > * When transitioning like: > * > @@ -7179,6 +7188,7 @@ static void __sched notrace __schedule(int sched_mode) > donor->sched_class->set_next_task(rq, donor, true); > } > } else { > + put_prev_set_next_task(rq, rq->donor, next); > rq_set_donor(rq, next); > } > > > -- > 2.34.1 > -- Thanks and Regards, Prateek