mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Bart Van Assche <bvanassche@acm.org>
To: Peter Zijlstra <peterz@infradead.org>
Cc: Ingo Molnar <mingo@redhat.com>, Will Deacon <will@kernel.org>,
	Boqun Feng <boqun@kernel.org>, Waiman Long <longman@redhat.com>,
	linux-kernel@vger.kernel.org, Marco Elver <elver@google.com>,
	"Paul E . McKenney" <paulmck@kernel.org>,
	Christoph Hellwig <hch@lst.de>,
	Bart Van Assche <bvanassche@acm.org>,
	Andrew Morton <akpm@linux-foundation.org>,
	Nathan Chancellor <nathan@kernel.org>
Subject: [PATCH v2 08/14] lockdep: Introduce lockdep_assume_ctx_held()
Date: Mon,  9 Nov 2026 11:13:16 -0800	[thread overview]
Message-ID: <f4725746370a2251abf3cc3b2f34cf79caac32ed.1794250850.git.bvanassche@acm.org> (raw)
In-Reply-To: <cover.1794250850.git.bvanassche@acm.org>

Introduce lockdep_assume_ctx_held() and lockdep_assume_shared_ctx_held()
for code that needs to inform Clang's context analysis that a lock is
held in code paths where lock ownership cannot be proven at compile
time, e.g. because the lock is accessed through a pointer alias that
the analysis cannot resolve. Make these macros call respectively
__assume_ctx_lock() and __assume_shared_ctx_lock() and also verify at
runtime with lockdep_assert_held() or lockdep_assert_held_read() that
the lock is held. Store the macro argument in a local variable with a
unique name such that it is evaluated only once and such that nested
use of these macros does not cause shadowing. Rely on Clang's context
analysis resolving that local variable to the expression it has been
initialized with. Document both macros with kernel-doc comments,
including that __assume_ctx_lock() and __assume_shared_ctx_lock() must
be used for context locks without lockdep support, e.g. bit spinlocks
and the RCU context tokens.

Convert the lockdep_assert_held() tests in lib/test_context-analysis.c
into lockdep_assume_ctx_held() tests and add tests for
lockdep_assume_shared_ctx_held().

Prepare for removing the context assumptions from lockdep_assert_held*()
so that pre-existing lockdep_assert_held*() calls across the kernel tree
stop silencing Clang context analysis warnings in functions that lack a
__must_hold() or __must_hold_shared() annotation when
WARN_CONTEXT_ANALYSIS_ALL is enabled. Use lockdep_assume_ctx_held() and
lockdep_assume_shared_ctx_held() only in the few places in the kernel
where static analysis cannot prove lock ownership at compile time
(futex, kfence, rtmutex and Bluetooth).

Cc: Marco Elver <elver@google.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
 include/linux/lockdep.h     | 54 +++++++++++++++++++++++++++++++++++++
 lib/test_context-analysis.c | 16 +++++++++--
 2 files changed, 68 insertions(+), 2 deletions(-)

diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
index a6451ecbbe9a..23ffc5f0557c 100644
--- a/include/linux/lockdep.h
+++ b/include/linux/lockdep.h
@@ -412,6 +412,60 @@ extern int lockdep_is_held(const void *);
 
 #endif /* !LOCKDEP */
 
+#define _lockdep_assume_ctx_held(var, uniq)				\
+	do {								\
+		__auto_type uniq = (var);				\
+									\
+		__assume_ctx_lock(uniq);				\
+		lockdep_assert_held(uniq);				\
+	} while (0)
+
+/**
+ * lockdep_assume_ctx_held() - assume and verify that a context lock is held
+ * @var: context lock instance pointer
+ *
+ * Instruct the compiler's context analysis to assume that @var is held
+ * exclusively from this point on and verify at runtime with
+ * lockdep_assert_held() that @var is held. Use this macro in code paths
+ * where lock ownership cannot be proven at compile time, e.g. because the
+ * lock is accessed through an alias the analysis cannot resolve or because
+ * a function does not always require the lock, making __must_hold()
+ * inappropriate. @var is evaluated only once.
+ *
+ * @var must point at a lock object that is tracked by lockdep, i.e. that
+ * has a dep_map member. For context locks that are not tracked by lockdep,
+ * e.g. bit spinlocks and the RCU context tokens, use
+ * __assume_ctx_lock() instead.
+ */
+#define lockdep_assume_ctx_held(var)					\
+	_lockdep_assume_ctx_held(var, __UNIQUE_ID(ctx_lock))
+
+#define _lockdep_assume_shared_ctx_held(var, uniq)			\
+	do {								\
+		__auto_type uniq = (var);				\
+									\
+		__assume_shared_ctx_lock(uniq);				\
+		lockdep_assert_held_read(uniq);				\
+	} while (0)
+
+/**
+ * lockdep_assume_shared_ctx_held() - assume and verify shared lock ownership
+ * @var: context lock instance pointer
+ *
+ * Instruct the compiler's context analysis to assume that @var is held with
+ * shared access from this point on and verify at runtime with
+ * lockdep_assert_held_read() that @var is held for reading. Use this macro
+ * for reader-writer locks, e.g. rwlock_t and struct rw_semaphore, in code
+ * paths where shared lock ownership cannot be proven at compile time. @var
+ * is evaluated only once.
+ *
+ * @var must point at a lock object that is tracked by lockdep, i.e. that
+ * has a dep_map member. For context locks that are not tracked by lockdep,
+ * e.g. the RCU context tokens, use __assume_shared_ctx_lock() instead.
+ */
+#define lockdep_assume_shared_ctx_held(var)				\
+	_lockdep_assume_shared_ctx_held(var, __UNIQUE_ID(ctx_lock))
+
 #ifdef CONFIG_PROVE_LOCKING
 void lockdep_set_lock_cmp_fn(struct lockdep_map *, lock_cmp_fn, lock_print_fn);
 
