From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from canpmsgout09.his.huawei.com (canpmsgout09.his.huawei.com [113.46.200.224]) (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 A58EE3E49D1 for ; Wed, 5 Aug 2026 08:00:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.224 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785916837; cv=none; b=FW06PXnSjbPzPVzgKG4sgrkPawNWhOmMueKYOLUb4ClhAhdZrLL5sad+n7dNpVvJtsxvyvuHhnITetPqc0jyqzxpxbJpTkWl6aTAGrBTmBc1pCRSXOb88zBLtk1/M4TLleAx2R5OqjUC8VIsOFARA1iyLzwRnvSqxgKdiYBkVQI= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785916837; c=relaxed/simple; bh=wnOtwgYlFzpQO++UxLeTlcHbds4WJ5SZF2yJI1Kpjr0=; h=Message-ID:Date:MIME-Version:Subject:To:CC:References:From: In-Reply-To:Content-Type; b=L0MqwOkP2cWar0NNrKO8a1WyyDW/rawgTEQBthJm3CAE//B7ZUmCJmOQEm6aZF0OAeNvahb04tehMYNG5yHQ++tgpavnj53R4YKisSc9liPkUQoAwwIAj9+gtEgvS54VJULa7q/c9SD6pa/KefgsCDyZfmkKu+qL2LSh8HorWjQ= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=NCG77q3Z; arc=none smtp.client-ip=113.46.200.224 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="NCG77q3Z" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=qv960yiXaNfopDFMQAJarhydyxY3R9s/rZAMeZ3PiIs=; b=NCG77q3Z3AXdquYQhRbqwkts8RkvH4hI85P2yaWJSPaS60m06AwCBh/GUarqxJplkktLs1NA4 /5Z2A++3nemfXT8bo12TbN3D+ng0BTSXp9WOMgPN//Ex+JFlEnBW07uCT4X66uWBWduiEm0OyKF tfNHuOoFo3cx7RrLhIP8Hz4= Received: from mail.maildlp.com (unknown [172.19.162.92]) by canpmsgout09.his.huawei.com (SkyGuard) with ESMTPS id 4hFMzH3mcvz1cyPY; Wed, 5 Aug 2026 15:50:51 +0800 (CST) Received: from dggpemr500006.china.huawei.com (unknown [7.185.36.185]) by mail.maildlp.com (Postfix) with ESMTPS id 6DA9540565; Wed, 5 Aug 2026 16:00:21 +0800 (CST) Received: from [100.103.109.15] (100.103.109.15) by dggpemr500006.china.huawei.com (7.185.36.185) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.45; Wed, 5 Aug 2026 16:00:20 +0800 Message-ID: <89bceee9-a68e-4d76-981e-0dd797988d09@huawei.com> Date: Wed, 5 Aug 2026 16:00:19 +0800 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 v2 1/2] futex/requeue: Fix rtmutex schedule preparation for requeue PI To: Peter Zijlstra CC: , , , , , , , References: <20260722085140.1949077-1-yaokai34@huawei.com> <20260722085140.1949077-2-yaokai34@huawei.com> <20260804122102.GI776954@noisy.programming.kicks-ass.net> Content-Language: en-US From: Yao Kai In-Reply-To: <20260804122102.GI776954@noisy.programming.kicks-ass.net> Content-Type: text/plain; charset="UTF-8"; format=flowed Content-Transfer-Encoding: 7bit X-ClientProxiedBy: kwepems500001.china.huawei.com (7.221.188.70) To dggpemr500006.china.huawei.com (7.185.36.185) On 8/4/2026 8:21 PM, Peter Zijlstra wrote: > On Wed, Jul 22, 2026 at 04:51:39PM +0800, Yao Kai wrote: >> A waiter requeued onto a PI futex can reach rt_mutex_wait_proxy_lock() >> without rtmutex schedule preparation: >> >> WARNING: CPU: 0 PID: 293 at kernel/sched/core.c:7606 >> RIP: rt_mutex_schedule+0x43/0x50 >> Call Trace: >> rt_mutex_slowlock_block.constprop.0+0x5b/0x320 >> rt_mutex_wait_proxy_lock+0x3e/0x80 >> futex_wait_requeue_pi+0x3ba/0x590 >> do_futex+0x171/0x1f0 >> >> rt_mutex_schedule() requires current->sched_rt_mutex to be set. Normally, >> rt_mutex_pre_schedule() sets it before an rtmutex waiter can schedule. With >> requeue PI, another task can enqueue the waiter after its futex_q becomes >> visible: >> >> waiter requeue task >> ------ ------------ >> futex_wait_requeue_pi() >> futex_wait_setup() >> futex_queue(&q) >> futex_requeue() >> rt_mutex_start_proxy_lock() >> enqueue rt_waiter >> install pi_blocked_on >> requeue_futex() >> plist_del(&q->list) >> futex_do_wait() >> plist_node_empty(&q->list) >> skip schedule() >> plist_add(&q->list) >> futex_requeue_pi_complete() >> IN_PROGRESS -> DONE >> futex_requeue_pi_wakeup_sync() // DONE >> rt_mutex_wait_proxy_lock() >> rt_mutex_schedule() >> >> futex_do_wait() mistakes the temporary removal for a wakeup and skips >> schedule(). The proxy waiter can nevertheless remain blocked on the target >> rtmutex and subsequently enter rt_mutex_schedule() with >> current->sched_rt_mutex clear. >> >> Call rt_mutex_pre_schedule() and rt_mutex_post_schedule() directly around >> rt_mutex_wait_proxy_lock() so this second blocking point has the required >> scheduler preparation. >> >> Fixes: d14f9e930b90 ("locking/rtmutex: Use rt_mutex specific scheduler helpers") >> Suggested-by: Sebastian Andrzej Siewior >> Cc: stable@vger.kernel.org >> Signed-off-by: Yao Kai >> --- >> kernel/futex/requeue.c | 8 ++++++++ >> 1 file changed, 8 insertions(+) >> >> diff --git a/kernel/futex/requeue.c b/kernel/futex/requeue.c >> index 79823ad13683..f7889fb2fce4 100644 >> --- a/kernel/futex/requeue.c >> +++ b/kernel/futex/requeue.c >> @@ -1,6 +1,7 @@ >> // SPDX-License-Identifier: GPL-2.0-or-later >> >> #include >> +#include >> #include >> >> #include "futex.h" >> @@ -865,7 +866,14 @@ int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags, >> case Q_REQUEUE_PI_DONE: >> /* Requeue completed. Current is 'pi_blocked_on' the rtmutex */ >> pi_mutex = &q.pi_state->pi_mutex; >> + /* >> + * Requeue temporarily removes q from the hash bucket, so >> + * futex_do_wait() may skip schedule() even though the proxy >> + * waiter still has to block on the rtmutex. >> + */ >> + rt_mutex_pre_schedule(); >> ret = rt_mutex_wait_proxy_lock(pi_mutex, to, &rt_waiter); >> + rt_mutex_post_schedule(); > > As per always, I'm totally confused about everything. I mean, futexes > suck, but requeue sucks worse. > > So the purpose of rt_mutex_pre_schedule() was to avoid the double waiter > enqueue for rt_mutex on RT, where sched_submit_work() will hit a > spinlock-nee-rtlock. > > So rt_mutex_pre_schedule() must happen before the rt_mutex is added as a > waiter. However, AFAICT we're already a waiter at the above spot, no? So > this cannot be right. > > The changelogs doesn't at all explain why this is correct. Please help? You are right that rt_mutex_pre_schedule() is normally required before the rtmutex waiter is enqueued. The v2 placement relies on a property of this particular call path that I failed to explain in the changelog: futex_wait_requeue_pi() is reachable only via the FUTEX_WAIT_REQUEUE_PI syscall from userspace. Therefore, 'current' cannot be a workqueue/io-wq worker, nor can it carry a live block plug across the syscall boundary. Consequently, sched_submit_work() inside rt_mutex_pre_schedule() has no pending plugged I/O or worker notifications to process here, so it cannot recurse into an rtlock after the proxy waiter has been installed. In this specific path, calling rt_mutex_pre_schedule() here effectively only sets current->sched_rt_mutex before rt_mutex_wait_proxy_lock() calls rt_mutex_schedule(), without executing any blocking submit_work after enqueue. This was the rationale for adopting Sebastian's simpler suggestion from the v1 discussion, but this essential invariant was omitted from the v2 changelog and code comments. Thanks, Yao Kai