From b8f7e9ea80b94dd3c8eb0fa434265e376e9e3330 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20L=C3=B3pez?= Date: Wed, 9 Sep 2026 18:23:11 +0200 Subject: [PATCH] lib: sbi_locks: annotate spinlock APIs for TSA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add Thread Safety Analysis (TSA) annotations for spinlock APIs, allowing the compiler to reason about lock acquisition and release. Annotations have a different meaning if used in header declarations vs C file implementations. In header declarations, they specify the semantics of the given function, meaning that we must specify that the spinlock functions acquire and release a lock ("capability" in clang terms). In function implementations, attributes affect the function body and callers in the same translation unit; since the spinlock functions contain inline assembly, they must be excluded from analysis. Signed-off-by: Carlos López Reviewed-by: Anup Patel Link: https://lore.kernel.org/r/20260909162322.29778-4-carlos.lopezr4096@gmail.com Signed-off-by: Anup Patel --- include/sbi/riscv_locks.h | 8 ++++---- lib/sbi/riscv_locks.c | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/sbi/riscv_locks.h b/include/sbi/riscv_locks.h index 38d9cbeb..a0a34c04 100644 --- a/include/sbi/riscv_locks.h +++ b/include/sbi/riscv_locks.h @@ -20,7 +20,7 @@ typedef struct { u16 owner; u16 next; #endif -} __aligned(4) spinlock_t; +} __aligned(4) CAPABILITY("spinlock") spinlock_t; #define __SPIN_LOCK_UNLOCKED \ (spinlock_t) { 0, 0 } @@ -36,10 +36,10 @@ typedef struct { bool spin_lock_check(spinlock_t *lock); -bool spin_trylock(spinlock_t *lock); +bool spin_trylock(spinlock_t *lock) TRY_ACQUIRE(true, *lock); -void spin_lock(spinlock_t *lock); +void spin_lock(spinlock_t *lock) ACQUIRE(*lock) MUST_NOT_HOLD(*lock); -void spin_unlock(spinlock_t *lock); +void spin_unlock(spinlock_t *lock) RELEASE(*lock); #endif diff --git a/lib/sbi/riscv_locks.c b/lib/sbi/riscv_locks.c index e253b1b7..fa624a94 100644 --- a/lib/sbi/riscv_locks.c +++ b/lib/sbi/riscv_locks.c @@ -45,7 +45,7 @@ bool spin_trylock(spinlock_t *lock) return l0 == 0; } -void spin_lock(spinlock_t *lock) +void spin_lock(spinlock_t *lock) NO_THREAD_SAFETY_ANALYSIS { unsigned long inc = 1u << TICKET_SHIFT; unsigned long mask = 0xffffu; @@ -84,7 +84,7 @@ void spin_lock(spinlock_t *lock) : "memory"); } -void spin_unlock(spinlock_t *lock) +void spin_unlock(spinlock_t *lock) NO_THREAD_SAFETY_ANALYSIS { __smp_store_release(&lock->owner, lock->owner + 1); }