* [PATCH v2 00/14] Add clang Thread Safety Analysis (TSA) support
@ 2026-09-09 16:23 Carlos López
2026-09-09 16:23 ` [PATCH v2 01/14] include: sbi: add thread safety analysis macros Carlos López
` (13 more replies)
0 siblings, 14 replies; 15+ messages in thread
From: Carlos López @ 2026-09-09 16:23 UTC (permalink / raw)
To: opensbi; +Cc: Carlos López
Enable the use of clang's Thread Safety Analysis [0]. TSA is a clang
language extension that allows detecting potential invalid locking
patterns and race conditions at compile time, with zero runtime
overhead. TSA relies on annotations to express the relationships between
data and locks, and the expected state of a lock at certain points in
the program.
The first two commits introduce the basic infrastructure to use the TSA
annotations. The last commit enables TSA by default in the Makefile.
Commits in between add the new annotations to particular OpenSBI
subsystems.
The general pattern is:
* Struct fields are rearranged so that locks appear before the
field(s) they protect. This is needed for the compiler to be able to
perform analysis. Protected fields are annotated with GUARDED_BY() /
PT_GUARDED_BY().
* Functions that access spinlock-protected fields are annotated wth
MUST_HOLD().
* Functions that acquire a spinlock, and which may plausibly be called
with that spinlock held, are annotated with MUST_NOT_HOLD() to prevent
potential future deadlocks.
* Initializer functions and other special cases are excluded via
NO_THREAD_SAFETY_ANALYSIS.
This successfully results in detecting incorrect locking on clang >19.
For example, the following change:
diff --git a/lib/sbi/sbi_fifo.c b/lib/sbi/sbi_fifo.c
index 88b8888d2e81..5348b7452f64 100644
--- a/lib/sbi/sbi_fifo.c
+++ b/lib/sbi/sbi_fifo.c
@@ -37,9 +37,7 @@ u16 sbi_fifo_avail(struct sbi_fifo *fifo)
if (!fifo)
return 0;
- spin_lock(&fifo->qlock);
ret = fifo->avail;
- spin_unlock(&fifo->qlock);
return ret;
}
Results in a build error:
lib/sbi/sbi_fifo.c:41:14: error: reading variable 'avail' requires holding spinlock '&sbi_fifo::qlock' [-Werror,-Wthread-safety-analysis]
41 | ret = fifo->avail;
| ^
1 error generated.
Tested with clang 18.1.8, 19.1.7 and 22.1.8.
[0] https://clang.llvm.org/docs/ThreadSafetyAnalysis.html
v2:
- Enable TSA macros only on clang >= 19.
Carlos López (14):
include: sbi: add thread safety analysis macros
lib: sbi_locks: annotate spinlock APIs for TSA
lib: sbi_fifo: add TSA annotations
lib: sbi_heap: add TSA annotations
lib: sbi_scratch: add TSA annotations
lib: rpmi: add TSA annotations
lib: sbi_timer: add TSA annotations
lib: htif: add TSA annotations
lib: sbi_domain: add TSA annotations
lib: sbi_sse: inline enable event locking
lib: sbi_sse: pass SSE hart state explicitly
lib: sbi_sse: add TSA annotations
lib: test: disable TSA for spinlock tests
Makefile: enable Thread Safety Analysis
Makefile | 7 ++
include/sbi/riscv_locks.h | 8 +-
include/sbi/sbi_domain.h | 10 ++-
include/sbi/sbi_fifo.h | 6 +-
include/sbi/sbi_visibility.h | 17 +++++
lib/sbi/riscv_locks.c | 4 +-
lib/sbi/sbi_domain.c | 3 +
lib/sbi/sbi_domain_context.c | 2 +
lib/sbi/sbi_fifo.c | 11 ++-
lib/sbi/sbi_heap.c | 25 +++---
lib/sbi/sbi_scratch.c | 3 +-
lib/sbi/sbi_sse.c | 89 ++++++++++------------
lib/sbi/sbi_timer.c | 5 +-
lib/sbi/tests/riscv_locks_test.c | 3 +
lib/utils/mailbox/fdt_mailbox_rpmi_shmem.c | 14 ++--
lib/utils/sys/htif.c | 28 ++++---
16 files changed, 140 insertions(+), 95 deletions(-)
base-commit: 3593a5facc4c6938b90429a6973ba9ee21fc5899
--
2.51.0
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v2 01/14] include: sbi: add thread safety analysis macros
2026-09-09 16:23 [PATCH v2 00/14] Add clang Thread Safety Analysis (TSA) support Carlos López
@ 2026-09-09 16:23 ` Carlos López
2026-09-09 16:23 ` [PATCH v2 02/14] lib: sbi_locks: annotate spinlock APIs for TSA Carlos López
` (12 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Carlos López @ 2026-09-09 16:23 UTC (permalink / raw)
To: opensbi; +Cc: Carlos López
Add macros to properly guard clang's thread safety analysis attributes
keeping compatibility with GCC, on top of making things more readable.
Clang < 19 does not support guarded_by() [0], so do not define the
macros in that case.
[0] https://github.com/llvm/llvm-project/pull/94216
Signed-off-by: Carlos López <carlos.lopezr4096@gmail.com>
---
include/sbi/sbi_visibility.h | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/include/sbi/sbi_visibility.h b/include/sbi/sbi_visibility.h
index f900c44565a4..993561ef5eea 100644
--- a/include/sbi/sbi_visibility.h
+++ b/include/sbi/sbi_visibility.h
@@ -15,4 +15,21 @@
#pragma GCC visibility push(hidden)
#endif
+/* Thread Safety Analysis (TSA) annotations for use with clang -Wthread-safety */
+#if defined(__clang__) && __clang_major__ >= 19
+#define TSA_ATTR(x) __attribute__((x))
+#else
+#define TSA_ATTR(x)
+#endif
+
+#define CAPABILITY(x) TSA_ATTR(capability(x))
+#define GUARDED_BY(x) TSA_ATTR(guarded_by(x))
+#define PT_GUARDED_BY(x) TSA_ATTR(pt_guarded_by(x))
+#define ACQUIRE(...) TSA_ATTR(acquire_capability(__VA_ARGS__))
+#define RELEASE(...) TSA_ATTR(release_capability(__VA_ARGS__))
+#define MUST_HOLD(...) TSA_ATTR(requires_capability(__VA_ARGS__))
+#define MUST_NOT_HOLD(...) TSA_ATTR(locks_excluded(__VA_ARGS__))
+#define TRY_ACQUIRE(b, ...) TSA_ATTR(try_acquire_capability(b, __VA_ARGS__))
+#define NO_THREAD_SAFETY_ANALYSIS TSA_ATTR(no_thread_safety_analysis)
+
#endif
--
2.51.0
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v2 02/14] lib: sbi_locks: annotate spinlock APIs for TSA
2026-09-09 16:23 [PATCH v2 00/14] Add clang Thread Safety Analysis (TSA) support Carlos López
2026-09-09 16:23 ` [PATCH v2 01/14] include: sbi: add thread safety analysis macros Carlos López
@ 2026-09-09 16:23 ` Carlos López
2026-09-09 16:23 ` [PATCH v2 03/14] lib: sbi_fifo: add TSA annotations Carlos López
` (11 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Carlos López @ 2026-09-09 16:23 UTC (permalink / raw)
To: opensbi; +Cc: Carlos López
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@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
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v2 03/14] lib: sbi_fifo: add TSA annotations
2026-09-09 16:23 [PATCH v2 00/14] Add clang Thread Safety Analysis (TSA) support Carlos López
2026-09-09 16:23 ` [PATCH v2 01/14] include: sbi: add thread safety analysis macros Carlos López
2026-09-09 16:23 ` [PATCH v2 02/14] lib: sbi_locks: annotate spinlock APIs for TSA Carlos López
@ 2026-09-09 16:23 ` Carlos López
2026-09-09 16:23 ` [PATCH v2 04/14] lib: sbi_heap: " Carlos López
` (10 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Carlos López @ 2026-09-09 16:23 UTC (permalink / raw)
To: opensbi; +Cc: Carlos López
Add Thread Safety Analysis (TSA) annotations for the FIFO
implementation. This consists of indicating which fields are protected
by a spinlock and annotating functionst that must be called under a
spinlock. sbi_fifo_init() must be excluded, as acquiring a spinlock
before it is initialized does not make sense.
Signed-off-by: Carlos López <carlos.lopezr4096@gmail.com>
---
include/sbi/sbi_fifo.h | 6 +++---
lib/sbi/sbi_fifo.c | 11 ++++++++---
2 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/include/sbi/sbi_fifo.h b/include/sbi/sbi_fifo.h
index 89a2ea26a259..4ec10e05415e 100644
--- a/include/sbi/sbi_fifo.h
+++ b/include/sbi/sbi_fifo.h
@@ -15,12 +15,12 @@
#include <sbi/sbi_types.h>
struct sbi_fifo {
- void *queue;
spinlock_t qlock;
+ void *queue PT_GUARDED_BY(&qlock);
u16 entry_size;
u16 num_entries;
- u16 avail;
- u16 tail;
+ u16 avail GUARDED_BY(&qlock);
+ u16 tail GUARDED_BY(&qlock);
};
#define SBI_FIFO_INITIALIZER(__queue_mem, __entries, __entry_size) \
diff --git a/lib/sbi/sbi_fifo.c b/lib/sbi/sbi_fifo.c
index d07ebff4955c..88b8888d2e81 100644
--- a/lib/sbi/sbi_fifo.c
+++ b/lib/sbi/sbi_fifo.c
@@ -13,7 +13,7 @@
#include <sbi/sbi_string.h>
void sbi_fifo_init(struct sbi_fifo *fifo, void *queue_mem, u16 entries,
- u16 entry_size)
+ u16 entry_size) NO_THREAD_SAFETY_ANALYSIS
{
fifo->queue = queue_mem;
fifo->num_entries = entries;
@@ -25,6 +25,7 @@ void sbi_fifo_init(struct sbi_fifo *fifo, void *queue_mem, u16 entries,
/* Note: must be called with fifo->qlock held */
static inline bool __sbi_fifo_is_full(struct sbi_fifo *fifo)
+ MUST_HOLD(&fifo->qlock)
{
return (fifo->avail == fifo->num_entries) ? true : false;
}
@@ -58,7 +59,8 @@ int sbi_fifo_is_full(struct sbi_fifo *fifo)
}
/* Note: must be called with fifo->qlock held */
-static inline void __sbi_fifo_enqueue(struct sbi_fifo *fifo, void *data)
+static inline void __sbi_fifo_enqueue(struct sbi_fifo *fifo, void *data)
+ MUST_HOLD(&fifo->qlock)
{
u32 head;
@@ -91,7 +93,8 @@ static inline void __sbi_fifo_enqueue(struct sbi_fifo *fifo, void *data)
}
/* Note: must be called with fifo->qlock held */
-static inline void __sbi_fifo_dequeue(struct sbi_fifo *fifo, void *data)
+static inline void __sbi_fifo_dequeue(struct sbi_fifo *fifo, void *data)
+ MUST_HOLD(&fifo->qlock)
{
if (!data)
goto skip_data_copy;
@@ -126,6 +129,7 @@ skip_data_copy:
/* Note: must be called with fifo->qlock held */
static inline bool __sbi_fifo_is_empty(struct sbi_fifo *fifo)
+ MUST_HOLD(&fifo->qlock)
{
return (fifo->avail == 0) ? true : false;
}
@@ -146,6 +150,7 @@ int sbi_fifo_is_empty(struct sbi_fifo *fifo)
/* Note: must be called with fifo->qlock held */
static inline void __sbi_fifo_reset(struct sbi_fifo *fifo)
+ MUST_HOLD(&fifo->qlock)
{
size_t size = (size_t)fifo->num_entries * fifo->entry_size;
--
2.51.0
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v2 04/14] lib: sbi_heap: add TSA annotations
2026-09-09 16:23 [PATCH v2 00/14] Add clang Thread Safety Analysis (TSA) support Carlos López
` (2 preceding siblings ...)
2026-09-09 16:23 ` [PATCH v2 03/14] lib: sbi_fifo: add TSA annotations Carlos López
@ 2026-09-09 16:23 ` Carlos López
2026-09-09 16:23 ` [PATCH v2 05/14] lib: sbi_scratch: " Carlos López
` (9 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Carlos López @ 2026-09-09 16:23 UTC (permalink / raw)
To: opensbi; +Cc: Carlos López
Add Thread Safety Analysis (TSA) annotations for the heap allocator.
This includes indicating which fields are protected by a spinlock and
annotating functions that must be called under a spinlock. Exclude
sbi_heap_init_new(), as the spinlock cannot be acquired before it is
initialized.
Signed-off-by: Carlos López <carlos.lopezr4096@gmail.com>
---
lib/sbi/sbi_heap.c | 25 ++++++++++++++-----------
1 file changed, 14 insertions(+), 11 deletions(-)
diff --git a/lib/sbi/sbi_heap.c b/lib/sbi/sbi_heap.c
index 1de6dc1e87a8..cda124a4eebd 100644
--- a/lib/sbi/sbi_heap.c
+++ b/lib/sbi/sbi_heap.c
@@ -28,18 +28,18 @@ struct heap_node {
struct sbi_heap_control {
spinlock_t lock;
- unsigned long base;
- unsigned long size;
- unsigned long resv;
- struct sbi_dlist free_node_list;
- struct sbi_dlist free_space_list;
- struct sbi_dlist used_space_list;
- struct heap_node init_free_space_node;
+ unsigned long base GUARDED_BY(&lock);
+ unsigned long size GUARDED_BY(&lock);
+ unsigned long resv GUARDED_BY(&lock);
+ struct sbi_dlist free_node_list GUARDED_BY(&lock);
+ struct sbi_dlist free_space_list GUARDED_BY(&lock);
+ struct sbi_dlist used_space_list GUARDED_BY(&lock);
+ struct heap_node init_free_space_node GUARDED_BY(&lock);
};
struct sbi_heap_control global_hpctrl;
-static bool alloc_nodes(struct sbi_heap_control *hpctrl)
+static bool alloc_nodes(struct sbi_heap_control *hpctrl) MUST_HOLD(&hpctrl->lock)
{
size_t size = HEAP_NODE_BATCH_SIZE * sizeof(struct heap_node);
struct heap_node *n, *new = NULL;
@@ -69,8 +69,9 @@ static bool alloc_nodes(struct sbi_heap_control *hpctrl)
return true;
}
-static void *alloc_with_align(struct sbi_heap_control *hpctrl,
- size_t align, size_t size)
+static void *alloc_with_align(struct sbi_heap_control *hpctrl, size_t align,
+ size_t size)
+ MUST_NOT_HOLD(&hpctrl->lock)
{
void *ret = NULL;
struct heap_node *n, *np;
@@ -230,17 +231,19 @@ unsigned long sbi_heap_free_space_from(struct sbi_heap_control *hpctrl)
}
unsigned long sbi_heap_used_space_from(struct sbi_heap_control *hpctrl)
+ NO_THREAD_SAFETY_ANALYSIS
{
return hpctrl->size - hpctrl->resv - sbi_heap_free_space();
}
unsigned long sbi_heap_reserved_space_from(struct sbi_heap_control *hpctrl)
+ NO_THREAD_SAFETY_ANALYSIS
{
return hpctrl->resv;
}
int sbi_heap_init_new(struct sbi_heap_control *hpctrl, unsigned long base,
- unsigned long size)
+ unsigned long size) NO_THREAD_SAFETY_ANALYSIS
{
struct heap_node *n;
--
2.51.0
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v2 05/14] lib: sbi_scratch: add TSA annotations
2026-09-09 16:23 [PATCH v2 00/14] Add clang Thread Safety Analysis (TSA) support Carlos López
` (3 preceding siblings ...)
2026-09-09 16:23 ` [PATCH v2 04/14] lib: sbi_heap: " Carlos López
@ 2026-09-09 16:23 ` Carlos López
2026-09-09 16:23 ` [PATCH v2 06/14] lib: rpmi: " Carlos López
` (8 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Carlos López @ 2026-09-09 16:23 UTC (permalink / raw)
To: opensbi; +Cc: Carlos López
Add Thread Safety Analysis (TSA) annotations for the scratch space
implementation. This only consists of annotating that the extra_offset
global must be accessed under the extra_lock spinlock.
Signed-off-by: Carlos López <carlos.lopezr4096@gmail.com>
---
lib/sbi/sbi_scratch.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/lib/sbi/sbi_scratch.c b/lib/sbi/sbi_scratch.c
index bb14a1a25feb..21120b145202 100644
--- a/lib/sbi/sbi_scratch.c
+++ b/lib/sbi/sbi_scratch.c
@@ -21,7 +21,8 @@ u32 hartindex_to_hartid_table[SBI_HARTMASK_MAX_BITS] = { [0 ... SBI_HARTMASK_MAX
struct sbi_scratch *hartindex_to_scratch_table[SBI_HARTMASK_MAX_BITS];
static spinlock_t extra_lock = SPIN_LOCK_INITIALIZER;
-static unsigned long extra_offset = SBI_SCRATCH_EXTRA_SPACE_OFFSET;
+static unsigned long
+ extra_offset GUARDED_BY(&extra_lock) = SBI_SCRATCH_EXTRA_SPACE_OFFSET;
/*
* Get the alignment size.
--
2.51.0
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v2 06/14] lib: rpmi: add TSA annotations
2026-09-09 16:23 [PATCH v2 00/14] Add clang Thread Safety Analysis (TSA) support Carlos López
` (4 preceding siblings ...)
2026-09-09 16:23 ` [PATCH v2 05/14] lib: sbi_scratch: " Carlos López
@ 2026-09-09 16:23 ` Carlos López
2026-09-09 16:23 ` [PATCH v2 07/14] lib: sbi_timer: " Carlos López
` (7 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Carlos López @ 2026-09-09 16:23 UTC (permalink / raw)
To: opensbi; +Cc: Carlos López
Add Thread Safety Analysis (TSA) annotations for the RPMI mailbox
implementation. This includes indicating which fields are protected
by a spinlock, and annotating which functions must be called under a
spinlock. Exclude rpmi_shmem_transport_init(), as the spinlock cannot be
acquired before it is initialized.
Signed-off-by: Carlos López <carlos.lopezr4096@gmail.com>
---
lib/utils/mailbox/fdt_mailbox_rpmi_shmem.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/lib/utils/mailbox/fdt_mailbox_rpmi_shmem.c b/lib/utils/mailbox/fdt_mailbox_rpmi_shmem.c
index 521e06735873..cf9756581cf0 100644
--- a/lib/utils/mailbox/fdt_mailbox_rpmi_shmem.c
+++ b/lib/utils/mailbox/fdt_mailbox_rpmi_shmem.c
@@ -113,9 +113,9 @@ struct smq_queue_ctx {
/* Type of queue - REQ or ACK */
enum rpmi_queue_type queue_type;
/* Pointers to the queue shared memory */
- volatile le32_t *headptr;
- volatile le32_t *tailptr;
- volatile uint8_t *buffer;
+ volatile le32_t *headptr PT_GUARDED_BY(&queue_lock);
+ volatile le32_t *tailptr PT_GUARDED_BY(&queue_lock);
+ volatile uint8_t *buffer PT_GUARDED_BY(&queue_lock);
/* Name of the queue */
char name[RPMI_NAME_CHARS_MAX];
};
@@ -154,12 +154,14 @@ struct rpmi_shmem_mbox_controller {
/**************** Shared Memory Queues Helpers **************/
static bool __smq_queue_full(struct smq_queue_ctx *qctx)
+ MUST_HOLD(&qctx->queue_lock)
{
return ((le32_to_cpu(*qctx->tailptr) + 1) % qctx->num_slots ==
le32_to_cpu(*qctx->headptr)) ? true : false;
}
static bool __smq_queue_empty(struct smq_queue_ctx *qctx)
+ MUST_HOLD(&qctx->queue_lock)
{
return (le32_to_cpu(*qctx->headptr) ==
le32_to_cpu(*qctx->tailptr)) ? true : false;
@@ -167,6 +169,7 @@ static bool __smq_queue_empty(struct smq_queue_ctx *qctx)
static int __smq_rx(struct smq_queue_ctx *qctx, u32 slot_size,
u32 service_group_id, struct mbox_xfer *xfer)
+ MUST_HOLD(&qctx->queue_lock)
{
void *dst, *src;
struct rpmi_message *msg;
@@ -250,7 +253,7 @@ static int __smq_rx(struct smq_queue_ctx *qctx, u32 slot_size,
static int __smq_tx(struct smq_queue_ctx *qctx, struct rpmi_mb_regs *mb_regs,
u32 a2p_doorbell_value, u32 slot_size, u32 service_group_id,
- struct mbox_xfer *xfer)
+ struct mbox_xfer *xfer) MUST_HOLD(&qctx->queue_lock)
{
u32 i, tailidx;
void *dst, *src;
@@ -583,7 +586,8 @@ static void rpmi_shmem_mbox_free_chan(struct mbox_controller *mbox,
extern struct fdt_mailbox fdt_mailbox_rpmi_shmem;
static int rpmi_shmem_transport_init(struct rpmi_shmem_mbox_controller *mctl,
- const void *fdt, int nodeoff)
+ const void *fdt,
+ int nodeoff) NO_THREAD_SAFETY_ANALYSIS
{
const char *name;
const fdt32_t *prop;
--
2.51.0
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v2 07/14] lib: sbi_timer: add TSA annotations
2026-09-09 16:23 [PATCH v2 00/14] Add clang Thread Safety Analysis (TSA) support Carlos López
` (5 preceding siblings ...)
2026-09-09 16:23 ` [PATCH v2 06/14] lib: rpmi: " Carlos López
@ 2026-09-09 16:23 ` Carlos López
2026-09-09 16:23 ` [PATCH v2 08/14] lib: htif: " Carlos López
` (6 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Carlos López @ 2026-09-09 16:23 UTC (permalink / raw)
To: opensbi; +Cc: Carlos López
Add Thread Safety Analysis (TSA) annotations for the timer
implementation. This includes indicating which fields are protected
by a spinlock, and annotating which functions must be called under a
spinlock. Exclude sbi_timer_init(), as the spinlock cannot be acquired
before it is initialized.
Signed-off-by: Carlos López <carlos.lopezr4096@gmail.com>
---
lib/sbi/sbi_timer.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/lib/sbi/sbi_timer.c b/lib/sbi/sbi_timer.c
index 8abb5e7bea20..78aaa32e9d10 100644
--- a/lib/sbi/sbi_timer.c
+++ b/lib/sbi/sbi_timer.c
@@ -23,7 +23,7 @@
struct timer_state {
u64 time_delta;
spinlock_t event_list_lock;
- struct sbi_dlist event_list;
+ struct sbi_dlist event_list GUARDED_BY(&event_list_lock);
struct sbi_timer_event smode_ev;
};
@@ -160,6 +160,7 @@ void sbi_timer_set_delta_upper(ulong delta_upper)
#endif
static void __sbi_timer_update_device(struct timer_state *tstate)
+ MUST_HOLD(&tstate->event_list_lock)
{
struct sbi_timer_event *ev;
@@ -188,6 +189,7 @@ static void __sbi_timer_event_stop(struct sbi_timer_event *ev)
static void __sbi_timer_event_start(struct timer_state *tstate,
struct sbi_timer_event *ev, u64 next_event)
+ MUST_HOLD(&tstate->event_list_lock)
{
struct sbi_timer_event *tev, *next_ev = NULL;
@@ -350,6 +352,7 @@ void sbi_timer_set_device(const struct sbi_timer_device *dev)
}
int sbi_timer_init(struct sbi_scratch *scratch, bool cold_boot)
+ NO_THREAD_SAFETY_ANALYSIS
{
const struct sbi_platform *plat = sbi_platform_ptr(scratch);
struct timer_state *tstate;
--
2.51.0
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v2 08/14] lib: htif: add TSA annotations
2026-09-09 16:23 [PATCH v2 00/14] Add clang Thread Safety Analysis (TSA) support Carlos López
` (6 preceding siblings ...)
2026-09-09 16:23 ` [PATCH v2 07/14] lib: sbi_timer: " Carlos López
@ 2026-09-09 16:23 ` Carlos López
2026-09-09 16:23 ` [PATCH v2 09/14] lib: sbi_domain: " Carlos López
` (5 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Carlos López @ 2026-09-09 16:23 UTC (permalink / raw)
To: opensbi; +Cc: Carlos López
Add Thread Safety Analysis (TSA) annotations for the HTIF driver
implementation.
This requires annotating the tohost/fromhost and htif_console_buf
globals to indicate that they are protected by htif_lock.
htif_system_reset() can be excluded since it is only called under
special circumstances from sbi_system_reset(), when all other harts
have been stopped.
Signed-off-by: Carlos López <carlos.lopezr4096@gmail.com>
---
lib/utils/sys/htif.c | 28 ++++++++++++++++------------
1 file changed, 16 insertions(+), 12 deletions(-)
diff --git a/lib/utils/sys/htif.c b/lib/utils/sys/htif.c
index b4e63212477a..1360613cd5aa 100644
--- a/lib/utils/sys/htif.c
+++ b/lib/utils/sys/htif.c
@@ -46,22 +46,25 @@
#define PK_SYS_write 64
-volatile uint64_t tohost __attribute__((section(".htif")));
-volatile uint64_t fromhost __attribute__((section(".htif")));
+static spinlock_t htif_lock = SPIN_LOCK_INITIALIZER;
+
+volatile uint64_t tohost
+ __attribute__((section(".htif"))) GUARDED_BY(&htif_lock);
+volatile uint64_t fromhost
+ __attribute__((section(".htif"))) GUARDED_BY(&htif_lock);
-static uint64_t *htif_fromhost = NULL;
-static uint64_t *htif_tohost = NULL;
+static uint64_t *htif_fromhost PT_GUARDED_BY(&htif_lock) = NULL;
+static uint64_t *htif_tohost PT_GUARDED_BY(&htif_lock) = NULL;
static bool htif_custom = false;
-static int htif_console_buf;
-static spinlock_t htif_lock = SPIN_LOCK_INITIALIZER;
+static int htif_console_buf GUARDED_BY(&htif_lock);
-static inline uint64_t __read_tohost(void)
+static inline uint64_t __read_tohost(void) MUST_HOLD(&htif_lock)
{
return (htif_custom) ? *htif_tohost : tohost;
}
-static inline void __write_tohost(uint64_t val)
+static inline void __write_tohost(uint64_t val) MUST_HOLD(&htif_lock)
{
if (htif_custom)
*htif_tohost = val;
@@ -69,12 +72,12 @@ static inline void __write_tohost(uint64_t val)
tohost = val;
}
-static inline uint64_t __read_fromhost(void)
+static inline uint64_t __read_fromhost(void) MUST_HOLD(&htif_lock)
{
return (htif_custom) ? *htif_fromhost : fromhost;
}
-static inline void __write_fromhost(uint64_t val)
+static inline void __write_fromhost(uint64_t val) MUST_HOLD(&htif_lock)
{
if (htif_custom)
*htif_fromhost = val;
@@ -82,7 +85,7 @@ static inline void __write_fromhost(uint64_t val)
fromhost = val;
}
-static void __check_fromhost()
+static void __check_fromhost() MUST_HOLD(&htif_lock)
{
uint64_t fh = __read_fromhost();
if (!fh)
@@ -104,6 +107,7 @@ static void __check_fromhost()
}
static void __set_tohost(uint64_t dev, uint64_t cmd, uint64_t data)
+ MUST_HOLD(&htif_lock)
{
while (__read_tohost())
__check_fromhost();
@@ -217,7 +221,7 @@ static int htif_system_reset_check(u32 type, u32 reason)
return 1;
}
-static void htif_system_reset(u32 type, u32 reason)
+static void htif_system_reset(u32 type, u32 reason) NO_THREAD_SAFETY_ANALYSIS
{
while (1) {
__write_fromhost(0);
--
2.51.0
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v2 09/14] lib: sbi_domain: add TSA annotations
2026-09-09 16:23 [PATCH v2 00/14] Add clang Thread Safety Analysis (TSA) support Carlos López
` (7 preceding siblings ...)
2026-09-09 16:23 ` [PATCH v2 08/14] lib: htif: " Carlos López
@ 2026-09-09 16:23 ` Carlos López
2026-09-09 16:23 ` [PATCH v2 10/14] lib: sbi_sse: inline enable event locking Carlos López
` (4 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Carlos López @ 2026-09-09 16:23 UTC (permalink / raw)
To: opensbi; +Cc: Carlos López
Add Thread Safety Analysis (TSA) annotations for the domain handling
code. This includes indicating which fields are protected by a spinlock,
and annotating which functions acquire a spinlock, in order to prevent
nesting. Exclude sbi_domain_register() from analysis, as it initializes
a domain's spinlock.
Signed-off-by: Carlos López <carlos.lopezr4096@gmail.com>
---
include/sbi/sbi_domain.h | 10 ++++++----
lib/sbi/sbi_domain.c | 3 +++
lib/sbi/sbi_domain_context.c | 2 ++
3 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/include/sbi/sbi_domain.h b/include/sbi/sbi_domain.h
index 38784a0e25b8..d8c42be595be 100644
--- a/include/sbi/sbi_domain.h
+++ b/include/sbi/sbi_domain.h
@@ -193,10 +193,10 @@ struct sbi_domain {
struct sbi_domain_state_priv state_priv;
/** Logical index of this domain */
u32 index;
- /** HARTs assigned to this domain */
- struct sbi_hartmask assigned_harts;
/** Spinlock for accessing assigned_harts */
spinlock_t assigned_harts_lock;
+ /** HARTs assigned to this domain */
+ struct sbi_hartmask assigned_harts GUARDED_BY(&assigned_harts_lock);
/** Name of this domain */
char name[64];
/** Possible HARTs in this domain */
@@ -252,7 +252,8 @@ extern struct sbi_dlist domain_list;
* @param hartindex the HART index
* @return true if HART is assigned to domain otherwise false
*/
-bool sbi_domain_is_assigned_hart(const struct sbi_domain *dom, u32 hartindex);
+bool sbi_domain_is_assigned_hart(const struct sbi_domain *dom, u32 hartindex)
+ MUST_NOT_HOLD(&dom->assigned_harts_lock);
/**
* Get the assigned HART mask for given domain
@@ -261,7 +262,8 @@ bool sbi_domain_is_assigned_hart(const struct sbi_domain *dom, u32 hartindex);
* @return 0 on success and SBI_Exxx (< 0) on failure
*/
int sbi_domain_get_assigned_hartmask(const struct sbi_domain *dom,
- struct sbi_hartmask *mask);
+ struct sbi_hartmask *mask)
+ MUST_NOT_HOLD(&dom->assigned_harts_lock);
/**
* Initialize a domain memory region based on it's physical
diff --git a/lib/sbi/sbi_domain.c b/lib/sbi/sbi_domain.c
index 79d61c54f545..dc0828bfdd47 100644
--- a/lib/sbi/sbi_domain.c
+++ b/lib/sbi/sbi_domain.c
@@ -60,6 +60,7 @@ void sbi_update_hartindex_to_domain(u32 hartindex, struct sbi_domain *dom)
}
bool sbi_domain_is_assigned_hart(const struct sbi_domain *dom, u32 hartindex)
+ MUST_NOT_HOLD(&dom->assigned_harts_lock)
{
bool ret;
struct sbi_domain *tdom = (struct sbi_domain *)dom;
@@ -76,6 +77,7 @@ bool sbi_domain_is_assigned_hart(const struct sbi_domain *dom, u32 hartindex)
int sbi_domain_get_assigned_hartmask(const struct sbi_domain *dom,
struct sbi_hartmask *mask)
+ MUST_NOT_HOLD(&dom->assigned_harts_lock)
{
ulong ret = 0;
struct sbi_domain *tdom = (struct sbi_domain *)dom;
@@ -627,6 +629,7 @@ void sbi_domain_dump_all(const char *suffix)
int sbi_domain_register(struct sbi_domain *dom,
const struct sbi_hartmask *assign_mask)
+ NO_THREAD_SAFETY_ANALYSIS
{
u32 i;
int rc;
diff --git a/lib/sbi/sbi_domain_context.c b/lib/sbi/sbi_domain_context.c
index 37cbe1751d89..53bf0c207971 100644
--- a/lib/sbi/sbi_domain_context.c
+++ b/lib/sbi/sbi_domain_context.c
@@ -107,6 +107,8 @@ static void hart_context_set(struct sbi_domain *dom, u32 hartindex,
*/
static int switch_to_next_domain_context(struct hart_context *ctx,
struct hart_context *dom_ctx)
+ MUST_NOT_HOLD(&ctx->dom->assigned_harts_lock)
+ MUST_NOT_HOLD(&dom_ctx->dom->assigned_harts_lock)
{
u32 hartindex = current_hartindex();
struct sbi_trap_context *trap_ctx;
--
2.51.0
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v2 10/14] lib: sbi_sse: inline enable event locking
2026-09-09 16:23 [PATCH v2 00/14] Add clang Thread Safety Analysis (TSA) support Carlos López
` (8 preceding siblings ...)
2026-09-09 16:23 ` [PATCH v2 09/14] lib: sbi_domain: " Carlos López
@ 2026-09-09 16:23 ` Carlos López
2026-09-09 16:23 ` [PATCH v2 11/14] lib: sbi_sse: pass SSE hart state explicitly Carlos López
` (3 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Carlos López @ 2026-09-09 16:23 UTC (permalink / raw)
To: opensbi; +Cc: Carlos López
In preparation to add TSA annotations, inline sse_enabled_event_lock()
and sse_enabled_event_unlock(). This will help the compiler reason about
locking of the hart state by explicitly acquiring the spinlock in the
callers.
Signed-off-by: Carlos López <carlos.lopezr4096@gmail.com>
---
lib/sbi/sbi_sse.c | 34 ++++++++--------------------------
1 file changed, 8 insertions(+), 26 deletions(-)
diff --git a/lib/sbi/sbi_sse.c b/lib/sbi/sbi_sse.c
index f6d0111dc1e7..3d1601674e07 100644
--- a/lib/sbi/sbi_sse.c
+++ b/lib/sbi/sbi_sse.c
@@ -265,28 +265,6 @@ static struct sse_global_event *sse_get_global_event(struct sbi_sse_event *e)
return container_of(e, struct sse_global_event, event);
}
-/**
- * If event is global, must be called under enabled event lock
- */
-static void sse_enabled_event_lock(struct sbi_sse_event *e)
-{
- struct sse_hart_state *shs;
-
- shs = sse_get_hart_state(e);
- spin_lock(&shs->enabled_event_lock);
-}
-
-/**
- * If event is global, must be called under enabled event lock
- */
-static void sse_enabled_event_unlock(struct sbi_sse_event *e)
-{
- struct sse_hart_state *shs;
-
- shs = sse_get_hart_state(e);
- spin_unlock(&shs->enabled_event_lock);
-}
-
static void sse_event_set_state(struct sbi_sse_event *e,
unsigned long new_state)
{
@@ -865,14 +843,16 @@ int sbi_sse_enable(uint32_t event_id)
{
int ret;
struct sbi_sse_event *e;
+ struct sse_hart_state *shs;
ret = sse_event_get(event_id, &e);
if (ret)
return ret;
- sse_enabled_event_lock(e);
+ shs = sse_get_hart_state(e);
+ spin_lock(&shs->enabled_event_lock);
ret = sse_event_enable(e);
- sse_enabled_event_unlock(e);
+ spin_unlock(&shs->enabled_event_lock);
sse_event_put(e);
return ret;
@@ -882,14 +862,16 @@ int sbi_sse_disable(uint32_t event_id)
{
int ret;
struct sbi_sse_event *e;
+ struct sse_hart_state *shs;
ret = sse_event_get(event_id, &e);
if (ret)
return ret;
- sse_enabled_event_lock(e);
+ shs = sse_get_hart_state(e);
+ spin_lock(&shs->enabled_event_lock);
ret = sse_event_disable(e);
- sse_enabled_event_unlock(e);
+ spin_unlock(&shs->enabled_event_lock);
sse_event_put(e);
--
2.51.0
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v2 11/14] lib: sbi_sse: pass SSE hart state explicitly
2026-09-09 16:23 [PATCH v2 00/14] Add clang Thread Safety Analysis (TSA) support Carlos López
` (9 preceding siblings ...)
2026-09-09 16:23 ` [PATCH v2 10/14] lib: sbi_sse: inline enable event locking Carlos López
@ 2026-09-09 16:23 ` Carlos López
2026-09-09 16:23 ` [PATCH v2 12/14] lib: sbi_sse: add TSA annotations Carlos López
` (2 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Carlos López @ 2026-09-09 16:23 UTC (permalink / raw)
To: opensbi; +Cc: Carlos López
In preparation to add TSA annotations, pass the SSE hart state owning an
event, instead of relying on sse_get_hart_state() to retrieve it from
the event itself. This makes the relationship more explicit, and will
allow the compiler to reason about the state of locks.
Signed-off-by: Carlos López <carlos.lopezr4096@gmail.com>
---
lib/sbi/sbi_sse.c | 23 +++++++++++++----------
1 file changed, 13 insertions(+), 10 deletions(-)
diff --git a/lib/sbi/sbi_sse.c b/lib/sbi/sbi_sse.c
index 3d1601674e07..39e52752b024 100644
--- a/lib/sbi/sbi_sse.c
+++ b/lib/sbi/sbi_sse.c
@@ -328,9 +328,9 @@ static void sse_event_remove_from_list(struct sbi_sse_event *e)
/**
* Must be called under owner hart lock
*/
-static void sse_event_add_to_list(struct sbi_sse_event *e)
+static void sse_event_add_to_list(struct sse_hart_state *state,
+ struct sbi_sse_event *e)
{
- struct sse_hart_state *state = sse_get_hart_state(e);
struct sbi_sse_event *tmp;
sbi_list_for_each_entry(tmp, &state->enabled_event_list, node) {
@@ -346,7 +346,8 @@ static void sse_event_add_to_list(struct sbi_sse_event *e)
/**
* Must be called under owner hart lock
*/
-static int sse_event_disable(struct sbi_sse_event *e)
+static int sse_event_disable(struct sse_hart_state *shs,
+ struct sbi_sse_event *e)
{
if (sse_event_state(e) != SBI_SSE_STATE_ENABLED)
return SBI_EINVALID_STATE;
@@ -778,13 +779,14 @@ static int sse_inject_event(uint32_t event_id, unsigned long hartid)
/**
* Must be called under owner hart lock
*/
-static int sse_event_enable(struct sbi_sse_event *e)
+static int sse_event_enable(struct sse_hart_state *shs,
+ struct sbi_sse_event *e)
{
if (sse_event_state(e) != SBI_SSE_STATE_REGISTERED)
return SBI_EINVALID_STATE;
sse_event_set_state(e, SBI_SSE_STATE_ENABLED);
- sse_event_add_to_list(e);
+ sse_event_add_to_list(shs, e);
sse_event_invoke_cb(e, enable_cb);
@@ -795,7 +797,8 @@ static int sse_event_enable(struct sbi_sse_event *e)
return SBI_OK;
}
-static int sse_event_complete(struct sbi_sse_event *e,
+static int sse_event_complete(struct sse_hart_state *shs,
+ struct sbi_sse_event *e,
struct sbi_trap_regs *regs,
struct sbi_ecall_return *out)
{
@@ -807,7 +810,7 @@ static int sse_event_complete(struct sbi_sse_event *e,
sse_event_set_state(e, SBI_SSE_STATE_ENABLED);
if (e->attrs.config & SBI_SSE_ATTR_CONFIG_ONESHOT)
- sse_event_disable(e);
+ sse_event_disable(shs, e);
sse_event_invoke_cb(e, complete_cb);
@@ -830,7 +833,7 @@ int sbi_sse_complete(struct sbi_trap_regs *regs, struct sbi_ecall_return *out)
* the one that needs to be completed
*/
if (sse_event_state(tmp) == SBI_SSE_STATE_RUNNING) {
- ret = sse_event_complete(tmp, regs, out);
+ ret = sse_event_complete(state, tmp, regs, out);
break;
}
}
@@ -851,7 +854,7 @@ int sbi_sse_enable(uint32_t event_id)
shs = sse_get_hart_state(e);
spin_lock(&shs->enabled_event_lock);
- ret = sse_event_enable(e);
+ ret = sse_event_enable(shs, e);
spin_unlock(&shs->enabled_event_lock);
sse_event_put(e);
@@ -870,7 +873,7 @@ int sbi_sse_disable(uint32_t event_id)
shs = sse_get_hart_state(e);
spin_lock(&shs->enabled_event_lock);
- ret = sse_event_disable(e);
+ ret = sse_event_disable(shs, e);
spin_unlock(&shs->enabled_event_lock);
sse_event_put(e);
--
2.51.0
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v2 12/14] lib: sbi_sse: add TSA annotations
2026-09-09 16:23 [PATCH v2 00/14] Add clang Thread Safety Analysis (TSA) support Carlos López
` (10 preceding siblings ...)
2026-09-09 16:23 ` [PATCH v2 11/14] lib: sbi_sse: pass SSE hart state explicitly Carlos López
@ 2026-09-09 16:23 ` Carlos López
2026-09-09 16:23 ` [PATCH v2 13/14] lib: test: disable TSA for spinlock tests Carlos López
2026-09-09 16:23 ` [PATCH v2 14/14] Makefile: enable Thread Safety Analysis Carlos López
13 siblings, 0 replies; 15+ messages in thread
From: Carlos López @ 2026-09-09 16:23 UTC (permalink / raw)
To: opensbi; +Cc: Carlos López
Now that the lock relationship between an event and its owner hart is
explicit, add TSA annotations for the SSE handling code. This includes
indicating which fields are protected by a spinlock, as well as
annotating which functions need to run under a spinlock.
Exclude sse_local_init(), which initializes the spinlock to be acquired,
and sse_event_get() / sse_event_put(), which perform conditional locking
that TSA is not able to follow properly.
Signed-off-by: Carlos López <carlos.lopezr4096@gmail.com>
---
lib/sbi/sbi_sse.c | 32 +++++++++++++++++++-------------
1 file changed, 19 insertions(+), 13 deletions(-)
diff --git a/lib/sbi/sbi_sse.c b/lib/sbi/sbi_sse.c
index 39e52752b024..767ea1280014 100644
--- a/lib/sbi/sbi_sse.c
+++ b/lib/sbi/sbi_sse.c
@@ -108,6 +108,11 @@ struct sbi_sse_event {
/** Per-hart state */
struct sse_hart_state {
+ /**
+ * Lock that protects enabled_event_list
+ */
+ spinlock_t enabled_event_lock;
+
/* Priority sorted list of enabled events (global and local in >=
* ENABLED state). This list is protected by the enabled_event_lock.
*
@@ -124,12 +129,7 @@ struct sse_hart_state {
* this enabled_event_list and thus can only be removed from this
* list upon disable ecall or on complete with ONESHOT flag.
*/
- struct sbi_dlist enabled_event_list;
-
- /**
- * Lock that protects enabled_event_list
- */
- spinlock_t enabled_event_lock;
+ struct sbi_dlist enabled_event_list GUARDED_BY(&enabled_event_lock);
/**
* List of local events allocated at boot time.
@@ -147,16 +147,16 @@ struct sse_hart_state {
* Global events are accessible by all harts
*/
struct sse_global_event {
- /**
- * global event struct
- */
- struct sbi_sse_event event;
-
/**
* Global event lock protecting access from multiple harts from ecall to
* the event.
*/
spinlock_t lock;
+
+ /**
+ * global event struct
+ */
+ struct sbi_sse_event event GUARDED_BY(&lock);
};
struct sse_event_info {
@@ -272,7 +272,8 @@ static void sse_event_set_state(struct sbi_sse_event *e,
e->attrs.status |= new_state;
}
-static int sse_event_get(uint32_t event_id, struct sbi_sse_event **eret)
+static int sse_event_get(uint32_t event_id,
+ struct sbi_sse_event **eret) NO_THREAD_SAFETY_ANALYSIS
{
unsigned int i;
struct sbi_sse_event *e;
@@ -309,7 +310,7 @@ static int sse_event_get(uint32_t event_id, struct sbi_sse_event **eret)
return SBI_EINVAL;
}
-static void sse_event_put(struct sbi_sse_event *e)
+static void sse_event_put(struct sbi_sse_event *e) NO_THREAD_SAFETY_ANALYSIS
{
struct sse_global_event *ge;
@@ -330,6 +331,7 @@ static void sse_event_remove_from_list(struct sbi_sse_event *e)
*/
static void sse_event_add_to_list(struct sse_hart_state *state,
struct sbi_sse_event *e)
+ MUST_HOLD(&state->enabled_event_lock)
{
struct sbi_sse_event *tmp;
@@ -348,6 +350,7 @@ static void sse_event_add_to_list(struct sse_hart_state *state,
*/
static int sse_event_disable(struct sse_hart_state *shs,
struct sbi_sse_event *e)
+ MUST_HOLD(&shs->enabled_event_lock)
{
if (sse_event_state(e) != SBI_SSE_STATE_ENABLED)
return SBI_EINVALID_STATE;
@@ -781,6 +784,7 @@ static int sse_inject_event(uint32_t event_id, unsigned long hartid)
*/
static int sse_event_enable(struct sse_hart_state *shs,
struct sbi_sse_event *e)
+ MUST_HOLD(&shs->enabled_event_lock)
{
if (sse_event_state(e) != SBI_SSE_STATE_REGISTERED)
return SBI_EINVALID_STATE;
@@ -801,6 +805,7 @@ static int sse_event_complete(struct sse_hart_state *shs,
struct sbi_sse_event *e,
struct sbi_trap_regs *regs,
struct sbi_ecall_return *out)
+ MUST_HOLD(&shs->enabled_event_lock)
{
if (sse_event_state(e) != SBI_SSE_STATE_RUNNING)
return SBI_EINVALID_STATE;
@@ -1175,6 +1180,7 @@ static int sse_global_init()
}
static void sse_local_init(struct sse_hart_state *shs)
+ NO_THREAD_SAFETY_ANALYSIS
{
unsigned int ev = 0;
struct sse_event_info *info;
--
2.51.0
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v2 13/14] lib: test: disable TSA for spinlock tests
2026-09-09 16:23 [PATCH v2 00/14] Add clang Thread Safety Analysis (TSA) support Carlos López
` (11 preceding siblings ...)
2026-09-09 16:23 ` [PATCH v2 12/14] lib: sbi_sse: add TSA annotations Carlos López
@ 2026-09-09 16:23 ` Carlos López
2026-09-09 16:23 ` [PATCH v2 14/14] Makefile: enable Thread Safety Analysis Carlos López
13 siblings, 0 replies; 15+ messages in thread
From: Carlos López @ 2026-09-09 16:23 UTC (permalink / raw)
To: opensbi; +Cc: Carlos López
The spinlock tests deliberately use unconventional locking patterns to
test edge cases. Disable thread safety analysis for them so that they
don't generate false positives when the feature is enabled.
Signed-off-by: Carlos López <carlos.lopezr4096@gmail.com>
---
lib/sbi/tests/riscv_locks_test.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/lib/sbi/tests/riscv_locks_test.c b/lib/sbi/tests/riscv_locks_test.c
index 7894c4e9873c..2cbba3da8b6b 100644
--- a/lib/sbi/tests/riscv_locks_test.c
+++ b/lib/sbi/tests/riscv_locks_test.c
@@ -4,6 +4,7 @@
static spinlock_t test_lock = SPIN_LOCK_INITIALIZER;
static void spin_lock_test(struct sbiunit_test_case *test)
+ NO_THREAD_SAFETY_ANALYSIS
{
/* We don't want to accidentally get locked */
SBIUNIT_ASSERT(test, !spin_lock_check(&test_lock));
@@ -16,6 +17,7 @@ static void spin_lock_test(struct sbiunit_test_case *test)
}
static void spin_trylock_fail(struct sbiunit_test_case *test)
+ NO_THREAD_SAFETY_ANALYSIS
{
/* We don't want to accidentally get locked */
SBIUNIT_ASSERT(test, !spin_lock_check(&test_lock));
@@ -26,6 +28,7 @@ static void spin_trylock_fail(struct sbiunit_test_case *test)
}
static void spin_trylock_success(struct sbiunit_test_case *test)
+ NO_THREAD_SAFETY_ANALYSIS
{
SBIUNIT_EXPECT(test, spin_trylock(&test_lock));
spin_unlock(&test_lock);
--
2.51.0
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v2 14/14] Makefile: enable Thread Safety Analysis
2026-09-09 16:23 [PATCH v2 00/14] Add clang Thread Safety Analysis (TSA) support Carlos López
` (12 preceding siblings ...)
2026-09-09 16:23 ` [PATCH v2 13/14] lib: test: disable TSA for spinlock tests Carlos López
@ 2026-09-09 16:23 ` Carlos López
13 siblings, 0 replies; 15+ messages in thread
From: Carlos López @ 2026-09-09 16:23 UTC (permalink / raw)
To: opensbi; +Cc: Carlos López
Now that all locking code has been properly annotated, enable clang's
Thread Safety Analysis.
Two flags are available, -Wthread-safety, and the more recent
-Wthread-safety-pointer. The former was introduced before clang gained
RISC-V support, so it is guaranteed to be available. The latter was
introduced in clang 21, so check if the provided compiler supports it
before enabling it.
Signed-off-by: Carlos López <carlos.lopezr4096@gmail.com>
---
Makefile | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/Makefile b/Makefile
index aebaa98c36c9..1b3333f3c2df 100644
--- a/Makefile
+++ b/Makefile
@@ -209,6 +209,9 @@ CC_SUPPORT_ZICSR_ZIFENCEI := $(shell $(CC) $(CLANG_TARGET) $(RELAX_FLAG) -nostdl
# Check whether the assembler and the compiler support the Vector extension
CC_SUPPORT_VECTOR := $(shell $(CC) $(CLANG_TARGET) $(RELAX_FLAG) -nostdlib -march=rv$(OPENSBI_CC_XLEN)gv -dM -E -x c /dev/null 2>&1 | grep -q riscv.*vector && echo y || echo n)
+# Check whether the compiler supports -Wthread-safety-pointer (clang >= 22)
+CC_SUPPORT_WTHREAD_SAFETY_POINTER := $(shell $(CC) $(CLANG_TARGET) $(RELAX_FLAG) -nostdlib -Wthread-safety-pointer -x c /dev/null -o /dev/null 2>&1 | grep -q "unknown warning" && echo n || echo y)
+
ifneq ($(OPENSBI_LD_PIE),y)
$(error Your linker does not support creating PIEs, opensbi requires this.)
endif
@@ -359,6 +362,10 @@ endif
ifeq ($(CC_IS_CLANG),y)
GENFLAGS += $(CLANG_TARGET)
GENFLAGS += -Wno-unused-command-line-argument
+GENFLAGS += -Wthread-safety
+ifeq ($(CC_SUPPORT_WTHREAD_SAFETY_POINTER),y)
+GENFLAGS += -Wthread-safety-pointer
+endif
endif
GENFLAGS += -I$(platform_src_dir)/include
GENFLAGS += -I$(include_dir)
--
2.51.0
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 15+ messages in thread
end of thread, other threads:[~2026-09-09 16:31 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-09 16:23 [PATCH v2 00/14] Add clang Thread Safety Analysis (TSA) support Carlos López
2026-09-09 16:23 ` [PATCH v2 01/14] include: sbi: add thread safety analysis macros Carlos López
2026-09-09 16:23 ` [PATCH v2 02/14] lib: sbi_locks: annotate spinlock APIs for TSA Carlos López
2026-09-09 16:23 ` [PATCH v2 03/14] lib: sbi_fifo: add TSA annotations Carlos López
2026-09-09 16:23 ` [PATCH v2 04/14] lib: sbi_heap: " Carlos López
2026-09-09 16:23 ` [PATCH v2 05/14] lib: sbi_scratch: " Carlos López
2026-09-09 16:23 ` [PATCH v2 06/14] lib: rpmi: " Carlos López
2026-09-09 16:23 ` [PATCH v2 07/14] lib: sbi_timer: " Carlos López
2026-09-09 16:23 ` [PATCH v2 08/14] lib: htif: " Carlos López
2026-09-09 16:23 ` [PATCH v2 09/14] lib: sbi_domain: " Carlos López
2026-09-09 16:23 ` [PATCH v2 10/14] lib: sbi_sse: inline enable event locking Carlos López
2026-09-09 16:23 ` [PATCH v2 11/14] lib: sbi_sse: pass SSE hart state explicitly Carlos López
2026-09-09 16:23 ` [PATCH v2 12/14] lib: sbi_sse: add TSA annotations Carlos López
2026-09-09 16:23 ` [PATCH v2 13/14] lib: test: disable TSA for spinlock tests Carlos López
2026-09-09 16:23 ` [PATCH v2 14/14] Makefile: enable Thread Safety Analysis Carlos López
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox