From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from SJ2PR03CU001.outbound.protection.outlook.com (mail-westusazon11012022.outbound.protection.outlook.com [52.101.43.22]) (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 6B07415E8B for ; Wed, 5 Aug 2026 03:30:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.43.22 ARC-Seal:i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785900658; cv=fail; b=lZeA/tl6LTz9Az2lWLJXggDf66JaZfBD6ut+GeDXjdaM/7S9bm4n8fn0zAs9nr0R5NblhPMSZd4cvD5NXM7mJiKcj002sYqQHMTTJ5cqKSfo3c032iQOauoytNfugfnQVOZccMI5qOSofrnKdKpvs8eZf3JboyeGCat6zy016w8= ARC-Message-Signature:i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785900658; c=relaxed/simple; bh=z1eZeqkPo3UukOsn5Q1b6Xzkca4cad+0gy2hi3yIOM4=; h=Message-ID:Date:MIME-Version:Subject:To:CC:References:From: In-Reply-To:Content-Type; b=jPvXiXygu/C0LY7Y5GeDeN/c/8+Tt9xNsa9r6ScFz1fH7yTWoKsxpO/AaJ4XTAPSytlQ70D6g49elYeL6goLabajKq/KP3RGY+32/jJIa9D/NQFBy9+BD2V4HTZDcBaM4fohPe61q3JbwDihVfvl5tJbcOkpGSxwwKtdAlH3HMM= 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=y8DNTG47; arc=fail smtp.client-ip=52.101.43.22 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="y8DNTG47" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=N93NSUgFP1RMM2tOjWU/zprpap7mr1ELl2R2Jp5g0prVrNiGGdrY2svLc0VgBHoHR54Uv/O4eZsD22wuLqMB7ywSloDrweNReUiBAAVFc1oiAXGVk61TXbMNYipU4GsTE2sFxtWJSRZgPMVVKw/oY98LHJ/+sbfdnwsEyNJ8L/tNDiP9uKnlzvcWbmJwVCzEKsSomR14aOl4nycQtEhWgT0bqgusNVQkhkfUSMhR2u4yZ1x7DKj1zBQSMEoeu3EeS686e4d/AszdmOosRleuEvHWcrfxSh8Nbrb0DMt0oMMmg7g9vZbua5QYywlelChw4Av4FYuU2DJLb09/8GdwGA== 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=LoQlcimaxS+gcOYSJ6QafQEfLXrmF26/na9HgOrPwTg=; b=YzLff5LLeJ1IPDHqoNjokHnu6/1ZpydRpy+oVAxBBAjrpc07UoyhS0xpMbnepfT55KhJhBv4bXTenY4MpDZAJ8r+//K7ts2L+nrelMzHfwgJkJzkHD+C8IFkrApEWAccJmp5sF5am2RdzEdF8Y/n6XsLkbCZK2mGhf4vxEY9Kt8546DwxSpn6Ykrz7mqmeTx3MEFLhCXFZaLcVOSsKs29/j+gpcP9TlFXdpX1HbDCR8tTNzd6BeCbE/6G7WKYZlOrHWR+dHdvMmYmZqDYZM0qUWgVwbxV/q+Ae2eKdFPoSh/hlOTnEXLfrOLHm/eQaQB0H03rLmIG4GglHY7F8vTLw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=linux.ibm.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=LoQlcimaxS+gcOYSJ6QafQEfLXrmF26/na9HgOrPwTg=; b=y8DNTG47s+PAeb/1csbMox77bSnfYSshnNChFD1hZYd1uBZIdN9FZF8An9yPvC1DwBDHJBEV/vaWMr1PYcuYNQ7N7yOQ9K6BUcOBuYGY3SchxWxoDsaBnw5KhCsS0OQ2O02WfX7Bmj2wOYXB+Z7chQ/gCt1kSQuMevGBjIqkSDE= Received: from BY3PR05CA0059.namprd05.prod.outlook.com (2603:10b6:a03:39b::34) by BN7PPFD6BF22047.namprd12.prod.outlook.com (2603:10b6:40f:fc02::6e4) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.270.18; Wed, 5 Aug 2026 03:30:50 +0000 Received: from SJ1PEPF00002324.namprd03.prod.outlook.com (2603:10b6:a03:39b:cafe::83) by BY3PR05CA0059.outlook.office365.com (2603:10b6:a03:39b::34) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.21.292.15 via Frontend Transport; Wed, 5 Aug 2026 03:30:50 +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 SJ1PEPF00002324.mail.protection.outlook.com (10.167.242.87) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.292.8 via Frontend Transport; Wed, 5 Aug 2026 03:30:50 +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; Tue, 4 Aug 2026 22:30:49 -0500 Received: from satlexmb07.amd.com (10.181.42.216) 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; Tue, 4 Aug 2026 22:30:49 -0500 Received: from [10.136.47.95] (10.180.168.240) by satlexmb07.amd.com (10.181.42.216) with Microsoft SMTP Server id 15.2.2562.41 via Frontend Transport; Tue, 4 Aug 2026 22:30:46 -0500 Message-ID: Date: Wed, 5 Aug 2026 09:00:40 +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] sched/fair: Let sync wakeups target the waker's core To: Madadi Vineeth Reddy CC: Ingo Molnar , Peter Zijlstra , Juri Lelli , Vincent Guittot , Dietmar Eggemann , Steven Rostedt , Ben Segall , "Mel Gorman" , Valentin Schneider , , References: <20260801035532.260625-1-vineethr@linux.ibm.com> <492e6bb3-504d-486a-ad9d-226e9d7235a3@amd.com> <40536fd1-cdc6-4fac-a78f-1ed0df1fcce6@linux.ibm.com> Content-Language: en-US From: K Prateek Nayak In-Reply-To: <40536fd1-cdc6-4fac-a78f-1ed0df1fcce6@linux.ibm.com> Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 7bit X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: SJ1PEPF00002324:EE_|BN7PPFD6BF22047:EE_ X-MS-Office365-Filtering-Correlation-Id: 27ee0faf-b1c0-469b-f41b-08def2a1f294 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|376014|23010399003|36860700016|7416014|1800799024|82310400026|56012099006|5023799004|11063799006|10067099003|4143699003|22082099003|18002099003; X-Microsoft-Antispam-Message-Info: bSWEjmFzCh8zMaYHEC86ZKuu2jIJ4x54RCT2OpozNXlxWqhwir96n84bjmx+CDXK/jmlFclAukyJ2cRnM2C8yDAuxRAio/YPXwrP/i/UNa90UO/tvBtvum9aJ/FfDWRtdAark61InYjLEJg7mFOujp9ic/fVCaNYxTUWJeKS1srv94KJLCsJEm8oknAPvdfXLk9boPJagebVWfwiQ3GiAu4RH6f9SWV4UemA7PSS+VornJaHrIVPVXD5dtPl90sUImNAJhapo6dGXIsOcivt4ttsDS/bMtxl4oRB6jjUpr4IOiKMLgdRUFSqp+LkqtCZFLi8iv7vb8CK2Ju9DDL0+JpL5BXeC7Ub+Dw2SXVBEpGUXUYVzOpF4XERCJddnkECtlT64CW1ZPEJ5zt3qDCRO/8s1WLQIZ2w0ScZl2oq6wNyuiIT9nUyLLnWHD42BGHmOUrsjd9BPRWbOakHoXutD67rPbYvpmcWZkG7LDwIwL0zvULDv/0/4AozyEW2k0FPslsgDxQ+z5zsEwtUboyp1ufmxUEoCuFDLFigzEFXIf/TpdXclQuH3Mdf2HYNB5zyIBLAP6JfST5AYiugqR21kRpQp6HCa1AlhA6/NOUuk/FTVht0SQcu7VAR7tan4XSU6/loTT83iujZJA5r/LfIkcod3MNMRnbNXcibg97gUDxC5KDoxqWLKgs9Nl9NE28/zs+9DfLE9z5vJ72vejvy0g== 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)(376014)(23010399003)(36860700016)(7416014)(1800799024)(82310400026)(56012099006)(5023799004)(11063799006)(10067099003)(4143699003)(22082099003)(18002099003);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: JKezpxA1Vlc/LOMd6fOtnq/X00V2okb3uZpPoaP89NOsaEoLcoNnWS3x+FfjfdL+8FxECUGK5sduQPZLHoaopf7HjvqCYthbSKrw/bUA8gnxFSio+G5bI+OJWqdFC5CZQdytZiQAIlk88u7jo9Cx9IcH7G4wfLxwtDDKG77+HzNCkpwUUWSZGbplD+H58MclCyB4AaeXMc/sy7HJsPGB9wBtCbYavV9EtFJB9JAg0IT6op0xKE7gawc8mqcv8N5x+J/CGEWsHFpAZTq4uRoeGhmFE9W8fKQYylZPUWQLrVnf9XH0sEbBwk8K+ApLLap/ifS/SLqjtMvPrAqc9IpPUZL9ESTqC5EljMUB4DEAHUDRw4lI/pTP3T3urejQJg4P7KJFtNdJNJrIAUrLwRAVPlAhjKn+qoVhBoSAeuibT+L2EZxvRfAfUzWEn7e+wVKj X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 05 Aug 2026 03:30:50.5444 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 27ee0faf-b1c0-469b-f41b-08def2a1f294 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: SJ1PEPF00002324.namprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN7PPFD6BF22047 Hello Vineeth, On 8/4/2026 5:43 PM, Madadi Vineeth Reddy wrote: > Hello Prateek, > > On 04/08/26 10:19, K Prateek Nayak wrote: >> Hello Vineeth, >> >> On 8/1/2026 9:25 AM, Madadi Vineeth Reddy wrote: >>> -static int select_idle_core(struct task_struct *p, int core, struct cpumask *cpus, int *idle_cpu) >>> +static int select_idle_core(struct task_struct *p, int core, struct cpumask *cpus, >>> + int *idle_cpu, int sync_cpu) >>> { >>> bool idle = true; >>> int cpu; >>> >>> for_each_cpu(cpu, cpu_smt_mask(core)) { >>> - if (!available_idle_cpu(cpu)) { >>> + bool sync_waker = (cpu == sync_cpu); >>> + >>> + /* >>> + * @sync_cpu, if set, is running a waker that is about to >>> + * block with nothing else runnable behind it. Treat it as >>> + * idle so this core stays an idle-core candidate: placing >>> + * the wakee on a sibling keeps the cache sharing that >>> + * stacking on the waker's rq would get, without serialising >>> + * the wakee behind the waker's remaining work. >>> + */ >>> + if (!available_idle_cpu(cpu) && !sync_waker) { >> >> If I'm not wrong, all you want to make is the sync_waker appear idle and >> then see if you can then consider that core as idle core or not right? >> > > Correct. > >> Why can't this be done in select_idle_sibling() extending that early >> check for (!has_idle_core && cpus_share_cache(prev, target)) condition >> and then initializing "idle_cpu" in select_idle_cpu() accordingly? >> >> Something along the lines of: >> >> (Only build tested) >> >> diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c >> index df8c9c2c7918..dd62bceb3838 100644 >> --- a/kernel/sched/fair.c >> +++ b/kernel/sched/fair.c >> @@ -1301,7 +1301,6 @@ static bool update_deadline(struct cfs_rq *cfs_rq, struct sched_entity *se) >> >> #include "pelt.h" >> >> -static int select_idle_sibling(struct task_struct *p, int prev_cpu, int cpu); >> static unsigned long task_h_load(struct task_struct *p); >> static unsigned long capacity_of(int cpu); >> >> @@ -8661,10 +8660,11 @@ static int select_idle_smt(struct task_struct *p, struct sched_domain *sd, int t >> * comparing the average scan cost (tracked in sd->avg_scan_cost) against the >> * average idle time for this rq (as found in rq->avg_idle). >> */ >> -static int select_idle_cpu(struct task_struct *p, struct sched_domain *sd, bool has_idle_core, int target) >> +static int select_idle_cpu(struct task_struct *p, struct sched_domain *sd, bool has_idle_core, >> + int target, int idle_cpu) >> { >> struct cpumask *cpus = this_cpu_cpumask_var_ptr(select_rq_mask); >> - int i, cpu, idle_cpu = -1, nr = INT_MAX; >> + int i, cpu, nr = INT_MAX; >> >> if (sched_feat(SIS_UTIL) && sd->shared) { >> /* >> @@ -8928,7 +8928,7 @@ static inline bool asym_fits_cpu(unsigned long util, >> /* >> * Try and locate an idle core/thread in the LLC cache domain. >> */ >> -static int select_idle_sibling(struct task_struct *p, int prev, int target) >> +static int select_idle_sibling(struct task_struct *p, int prev, int target, int sync_cpu) >> { >> bool has_idle_core = false; >> struct sched_domain *sd; >> @@ -9028,16 +9028,19 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target) >> return target; >> >> if (sched_smt_active()) { >> + int cpu = ((unsigned)sync_cpu < nr_cpumask_bits) ? sync_cpu : prev; >> + >> has_idle_core = test_idle_cores(target); >> >> - if (!has_idle_core && cpus_share_cache(prev, target)) { >> - i = select_idle_smt(p, sd, prev); >> - if ((unsigned int)i < nr_cpumask_bits) >> + if (sync_cpu == target || (!has_idle_core && cpus_share_cache(prev, target))) { >> + i = select_idle_smt(p, sd, cpu); >> + >> + if (!has_idle_core && ((unsigned int)i < nr_cpumask_bits)) >> return i; >> } >> } >> >> - i = select_idle_cpu(p, sd, has_idle_core, target); >> + i = select_idle_cpu(p, sd, has_idle_core, target, i); > > `i` which is passed could be garbage value if we don't enter sched_smt_active block. > >> if ((unsigned)i < nr_cpumask_bits) >> return i; >> > > This is different from what I wanted to achieve in a couple of ways. > > - Calling `select_idle_smt()` in sync case, would only give an idle CPU in that core but doesn't > test if that core is idle. That would be lost. > - You return `i` only when `!has_idle_core`, but I wanted to return waker core given that rest of the siblings > in that waker core are idle even though there are other idle cores present in the LLC. > > I agree that this could be done in `select_idle_sibling` but with a helper function. > Something like below (build tested) > > diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c > index df8c9c2c7918..448af3c4b183 100644 > --- a/kernel/sched/fair.c > +++ b/kernel/sched/fair.c > @@ -1301,7 +1301,7 @@ static bool update_deadline(struct cfs_rq *cfs_rq, struct sched_entity *se) > > #include "pelt.h" > > -static int select_idle_sibling(struct task_struct *p, int prev_cpu, int cpu); > +static int select_idle_sibling(struct task_struct *p, int prev_cpu, int cpu, bool sync_core); Is this forward declaration necessary? I think you can remove it entirely. > static unsigned long task_h_load(struct task_struct *p); > static unsigned long capacity_of(int cpu); > > @@ -8656,6 +8656,27 @@ static int select_idle_smt(struct task_struct *p, struct sched_domain *sd, int t > return -1; > } > > +static int select_idle_sync_core(struct task_struct *p, struct sched_domain *sd, > + int target) > +{ > + int cpu, idle_sibling = -1; > + > + for_each_cpu(cpu, cpu_smt_mask(target)) { > + if (cpu == target) > + continue; > + > + if (!available_idle_cpu(cpu)) > + return -1; Reads a lot like select_idle_smt(). Perhaps you can pass "has_idle_core" hint to the same and return idle CPU early if !has_idle_core or otherwise return the first idle sibling if core is idle. That way even sync_core case is handled by the same function. You can gate the call with (sync_core || !has_idle_core) > + > + if (idle_sibling == -1 && > + cpumask_test_cpu(cpu, sched_domain_span(sd)) && > + cpumask_test_cpu(cpu, p->cpus_ptr)) > + idle_sibling = cpu; > + } > + > + return idle_sibling; > +} > + > /* > * Scan the LLC domain for idle CPUs; this is dynamically regulated by > * comparing the average scan cost (tracked in sd->avg_scan_cost) against the > @@ -8928,7 +8949,7 @@ static inline bool asym_fits_cpu(unsigned long util, > /* > * Try and locate an idle core/thread in the LLC cache domain. > */ > -static int select_idle_sibling(struct task_struct *p, int prev, int target) > +static int select_idle_sibling(struct task_struct *p, int prev, int target, bool sync_core) > { > bool has_idle_core = false; > struct sched_domain *sd; > @@ -9035,6 +9056,12 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target) > if ((unsigned int)i < nr_cpumask_bits) > return i; > } > + > + if (sync_core) { > + i = select_idle_sync_core(p, sd, target); > + if ((unsigned int)i < nr_cpumask_bits) > + return i; > + } > } > > i = select_idle_cpu(p, sd, has_idle_core, target); > @@ -9733,8 +9760,16 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int wake_flags) > return sched_balance_find_dst_cpu(sd, p, cpu, prev_cpu, sd_flag); > > /* Fast path */ > - if (wake_flags & WF_TTWU) > - return select_idle_sibling(p, prev_cpu, new_cpu); > + if (wake_flags & WF_TTWU) { > + bool sync_core = false; > + if (want_affine && sync && new_cpu == cpu) { > + struct rq *rq = cpu_rq(cpu); > + > + sync_core = (rq->nr_running - cfs_h_nr_delayed(rq)) == 1; Instead of computing this twice on wake_affine path, you can have a task flag like sched_task_hot that you just set in wake_affine_idle() before it returns early from the sync branch. You can clear it up top in select_task_rq_fair() and check it select_idle_sibling() to conditionally call select_idle_sync_core(). > + } > + > + return select_idle_sibling(p, prev_cpu, new_cpu, sync_core); > + } > > return new_cpu; > } > > This should also solve the issue raised by Zhan Xusheng and first target waker core given > that it is idle by giving exception to waker cpu. > > Thoughts? Let me give it a spin. I'll report back if I see anything unexpected. -- Thanks and Regards, Prateek