[PATCH 02/14] lib: sbi_locks: annotate spinlock APIs for TSA

Carlos López carlos.lopezr4096 at gmail.com
Wed Jul 29 09:35:29 PDT 2026


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 <carlos.lopezr4096 at gmail.com>
---
 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 38d9cbeb7b2a..a0a34c049750 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 e253b1b723ab..fa624a94be81 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);
 }
-- 
2.51.0




More information about the opensbi mailing list