From nobody Mon Apr 6 19:59:13 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 E1EC3378D87; Wed, 18 Mar 2026 08:02:56 +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=1773820980; cv=none; b=Twi1HJx+K4zqyVTUyd35RHg7QZYMIbHA2q9MTDGSYqTwX1zP340X/rUjQpr6gLmXI/3/3ywrRPnFN5PNGBbEHRYX9kMLi/cb+J05kBtdIOGSEC3sgJsc6kIaFW81tezf+h/w1t0Anli2MwHPokahuA/Z4Pfvdr43tRQilajKoO8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773820980; c=relaxed/simple; bh=S8jMsEVNsF2rKiAB474KTmsW64By5dUhEllHg4YUt+M=; h=Date:From:To:Subject:Cc:In-Reply-To:References:MIME-Version: Message-ID:Content-Type; b=UHoU/T0B9QCOhkUmtxvsoaNfLqSfh0zRLpy2Loll/GC8UFDn3qFooA3m2fJTkN4SJ/Uoqg2s8cj1sATB6ocNcaZNa0a2DoAWhzVvn7caDrRLZCawEuGLa1ASkVtV1lB9z3y5s4dQk7Dl4lWC8NTjlomUUHSbVGUXs4brO7EPe/Y= 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=jsoVK00Z; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=XqQVqP/9; 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="jsoVK00Z"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="XqQVqP/9" Date: Wed, 18 Mar 2026 08:02:54 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1773820975; 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=KqPqC/Flhwvm4wVsPRhCcovfYMFTfS8y1XP0dZKZOMM=; b=jsoVK00ZHCykM+DMDlT22jh7hoPSVhrF/U6ZTJrHGY7fpFQWme0tM4C9E9/8gTP2OnaQNc aLrBTZjLuV11HZdYC75e4aCJwOH16lmcs9a56T3z5s4v2vb7RpCal7Bn8dx81YRA1/WnOF O3QqKR0B2OoGa1lzhLDJtZqAazJCvkJocvSdbL6sADzSNYZqtDDPpcBhvNSBfl9Yb1xvm7 nW5mM7tfKyBPGmQ5Xx5RYVI7Y+K9EDc3TspQd8EZiVMGmXj3xTNO0Ubzs+nCtOYrinQy7H hcvZ2F+P1v4E1YbeeVmCLdnCMtjVyfvLaJ6y8CifLnFhUQBb/zg8BOfTcQp1jQ== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1773820975; 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=KqPqC/Flhwvm4wVsPRhCcovfYMFTfS8y1XP0dZKZOMM=; b=XqQVqP/9Aj+tvoPo4SOIaECMq1ZMeInWT55J0sBHFBHEN5/syvhz+pLf0uvCxeFqm/Xdkw 8ERUD3LmDaynmWAg== From: "tip-bot2 for Peter Zijlstra" Sender: tip-bot2@linutronix.de Reply-to: linux-kernel@vger.kernel.org To: linux-tip-commits@vger.kernel.org Subject: [tip: locking/core] futex: Convert to compiler context analysis Cc: "Peter Zijlstra (Intel)" , x86@kernel.org, linux-kernel@vger.kernel.org In-Reply-To: <20260121111213.950376128@infradead.org> References: <20260121111213.950376128@infradead.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-ID: <177382097436.1647592.3592886721261987588.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 locking/core branch of tip: Commit-ID: 16df04446e34a1e7dba57f657af6ad5f51199763 Gitweb: https://git.kernel.org/tip/16df04446e34a1e7dba57f657af6ad5f5= 1199763 Author: Peter Zijlstra AuthorDate: Wed, 14 Jan 2026 12:08:28 +01:00 Committer: Peter Zijlstra CommitterDate: Mon, 16 Mar 2026 13:16:48 +01:00 futex: Convert to compiler context analysis Convert the sparse annotations over to the new compiler context analysis stuff. Signed-off-by: Peter Zijlstra (Intel) Link: https://patch.msgid.link/20260121111213.950376128@infradead.org --- kernel/futex/Makefile | 2 ++ kernel/futex/core.c | 9 ++++++--- kernel/futex/futex.h | 17 ++++++++++++++--- kernel/futex/pi.c | 9 +++++++++ kernel/futex/waitwake.c | 4 ++++ 5 files changed, 35 insertions(+), 6 deletions(-) diff --git a/kernel/futex/Makefile b/kernel/futex/Makefile index b77188d..dce70f8 100644 --- a/kernel/futex/Makefile +++ b/kernel/futex/Makefile @@ -1,3 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 =20 +CONTEXT_ANALYSIS :=3D y + obj-y +=3D core.o syscalls.o pi.o requeue.o waitwake.o diff --git a/kernel/futex/core.c b/kernel/futex/core.c index cf7e610..4bacf55 100644 --- a/kernel/futex/core.c +++ b/kernel/futex/core.c @@ -864,7 +864,6 @@ void __futex_unqueue(struct futex_q *q) =20 /* The key must be already stored in q->key. */ void futex_q_lock(struct futex_q *q, struct futex_hash_bucket *hb) - __acquires(&hb->lock) { /* * Increment the counter before taking the lock so that @@ -879,10 +878,10 @@ void futex_q_lock(struct futex_q *q, struct futex_has= h_bucket *hb) q->lock_ptr =3D &hb->lock; =20 spin_lock(&hb->lock); + __acquire(q->lock_ptr); } =20 void futex_q_unlock(struct futex_hash_bucket *hb) - __releases(&hb->lock) { futex_hb_waiters_dec(hb); spin_unlock(&hb->lock); @@ -1443,12 +1442,15 @@ static void futex_cleanup(struct task_struct *tsk) void futex_exit_recursive(struct task_struct *tsk) { /* If the state is FUTEX_STATE_EXITING then futex_exit_mutex is held */ - if (tsk->futex_state =3D=3D FUTEX_STATE_EXITING) + if (tsk->futex_state =3D=3D FUTEX_STATE_EXITING) { + __assume_ctx_lock(&tsk->futex_exit_mutex); mutex_unlock(&tsk->futex_exit_mutex); + } tsk->futex_state =3D FUTEX_STATE_DEAD; } =20 static void futex_cleanup_begin(struct task_struct *tsk) + __acquires(&tsk->futex_exit_mutex) { /* * Prevent various race issues against a concurrent incoming waiter @@ -1475,6 +1477,7 @@ static void futex_cleanup_begin(struct task_struct *t= sk) } =20 static void futex_cleanup_end(struct task_struct *tsk, int state) + __releases(&tsk->futex_exit_mutex) { /* * Lockless store. The only side effect is that an observer might diff --git a/kernel/futex/futex.h b/kernel/futex/futex.h index 30c2afa..9f6bf6f 100644 --- a/kernel/futex/futex.h +++ b/kernel/futex/futex.h @@ -217,7 +217,7 @@ enum futex_access { =20 extern int get_futex_key(u32 __user *uaddr, unsigned int flags, union fute= x_key *key, enum futex_access rw); -extern void futex_q_lockptr_lock(struct futex_q *q); +extern void futex_q_lockptr_lock(struct futex_q *q) __acquires(q->lock_ptr= ); extern struct hrtimer_sleeper * futex_setup_timer(ktime_t *time, struct hrtimer_sleeper *timeout, int flags, u64 range_ns); @@ -311,9 +311,11 @@ extern int futex_unqueue(struct futex_q *q); static inline void futex_queue(struct futex_q *q, struct futex_hash_bucket= *hb, struct task_struct *task) __releases(&hb->lock) + __releases(q->lock_ptr) { __futex_queue(q, hb, task); spin_unlock(&hb->lock); + __release(q->lock_ptr); } =20 extern void futex_unqueue_pi(struct futex_q *q); @@ -358,9 +360,12 @@ static inline int futex_hb_waiters_pending(struct fute= x_hash_bucket *hb) #endif } =20 -extern void futex_q_lock(struct futex_q *q, struct futex_hash_bucket *hb); -extern void futex_q_unlock(struct futex_hash_bucket *hb); +extern void futex_q_lock(struct futex_q *q, struct futex_hash_bucket *hb) + __acquires(&hb->lock) + __acquires(q->lock_ptr); =20 +extern void futex_q_unlock(struct futex_hash_bucket *hb) + __releases(&hb->lock); =20 extern int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucke= t *hb, union futex_key *key, @@ -379,6 +384,9 @@ extern int fixup_pi_owner(u32 __user *uaddr, struct fut= ex_q *q, int locked); */ static inline void double_lock_hb(struct futex_hash_bucket *hb1, struct futex_hash_bucket *hb= 2) + __acquires(&hb1->lock) + __acquires(&hb2->lock) + __no_context_analysis { if (hb1 > hb2) swap(hb1, hb2); @@ -390,6 +398,9 @@ double_lock_hb(struct futex_hash_bucket *hb1, struct fu= tex_hash_bucket *hb2) =20 static inline void double_unlock_hb(struct futex_hash_bucket *hb1, struct futex_hash_bucket *= hb2) + __releases(&hb1->lock) + __releases(&hb2->lock) + __no_context_analysis { spin_unlock(&hb1->lock); if (hb1 !=3D hb2) diff --git a/kernel/futex/pi.c b/kernel/futex/pi.c index bc1f7e8..49ab5f4 100644 --- a/kernel/futex/pi.c +++ b/kernel/futex/pi.c @@ -389,6 +389,7 @@ static void __attach_to_pi_owner(struct task_struct *p,= union futex_key *key, * Initialize the pi_mutex in locked state and make @p * the owner of it: */ + __assume_ctx_lock(&pi_state->pi_mutex.wait_lock); rt_mutex_init_proxy_locked(&pi_state->pi_mutex, p); =20 /* Store the key for possible exit cleanups: */ @@ -614,6 +615,8 @@ int futex_lock_pi_atomic(u32 __user *uaddr, struct fute= x_hash_bucket *hb, static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_pi_state *pi_state, struct rt_mutex_waiter *top_waiter) + __must_hold(&pi_state->pi_mutex.wait_lock) + __releases(&pi_state->pi_mutex.wait_lock) { struct task_struct *new_owner; bool postunlock =3D false; @@ -670,6 +673,8 @@ out_unlock: =20 static int __fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, struct task_struct *argowner) + __must_hold(&q->pi_state->pi_mutex.wait_lock) + __must_hold(q->lock_ptr) { struct futex_pi_state *pi_state =3D q->pi_state; struct task_struct *oldowner, *newowner; @@ -966,6 +971,7 @@ retry_private: * - EAGAIN: The user space value changed. */ futex_q_unlock(hb); + __release(q.lock_ptr); /* * Handle the case where the owner is in the middle of * exiting. Wait for the exit to complete otherwise @@ -1090,6 +1096,7 @@ no_block: if (res) ret =3D (res < 0) ? res : 0; =20 + __release(&hb->lock); futex_unqueue_pi(&q); spin_unlock(q.lock_ptr); if (q.drop_hb_ref) { @@ -1101,10 +1108,12 @@ no_block: =20 out_unlock_put_key: futex_q_unlock(hb); + __release(q.lock_ptr); goto out; =20 uaddr_faulted: futex_q_unlock(hb); + __release(q.lock_ptr); =20 ret =3D fault_in_user_writeable(uaddr); if (ret) diff --git a/kernel/futex/waitwake.c b/kernel/futex/waitwake.c index 1c2dd03..ceed9d8 100644 --- a/kernel/futex/waitwake.c +++ b/kernel/futex/waitwake.c @@ -462,6 +462,7 @@ retry: } =20 futex_q_unlock(hb); + __release(q->lock_ptr); } __set_current_state(TASK_RUNNING); =20 @@ -628,6 +629,7 @@ retry_private: =20 if (ret) { futex_q_unlock(hb); + __release(q->lock_ptr); =20 ret =3D get_user(uval, uaddr); if (ret) @@ -641,11 +643,13 @@ retry_private: =20 if (uval !=3D val) { futex_q_unlock(hb); + __release(q->lock_ptr); return -EWOULDBLOCK; } =20 if (key2 && futex_match(&q->key, key2)) { futex_q_unlock(hb); + __release(q->lock_ptr); return -EINVAL; } =20