diff options
| author | Marco Elver <elver@google.com> | 2025-12-19 16:40:09 +0100 |
|---|---|---|
| committer | Peter Zijlstra <peterz@infradead.org> | 2026-01-05 16:43:32 +0100 |
| commit | 47907461e4f6fcdce8cf91dd164369192deeb7c4 (patch) | |
| tree | 7bd6c1b08792910ec5d2eca8d236b28c0370862b /lib/test_context-analysis.c | |
| parent | d3febf16dee28a74b01ba43195ee4965edb6208f (diff) | |
locking/ww_mutex: Support Clang's context analysis
Add support for Clang's context analysis for ww_mutex.
The programming model for ww_mutex is subtly more complex than other
locking primitives when using ww_acquire_ctx. Encoding the respective
pre-conditions for ww_mutex lock/unlock based on ww_acquire_ctx state
using Clang's context analysis makes incorrect use of the API harder.
Signed-off-by: Marco Elver <elver@google.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://patch.msgid.link/20251219154418.3592607-21-elver@google.com
Diffstat (limited to 'lib/test_context-analysis.c')
| -rw-r--r-- | lib/test_context-analysis.c | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/lib/test_context-analysis.c b/lib/test_context-analysis.c index 003e64cac540..2dc404456497 100644 --- a/lib/test_context-analysis.c +++ b/lib/test_context-analysis.c @@ -14,6 +14,7 @@ #include <linux/seqlock.h> #include <linux/spinlock.h> #include <linux/srcu.h> +#include <linux/ww_mutex.h> /* * Test that helper macros work as expected. @@ -531,3 +532,71 @@ static void __used test_local_trylock(void) local_unlock(&test_local_trylock_data.lock); } } + +static DEFINE_WD_CLASS(ww_class); + +struct test_ww_mutex_data { + struct ww_mutex mtx; + int counter __guarded_by(&mtx); +}; + +static void __used test_ww_mutex_init(struct test_ww_mutex_data *d) +{ + ww_mutex_init(&d->mtx, &ww_class); + d->counter = 0; +} + +static void __used test_ww_mutex_lock_noctx(struct test_ww_mutex_data *d) +{ + if (!ww_mutex_lock(&d->mtx, NULL)) { + d->counter++; + ww_mutex_unlock(&d->mtx); + } + + if (!ww_mutex_lock_interruptible(&d->mtx, NULL)) { + d->counter++; + ww_mutex_unlock(&d->mtx); + } + + if (ww_mutex_trylock(&d->mtx, NULL)) { + d->counter++; + ww_mutex_unlock(&d->mtx); + } + + ww_mutex_lock_slow(&d->mtx, NULL); + d->counter++; + ww_mutex_unlock(&d->mtx); + + ww_mutex_destroy(&d->mtx); +} + +static void __used test_ww_mutex_lock_ctx(struct test_ww_mutex_data *d) +{ + struct ww_acquire_ctx ctx; + + ww_acquire_init(&ctx, &ww_class); + + if (!ww_mutex_lock(&d->mtx, &ctx)) { + d->counter++; + ww_mutex_unlock(&d->mtx); + } + + if (!ww_mutex_lock_interruptible(&d->mtx, &ctx)) { + d->counter++; + ww_mutex_unlock(&d->mtx); + } + + if (ww_mutex_trylock(&d->mtx, &ctx)) { + d->counter++; + ww_mutex_unlock(&d->mtx); + } + + ww_mutex_lock_slow(&d->mtx, &ctx); + d->counter++; + ww_mutex_unlock(&d->mtx); + + ww_acquire_done(&ctx); + ww_acquire_fini(&ctx); + + ww_mutex_destroy(&d->mtx); +} |
