summaryrefslogtreecommitdiff
path: root/lib/test_context-analysis.c
diff options
context:
space:
mode:
authorMarco Elver <elver@google.com>2025-12-19 16:40:08 +0100
committerPeter Zijlstra <peterz@infradead.org>2026-01-05 16:43:31 +0100
commitd3febf16dee28a74b01ba43195ee4965edb6208f (patch)
tree2363a4c04c89d9c7a358fce9b4f25b3b961bc5a4 /lib/test_context-analysis.c
parent8c9c8566e139c0f1398245fbe3aa409fc1a79da8 (diff)
locking/local_lock: Support Clang's context analysis
Add support for Clang's context analysis for local_lock_t and local_trylock_t. Signed-off-by: Marco Elver <elver@google.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://patch.msgid.link/20251219154418.3592607-20-elver@google.com
Diffstat (limited to 'lib/test_context-analysis.c')
-rw-r--r--lib/test_context-analysis.c73
1 files changed, 73 insertions, 0 deletions
diff --git a/lib/test_context-analysis.c b/lib/test_context-analysis.c
index 1c96c56cf873..003e64cac540 100644
--- a/lib/test_context-analysis.c
+++ b/lib/test_context-analysis.c
@@ -6,7 +6,9 @@
#include <linux/bit_spinlock.h>
#include <linux/build_bug.h>
+#include <linux/local_lock.h>
#include <linux/mutex.h>
+#include <linux/percpu.h>
#include <linux/rcupdate.h>
#include <linux/rwsem.h>
#include <linux/seqlock.h>
@@ -458,3 +460,74 @@ static void __used test_srcu_guard(struct test_srcu_data *d)
{ guard(srcu_fast)(&d->srcu); (void)srcu_dereference(d->data, &d->srcu); }
{ guard(srcu_fast_notrace)(&d->srcu); (void)srcu_dereference(d->data, &d->srcu); }
}
+
+struct test_local_lock_data {
+ local_lock_t lock;
+ int counter __guarded_by(&lock);
+};
+
+static DEFINE_PER_CPU(struct test_local_lock_data, test_local_lock_data) = {
+ .lock = INIT_LOCAL_LOCK(lock),
+};
+
+static void __used test_local_lock_init(struct test_local_lock_data *d)
+{
+ local_lock_init(&d->lock);
+ d->counter = 0;
+}
+
+static void __used test_local_lock(void)
+{
+ unsigned long flags;
+
+ local_lock(&test_local_lock_data.lock);
+ this_cpu_add(test_local_lock_data.counter, 1);
+ local_unlock(&test_local_lock_data.lock);
+
+ local_lock_irq(&test_local_lock_data.lock);
+ this_cpu_add(test_local_lock_data.counter, 1);
+ local_unlock_irq(&test_local_lock_data.lock);
+
+ local_lock_irqsave(&test_local_lock_data.lock, flags);
+ this_cpu_add(test_local_lock_data.counter, 1);
+ local_unlock_irqrestore(&test_local_lock_data.lock, flags);
+
+ local_lock_nested_bh(&test_local_lock_data.lock);
+ this_cpu_add(test_local_lock_data.counter, 1);
+ local_unlock_nested_bh(&test_local_lock_data.lock);
+}
+
+static void __used test_local_lock_guard(void)
+{
+ { guard(local_lock)(&test_local_lock_data.lock); this_cpu_add(test_local_lock_data.counter, 1); }
+ { guard(local_lock_irq)(&test_local_lock_data.lock); this_cpu_add(test_local_lock_data.counter, 1); }
+ { guard(local_lock_irqsave)(&test_local_lock_data.lock); this_cpu_add(test_local_lock_data.counter, 1); }
+ { guard(local_lock_nested_bh)(&test_local_lock_data.lock); this_cpu_add(test_local_lock_data.counter, 1); }
+}
+
+struct test_local_trylock_data {
+ local_trylock_t lock;
+ int counter __guarded_by(&lock);
+};
+
+static DEFINE_PER_CPU(struct test_local_trylock_data, test_local_trylock_data) = {
+ .lock = INIT_LOCAL_TRYLOCK(lock),
+};
+
+static void __used test_local_trylock_init(struct test_local_trylock_data *d)
+{
+ local_trylock_init(&d->lock);
+ d->counter = 0;
+}
+
+static void __used test_local_trylock(void)
+{
+ local_lock(&test_local_trylock_data.lock);
+ this_cpu_add(test_local_trylock_data.counter, 1);
+ local_unlock(&test_local_trylock_data.lock);
+
+ if (local_trylock(&test_local_trylock_data.lock)) {
+ this_cpu_add(test_local_trylock_data.counter, 1);
+ local_unlock(&test_local_trylock_data.lock);
+ }
+}