From nobody Sun Jun 14 15:53:27 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (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 1F5EF38A717; Fri, 3 Apr 2026 12:30:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775219414; cv=none; b=Z/D48uGgehTn2d3tdzEjtjgLXwVsetDWvLBJLyikKlBlC1ziENuENgXFq92c6TOK6jlKpFpvU4ifYnSZdlHV7RrkYJbgagzmjIJhtpav4RpGnFyQH9+j3pMYaJQQwucMvuQ5Ert0mvGXmFEDto8/w1N5V7o/wxSummLnb/5x+ZY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775219414; c=relaxed/simple; bh=dSywYRWLz7ZhEWvth1SavteTEC9YwT2MHQubSOSe+zY=; h=Date:From:To:Subject:Cc:In-Reply-To:References:MIME-Version: Message-ID:Content-Type; b=tZgGOOB6w4tTQQ73Fk6Wabywj1T85nA+Sa2EkBsKX7ze/fTn9/lVONCxF0EBrditGdpEgVB4SGJAPGr+7tBv+eaMtwp/K6yIuoNd7ztFLOm0XtrcAssCVV1TVFE76rDdtKsTa8STDwZQSV7UI4PvUGLGV2puboPBPR4HbDTxEEQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=onpQMeP+; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=QPr+b4YZ; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="onpQMeP+"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="QPr+b4YZ" Date: Fri, 03 Apr 2026 12:30:09 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1775219411; h=from:from:sender:sender:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=XdoH7u91IffrNsmLEXuBf9zuHn5go6eQARm8ZtaddQ0=; b=onpQMeP+9VvsXjpTV1lw+rvNTzlDCcZD6w+FdEirYq29ZQfG9H+k1MolEMLvMEB07x0OkW wT4nyDbJpITCQy86axwcaHGAvlVvjN9w34QPrPb70UAgiPS2diN+xCu2LLVYGZ3b9nuJL5 jo+M3GzCMjwcrIT/Jtv0wmuOhdgBNOsESZFx4Ud1k4zlrsweGkvx9ht35hbQuJBRVGaaS9 E5q32E9T/j2qH4ZSptr9rzowr9f2Bo/XQRRunH3HagwJndIYe6ffmCudqt/6koowII7Ouz ShYESWWZBCZ/rnD3gMTMzV+e/5XUEwnBFbVbmcHW5miyRvARQiT2jDIn+H6sTQ== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1775219411; h=from:from:sender:sender:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=XdoH7u91IffrNsmLEXuBf9zuHn5go6eQARm8ZtaddQ0=; b=QPr+b4YZrBOZ5T0yMuUbQlb9SUIpZbow7nV/ZyBVsV9TgSGlRxkzZTrIDiFgSnJnu2rDRH zA2oNlEsUioKQcAg== From: "tip-bot2 for John Stultz" Sender: tip-bot2@linutronix.de Reply-to: linux-kernel@vger.kernel.org To: linux-tip-commits@vger.kernel.org Subject: [tip: sched/core] sched: Add logic to zap balance callbacks if we pick again Cc: John Stultz , "Peter Zijlstra (Intel)" , K Prateek Nayak , x86@kernel.org, linux-kernel@vger.kernel.org In-Reply-To: <20260324191337.1841376-9-jstultz@google.com> References: <20260324191337.1841376-9-jstultz@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-ID: <177521940987.1647592.511257665998418890.tip-bot2@tip-bot2> Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails Precedence: bulk Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable The following commit has been merged into the sched/core branch of tip: Commit-ID: 48fda62de67a1e88fc8bada12caf0fc9b45116df Gitweb: https://git.kernel.org/tip/48fda62de67a1e88fc8bada12caf0fc9b= 45116df Author: John Stultz AuthorDate: Tue, 24 Mar 2026 19:13:23=20 Committer: Peter Zijlstra CommitterDate: Fri, 03 Apr 2026 14:23:40 +02:00 sched: Add logic to zap balance callbacks if we pick again With proxy-exec, a task is selected to run via pick_next_task(), and then if it is a mutex blocked task, we call find_proxy_task() to find a runnable owner. If the runnable owner is on another cpu, we will need to migrate the selected donor task away, after which we will pick_again can call pick_next_task() to choose something else. However, in the first call to pick_next_task(), we may have had a balance_callback setup by the class scheduler. After we pick again, its possible pick_next_task_fair() will be called which calls sched_balance_newidle() and sched_balance_rq(). This will throw a warning: [ 8.796467] rq->balance_callback && rq->balance_callback !=3D &balance_p= ush_callback [ 8.796467] WARNING: CPU: 32 PID: 458 at kernel/sched/sched.h:1750 sched= _balance_rq+0xe92/0x1250 ... [ 8.796467] Call Trace: [ 8.796467] [ 8.796467] ? __warn.cold+0xb2/0x14e [ 8.796467] ? sched_balance_rq+0xe92/0x1250 [ 8.796467] ? report_bug+0x107/0x1a0 [ 8.796467] ? handle_bug+0x54/0x90 [ 8.796467] ? exc_invalid_op+0x17/0x70 [ 8.796467] ? asm_exc_invalid_op+0x1a/0x20 [ 8.796467] ? sched_balance_rq+0xe92/0x1250 [ 8.796467] sched_balance_newidle+0x295/0x820 [ 8.796467] pick_next_task_fair+0x51/0x3f0 [ 8.796467] __schedule+0x23a/0x14b0 [ 8.796467] ? lock_release+0x16d/0x2e0 [ 8.796467] schedule+0x3d/0x150 [ 8.796467] worker_thread+0xb5/0x350 [ 8.796467] ? __pfx_worker_thread+0x10/0x10 [ 8.796467] kthread+0xee/0x120 [ 8.796467] ? __pfx_kthread+0x10/0x10 [ 8.796467] ret_from_fork+0x31/0x50 [ 8.796467] ? __pfx_kthread+0x10/0x10 [ 8.796467] ret_from_fork_asm+0x1a/0x30 [ 8.796467] This is because if a RT task was originally picked, it will setup the rq->balance_callback with push_rt_tasks() via set_next_task_rt(). Once the task is migrated away and we pick again, we haven't processed any balance callbacks, so rq->balance_callback is not in the same state as it was the first time pick_next_task was called. To handle this, add a zap_balance_callbacks() helper function which cleans up the balance callbacks without running them. This should be ok, as we are effectively undoing the state set in the first call to pick_next_task(), and when we pick again, the new callback can be configured for the donor task actually selected. Signed-off-by: John Stultz Signed-off-by: Peter Zijlstra (Intel) Reviewed-by: K Prateek Nayak Link: https://patch.msgid.link/20260324191337.1841376-9-jstultz@google.com --- kernel/sched/core.c | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index acb5894..162b24c 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -4917,6 +4917,34 @@ static inline void finish_task(struct task_struct *p= rev) smp_store_release(&prev->on_cpu, 0); } =20 +/* + * Only called from __schedule context + * + * There are some cases where we are going to re-do the action + * that added the balance callbacks. We may not be in a state + * where we can run them, so just zap them so they can be + * properly re-added on the next time around. This is similar + * handling to running the callbacks, except we just don't call + * them. + */ +static void zap_balance_callbacks(struct rq *rq) +{ + struct balance_callback *next, *head; + bool found =3D false; + + lockdep_assert_rq_held(rq); + + head =3D rq->balance_callback; + while (head) { + if (head =3D=3D &balance_push_callback) + found =3D true; + next =3D head->next; + head->next =3D NULL; + head =3D next; + } + rq->balance_callback =3D found ? &balance_push_callback : NULL; +} + static void do_balance_callbacks(struct rq *rq, struct balance_callback *h= ead) { void (*func)(struct rq *rq); @@ -6862,10 +6890,14 @@ pick_again: rq_set_donor(rq, next); if (unlikely(next->blocked_on)) { next =3D find_proxy_task(rq, next, &rf); - if (!next) + if (!next) { + zap_balance_callbacks(rq); goto pick_again; - if (next =3D=3D rq->idle) + } + if (next =3D=3D rq->idle) { + zap_balance_callbacks(rq); goto keep_resched; + } } if (rq->donor =3D=3D prev_donor && prev !=3D next) { struct task_struct *donor =3D rq->donor;