From nobody Sat Feb 7 07:25:43 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 1F73C347BA7; Mon, 5 Jan 2026 15:54:37 +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=1767628479; cv=none; b=sl60JLeK0YFLmbuOYP6JPbZPpKwqpRe+W0PtM3lFwatadjw7t5jGyW0O6Km6SvL3O9puMh8SefhGIa1690wDXUHsNE6BZ0y02keuwErG6KRGsEBqHtGBKjtabdLpq7s29+T3DfbuRxOmuSt6UVa1Bx96nc8oCtwLkH2bA3LXiMI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767628479; c=relaxed/simple; bh=RlMZj054Z2kM6A4ZRb6COpuFlxBfNpkBfwZsOLwiVjo=; h=Date:From:To:Subject:Cc:In-Reply-To:References:MIME-Version: Message-ID:Content-Type; b=BZlLq7T3COSX9N3Alquy2mtCBq0wxm/ymQY0GSlIaV+2tAkPJ3nQ8oX1+FVgxBNloFor4+dn+OwSuF04n8IdaODxl6eYnhaa0FTniTzv8mp6dc1ZbFlig/OJ7lXbEB/YrIuWkHeNg6hzCPgLwa525MDiYA0prQaaKzRYEta42Sg= 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=UbbV5Srq; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=XA3M7E+k; 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="UbbV5Srq"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="XA3M7E+k" Date: Mon, 05 Jan 2026 15:54:34 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1767628475; 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=mlc7/EBj5dmtb091qf/HTNuy2spWgSV7CH05CvYQhE4=; b=UbbV5Srq6UP+k7U7X4nvUyqtvBlwaSsNG6UdzBE1A/Z/Bi6dua6Y8QXMIMwh5zfnltlZx0 9XFyO0v71q7EXfoFjyVTkfxVOu06jwYxAMnnaKnLC9KgizmOhIWVUF2H04RVMmj5CuFMSq kDXeOqOGORMqUOInUTwNDtBLMra0E9j3VMGEPi69SzEyEtvXO1XtRDtNfVj/n2Tfkxww7Z Iq/DCIsW8YyMHA9sgq4dNy/XAeZ5TFLSxU4XT53qNBDQpyM3iD2O+8WCLUo92ID9RneAoO +gOfkvY2yqTPlkEs7x78E2q0Obgy8+gSlF74lmD5gLVENd4Nzbr1PFGsJqlEEg== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1767628475; 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=mlc7/EBj5dmtb091qf/HTNuy2spWgSV7CH05CvYQhE4=; b=XA3M7E+k/znTkKLIZ89jwPYFJ1J3DByym055bmoDAiEcpkH9AHGdIGW0EG2Giv1OUqOUzr kHmoSCrqOAogn5Bw== From: "tip-bot2 for Marco Elver" Sender: tip-bot2@linutronix.de Reply-to: linux-kernel@vger.kernel.org To: linux-tip-commits@vger.kernel.org Subject: [tip: locking/core] bit_spinlock: Support Clang's context analysis Cc: Marco Elver , "Peter Zijlstra (Intel)" , x86@kernel.org, linux-kernel@vger.kernel.org In-Reply-To: <20251219154418.3592607-14-elver@google.com> References: <20251219154418.3592607-14-elver@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-ID: <176762847461.510.2547212131548349147.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: eb7d96a13bf45f86909006a59e7855d8810f020a Gitweb: https://git.kernel.org/tip/eb7d96a13bf45f86909006a59e7855d88= 10f020a Author: Marco Elver AuthorDate: Fri, 19 Dec 2025 16:40:02 +01:00 Committer: Peter Zijlstra CommitterDate: Mon, 05 Jan 2026 16:43:30 +01:00 bit_spinlock: Support Clang's context analysis The annotations for bit_spinlock.h have simply been using "bitlock" as the token. For Sparse, that was likely sufficient in most cases. But Clang's context analysis is more precise, and we need to ensure we can distinguish different bitlocks. To do so, add a token context, and a macro __bitlock(bitnum, addr) that is used to construct unique per-bitlock tokens. Add the appropriate test. is implicitly included through other includes, and requires 2 annotations to indicate that acquisition (without release) and release (without prior acquisition) of its bitlock is intended. Signed-off-by: Marco Elver Signed-off-by: Peter Zijlstra (Intel) Link: https://patch.msgid.link/20251219154418.3592607-14-elver@google.com --- Documentation/dev-tools/context-analysis.rst | 3 +- include/linux/bit_spinlock.h | 22 +++++++++++++--- include/linux/list_bl.h | 2 +- lib/test_context-analysis.c | 26 +++++++++++++++++++- 4 files changed, 48 insertions(+), 5 deletions(-) diff --git a/Documentation/dev-tools/context-analysis.rst b/Documentation/d= ev-tools/context-analysis.rst index 6905659..b2d69fb 100644 --- a/Documentation/dev-tools/context-analysis.rst +++ b/Documentation/dev-tools/context-analysis.rst @@ -79,7 +79,8 @@ Supported Kernel Primitives ~~~~~~~~~~~~~~~~~~~~~~~~~~~ =20 Currently the following synchronization primitives are supported: -`raw_spinlock_t`, `spinlock_t`, `rwlock_t`, `mutex`, `seqlock_t`. +`raw_spinlock_t`, `spinlock_t`, `rwlock_t`, `mutex`, `seqlock_t`, +`bit_spinlock`. =20 For context locks with an initialization function (e.g., `spin_lock_init()= `), calling this function before initializing any guarded members or globals diff --git a/include/linux/bit_spinlock.h b/include/linux/bit_spinlock.h index 59e345f..7869a6e 100644 --- a/include/linux/bit_spinlock.h +++ b/include/linux/bit_spinlock.h @@ -10,12 +10,23 @@ #include /* for cpu_relax() */ =20 /* + * For static context analysis, we need a unique token for each possible b= it + * that can be used as a bit_spinlock. The easiest way to do that is to cr= eate a + * fake context that we can cast to with the __bitlock(bitnum, addr) macro + * below, which will give us unique instances for each (bit, addr) pair th= at the + * static analysis can use. + */ +context_lock_struct(__context_bitlock) { }; +#define __bitlock(bitnum, addr) (struct __context_bitlock *)(bitnum + (add= r)) + +/* * bit-based spin_lock() * * Don't use this unless you really need to: spin_lock() and spin_unlock() * are significantly faster. */ static __always_inline void bit_spin_lock(int bitnum, unsigned long *addr) + __acquires(__bitlock(bitnum, addr)) { /* * Assuming the lock is uncontended, this never enters @@ -34,13 +45,14 @@ static __always_inline void bit_spin_lock(int bitnum, u= nsigned long *addr) preempt_disable(); } #endif - __acquire(bitlock); + __acquire(__bitlock(bitnum, addr)); } =20 /* * Return true if it was acquired */ static __always_inline int bit_spin_trylock(int bitnum, unsigned long *add= r) + __cond_acquires(true, __bitlock(bitnum, addr)) { preempt_disable(); #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) @@ -49,7 +61,7 @@ static __always_inline int bit_spin_trylock(int bitnum, u= nsigned long *addr) return 0; } #endif - __acquire(bitlock); + __acquire(__bitlock(bitnum, addr)); return 1; } =20 @@ -57,6 +69,7 @@ static __always_inline int bit_spin_trylock(int bitnum, u= nsigned long *addr) * bit-based spin_unlock() */ static __always_inline void bit_spin_unlock(int bitnum, unsigned long *add= r) + __releases(__bitlock(bitnum, addr)) { #ifdef CONFIG_DEBUG_SPINLOCK BUG_ON(!test_bit(bitnum, addr)); @@ -65,7 +78,7 @@ static __always_inline void bit_spin_unlock(int bitnum, u= nsigned long *addr) clear_bit_unlock(bitnum, addr); #endif preempt_enable(); - __release(bitlock); + __release(__bitlock(bitnum, addr)); } =20 /* @@ -74,6 +87,7 @@ static __always_inline void bit_spin_unlock(int bitnum, u= nsigned long *addr) * protecting the rest of the flags in the word. */ static __always_inline void __bit_spin_unlock(int bitnum, unsigned long *a= ddr) + __releases(__bitlock(bitnum, addr)) { #ifdef CONFIG_DEBUG_SPINLOCK BUG_ON(!test_bit(bitnum, addr)); @@ -82,7 +96,7 @@ static __always_inline void __bit_spin_unlock(int bitnum,= unsigned long *addr) __clear_bit_unlock(bitnum, addr); #endif preempt_enable(); - __release(bitlock); + __release(__bitlock(bitnum, addr)); } =20 /* diff --git a/include/linux/list_bl.h b/include/linux/list_bl.h index ae1b541..df9eebe 100644 --- a/include/linux/list_bl.h +++ b/include/linux/list_bl.h @@ -144,11 +144,13 @@ static inline void hlist_bl_del_init(struct hlist_bl_= node *n) } =20 static inline void hlist_bl_lock(struct hlist_bl_head *b) + __acquires(__bitlock(0, b)) { bit_spin_lock(0, (unsigned long *)b); } =20 static inline void hlist_bl_unlock(struct hlist_bl_head *b) + __releases(__bitlock(0, b)) { __bit_spin_unlock(0, (unsigned long *)b); } diff --git a/lib/test_context-analysis.c b/lib/test_context-analysis.c index 53abea0..be0c5d4 100644 --- a/lib/test_context-analysis.c +++ b/lib/test_context-analysis.c @@ -4,6 +4,7 @@ * positive errors when compiled with Clang's context analysis. */ =20 +#include #include #include #include @@ -258,3 +259,28 @@ static void __used test_seqlock_scoped(struct test_seq= lock_data *d) (void)d->counter; } } + +struct test_bit_spinlock_data { + unsigned long bits; + int counter __guarded_by(__bitlock(3, &bits)); +}; + +static void __used test_bit_spin_lock(struct test_bit_spinlock_data *d) +{ + /* + * Note, the analysis seems to have false negatives, because it won't + * precisely recognize the bit of the fake __bitlock() token. + */ + bit_spin_lock(3, &d->bits); + d->counter++; + bit_spin_unlock(3, &d->bits); + + bit_spin_lock(3, &d->bits); + d->counter++; + __bit_spin_unlock(3, &d->bits); + + if (bit_spin_trylock(3, &d->bits)) { + d->counter++; + bit_spin_unlock(3, &d->bits); + } +}