diff --git a/lib/test_context-analysis.c b/lib/test_context-analysis.c
index 316f4dfcda65..022891999c9c 100644
--- a/lib/test_context-analysis.c
+++ b/lib/test_context-analysis.c
@@ -68,7 +68,7 @@ static void __used test_common_helpers(void)
 	}											\
 	static void __used test_##class##_assert(struct test_##class##_data *d)			\
 	{											\
-		lockdep_assert_held(&d->lock);							\
+		lockdep_assume_ctx_held(&d->lock);						\
 		op(d->counter);									\
 	}											\
 	static void __used test_##class##_guard(struct test_##class##_data *d)			\
@@ -156,6 +156,12 @@ TEST_SPINLOCK_COMMON(read_lock,
 		     read_trylock,
 		     TEST_OP_RO);
 
+static void __used test_read_lock_assert_shared(struct test_read_lock_data *d)
+{
+	lockdep_assume_shared_ctx_held(&d->lock);
+	TEST_OP_RO(d->counter);
+}
+
 struct test_mutex_data {
 	struct mutex mtx;
 	int counter __guarded_by(&mtx);
@@ -203,7 +209,7 @@ static void __used test_mutex_trylock(struct test_mutex_data *d, atomic_t *a)
 
 static void __used test_mutex_assert(struct test_mutex_data *d)
 {
-	lockdep_assert_held(&d->mtx);
+	lockdep_assume_ctx_held(&d->mtx);
 	d->counter++;
 }
 
@@ -339,6 +345,12 @@ static void __used test_rwsem_assert(struct test_rwsem_data *d)
 	d->counter++;
 }
 
+static void __used test_rwsem_assert_shared(struct test_rwsem_data *d)
+{
+	lockdep_assume_shared_ctx_held(&d->sem);
+	(void)d->counter;
+}
+
 static void __used test_rwsem_guard(struct test_rwsem_data *d)
 {
 	{ guard(rwsem_read)(&d->sem); (void)d->counter; }

  parent reply	other threads:[~2026-11-09 19:14 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-09 19:13 [PATCH v2 00/14] Stop lockdep_assert_held*() from assuming lock ownership Bart Van Assche
2026-11-09 19:13 ` [PATCH v2 01/14] bit_spinlock: Fix the __bitlock() definition Bart Van Assche
2026-11-09 19:13 ` [PATCH v2 02/14] cleanup: Disable context analysis for __free() helpers Bart Van Assche
2026-11-09 19:13 ` [PATCH v2 03/14] tracing: Disable branch profiling for COMPILE_TEST builds Bart Van Assche
2026-11-09 19:13 ` [PATCH v2 04/14] srcu: Remove check from srcu_dereference_check() Bart Van Assche
2026-11-09 19:13 ` [PATCH v2 05/14] futex: Annotate __attach_to_pi_owner() and fixup_pi_*owner() Bart Van Assche
2026-11-09 19:13 ` [PATCH v2 06/14] locking/rwsem: Annotate rwsem internal functions with __must_hold() Bart Van Assche
2026-11-09 19:13 ` [PATCH v2 07/14] nvme-fabrics: Annotate nvmf_lookup_transport() with __must_hold_shared() Bart Van Assche
2026-11-09 19:13 ` Bart Van Assche [this message]
2026-11-09 19:13 ` [PATCH v2 09/14] kfence: Use lockdep_assume_ctx_held() in kfence_report_error() Bart Van Assche
2026-11-09 19:13 ` [PATCH v2 10/14] Bluetooth: Add lock context annotations for connection aliases Bart Van Assche
2026-11-09 19:13 ` [PATCH v2 11/14] futex: Verify exit_mutex ownership in futex_exit_recursive() Bart Van Assche
2026-11-09 19:13 ` [PATCH v2 12/14] lockdep: Stop lockdep_assert_held*() from assuming lock ownership Bart Van Assche
2026-11-09 19:13 ` [PATCH v2 13/14] compiler-context-analysis: Split the RCU assertion tests Bart Van Assche
2026-11-09 19:13 ` [PATCH v2 14/14] rcu: Introduce lockdep_assume_in_rcu_*() Bart Van Assche

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=f4725746370a2251abf3cc3b2f34cf79caac32ed.1794250850.git.bvanassche@acm.org \
    --to=bvanassche@acm.org \
    --cc=akpm@linux-foundation.org \
    --cc=boqun@kernel.org \
    --cc=elver@google.com \
    --cc=hch@lst.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=longman@redhat.com \
    --cc=mingo@redhat.com \
    --cc=nathan@kernel.org \
    --cc=paulmck@kernel.org \
    --cc=peterz@infradead.org \
    --cc=will@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®