diff options
| author | Marco Elver <elver@google.com> | 2025-12-19 16:40:08 +0100 |
|---|---|---|
| committer | Peter Zijlstra <peterz@infradead.org> | 2026-01-05 16:43:31 +0100 |
| commit | d3febf16dee28a74b01ba43195ee4965edb6208f (patch) | |
| tree | 2363a4c04c89d9c7a358fce9b4f25b3b961bc5a4 /lib/test_context-analysis.c | |
| parent | 8c9c8566e139c0f1398245fbe3aa409fc1a79da8 (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.c | 73 |
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); + } +} |
