Thread Safety Analysis
include/tsa.h View source View on GitHubMacros around clang’s -Wthread-safety features. Does nothing on GCC
Use like this: struct list_head list TSA_GUARDED_BY(lock); struct spinlock lock;
NOTE
referencing a lock declared later in the struct is given by -fexperimental-late-parse-attributes
Functions
Section titled “Functions”tsa_owner_is_me
Section titled “tsa_owner_is_me”Macros
Section titled “Macros”TSA_CAPABILITY
Section titled “TSA_CAPABILITY”#define TSA_CAPABILITY(kind) source Expansion
#define TSA_CAPABILITY(kind) __attribute__((capability(kind))) TSA_GUARDED_BY
Section titled “TSA_GUARDED_BY”#define TSA_GUARDED_BY(...) source for regular data
Expansion
#define TSA_GUARDED_BY(...) __attribute__((guarded_by(__VA_ARGS__))) TSA_PTR_GUARDED_BY
Section titled “TSA_PTR_GUARDED_BY”#define TSA_PTR_GUARDED_BY(...) source This guards the data a POINTER points at, pointer itself is not guarded
Expansion
#define TSA_PTR_GUARDED_BY(...) __attribute__((pt_guarded_by(__VA_ARGS__))) Function verification
TSA_CALLER_HOLDS
Section titled “TSA_CALLER_HOLDS”#define TSA_CALLER_HOLDS(...) source Expansion
#define TSA_CALLER_HOLDS(...) __attribute__((requires_capability(__VA_ARGS__))) TSA_CALLER_HOLDS_SHARED
Section titled “TSA_CALLER_HOLDS_SHARED”#define TSA_CALLER_HOLDS_SHARED(...) source Expansion
#define TSA_CALLER_HOLDS_SHARED(...) \
__attribute__((requires_shared_capability(__VA_ARGS__))) TSA_EXCLUDED
Section titled “TSA_EXCLUDED”#define TSA_EXCLUDED(...) source Expansion
#define TSA_EXCLUDED(...) __attribute__((locks_excluded(__VA_ARGS__))) Lock primitives and wrappers
TSA_ACQUIRES
Section titled “TSA_ACQUIRES”#define TSA_ACQUIRES(...) source Expansion
#define TSA_ACQUIRES(...) __attribute__((acquire_capability(__VA_ARGS__))) TSA_ACQUIRES_SHARED
Section titled “TSA_ACQUIRES_SHARED”#define TSA_ACQUIRES_SHARED(...) source Expansion
#define TSA_ACQUIRES_SHARED(...) \
__attribute__((acquire_shared_capability(__VA_ARGS__))) TSA_RELEASES
Section titled “TSA_RELEASES”#define TSA_RELEASES(...) source Expansion
#define TSA_RELEASES(...) __attribute__((release_capability(__VA_ARGS__))) TSA_RELEASES_SHARED
Section titled “TSA_RELEASES_SHARED”#define TSA_RELEASES_SHARED(...) source Expansion
#define TSA_RELEASES_SHARED(...) \
__attribute__((release_shared_capability(__VA_ARGS__))) TSA_RELEASES_GENERIC
Section titled “TSA_RELEASES_GENERIC”#define TSA_RELEASES_GENERIC(...) source Releases whatever mode is held (rwlock unlock)
Expansion
#define TSA_RELEASES_GENERIC(...) \
__attribute__((release_generic_capability(__VA_ARGS__))) TSA_TRY_ACQUIRES
Section titled “TSA_TRY_ACQUIRES”#define TSA_TRY_ACQUIRES(ret, ...) source Expansion
#define TSA_TRY_ACQUIRES(ret, ...) \
__attribute__((try_acquire_capability(ret, __VA_ARGS__))) TSA_TRY_ACQUIRES_SHARED
Section titled “TSA_TRY_ACQUIRES_SHARED”#define TSA_TRY_ACQUIRES_SHARED(ret, ...) source Expansion
#define TSA_TRY_ACQUIRES_SHARED(ret, ...) \
__attribute__((try_acquire_shared_capability(ret, __VA_ARGS__))) TSA_ASSERT_CAPABILITY
Section titled “TSA_ASSERT_CAPABILITY”#define TSA_ASSERT_CAPABILITY(...) source Expansion
#define TSA_ASSERT_CAPABILITY(...) \
__attribute__((assert_capability(__VA_ARGS__))) TSA_ASSERT_SHARED_CAPABILITY
Section titled “TSA_ASSERT_SHARED_CAPABILITY”#define TSA_ASSERT_SHARED_CAPABILITY(...) source Expansion
#define TSA_ASSERT_SHARED_CAPABILITY(...) \
__attribute__((assert_shared_capability(__VA_ARGS__))) TSA_RETURNS_CAPABILITY
Section titled “TSA_RETURNS_CAPABILITY”#define TSA_RETURNS_CAPABILITY(cap) source function returns (a pointer to) this capability, for guards
Expansion
#define TSA_RETURNS_CAPABILITY(cap) __attribute__((lock_returned(cap))) TSA_ACQUIRED_AFTER
Section titled “TSA_ACQUIRED_AFTER”#define TSA_ACQUIRED_AFTER(...) source static ordering between sibling members or globals
Expansion
#define TSA_ACQUIRED_AFTER(...) __attribute__((acquired_after(__VA_ARGS__))) TSA_ACQUIRED_BEFORE
Section titled “TSA_ACQUIRED_BEFORE”#define TSA_ACQUIRED_BEFORE(...) source Expansion
#define TSA_ACQUIRED_BEFORE(...) __attribute__((acquired_before(__VA_ARGS__))) TSA_NO_ANALYSIS
Section titled “TSA_NO_ANALYSIS”#define TSA_NO_ANALYSIS __attribute__((no_thread_safety_analysis)) source escape hatch
TSA_UNSAFE
Section titled “TSA_UNSAFE”#define TSA_UNSAFE(expr) source For intentionally racy accesses and ganders
Expansion
#define TSA_UNSAFE(expr) \
({ \
_Pragma("clang diagnostic push"); \
_Pragma("clang diagnostic ignored \"-Wthread-safety-analysis\""); \
_Pragma("clang diagnostic ignored \"-Wthread-safety-pointer\""); \
__auto_type __tsa_unsafe_v = (expr); \
_Pragma("clang diagnostic pop"); \
__tsa_unsafe_v; \
}) TSA_DEFINE_ASSUME
Section titled “TSA_DEFINE_ASSUME”#define TSA_DEFINE_ASSUME(type) source tsa_unpublished(&o->lock) states that o is not reachable by anyone else yet, so we simply treat the lock as held for the rest of the function
Expansion
#define TSA_DEFINE_ASSUME(type) \
static inline cc_overloadable cc_always_inline cc_unused void \
tsa_unpublished_internal(type *cap) TSA_ASSERT_CAPABILITY(cap) { \
cc_ignore(cap); \
} tsa_unpublished
Section titled “tsa_unpublished”#define tsa_unpublished(cap) source Expansion
#define tsa_unpublished(cap) tsa_unpublished_internal(cap) TSA_CAPABILITY_DECLARE
Section titled “TSA_CAPABILITY_DECLARE”#define TSA_CAPABILITY_DECLARE(name, symbol) source Expansion
#define TSA_CAPABILITY_DECLARE(name, symbol) \
struct TSA_CAPABILITY(name) __##symbol##_ctx {}; \
extern struct __##symbol##_ctx symbol TSA_IRQL_TRACKS_SPINLOCKS
Section titled “TSA_IRQL_TRACKS_SPINLOCKS”#define TSA_IRQL_TRACKS_SPINLOCKS 1 source TSA_REENTRANT_CAPABILITY_DECLARE
Section titled “TSA_REENTRANT_CAPABILITY_DECLARE”#define TSA_REENTRANT_CAPABILITY_DECLARE(name, symbol) source Expansion
#define TSA_REENTRANT_CAPABILITY_DECLARE(name, symbol) \
struct TSA_CAPABILITY(name) \
__attribute__((reentrant_capability)) __##symbol##_ctx {}; \
extern struct __##symbol##_ctx symbol TSA_IRQL_TRACKS_SPINLOCKS
Section titled “TSA_IRQL_TRACKS_SPINLOCKS”#define TSA_IRQL_TRACKS_SPINLOCKS 0 source TSA_REENTRANT_CAPABILITY_DECLARE
Section titled “TSA_REENTRANT_CAPABILITY_DECLARE”#define TSA_REENTRANT_CAPABILITY_DECLARE(name, symbol) source Expansion
#define TSA_REENTRANT_CAPABILITY_DECLARE(name, symbol) \
TSA_CAPABILITY_DECLARE(name, symbol) TSA_ACQUIRES_SPIN
Section titled “TSA_ACQUIRES_SPIN”#define TSA_ACQUIRES_SPIN(lock) source Expansion
#define TSA_ACQUIRES_SPIN(lock) \
__attribute__((acquire_capability(lock, IRQL_RAISED))) TSA_RELEASES_SPIN
Section titled “TSA_RELEASES_SPIN”#define TSA_RELEASES_SPIN(lock) source Expansion
#define TSA_RELEASES_SPIN(lock) \
__attribute__((release_capability(lock, IRQL_RAISED))) TSA_TRY_ACQUIRES_SPIN
Section titled “TSA_TRY_ACQUIRES_SPIN”#define TSA_TRY_ACQUIRES_SPIN(ret, lock) source Expansion
#define TSA_TRY_ACQUIRES_SPIN(ret, lock) \
__attribute__((try_acquire_capability(ret, lock, IRQL_RAISED))) TSA_ACQUIRES_SPIN_IRQL
Section titled “TSA_ACQUIRES_SPIN_IRQL”#define TSA_ACQUIRES_SPIN_IRQL TSA_ACQUIRES(IRQL_RAISED) source TSA_RELEASES_SPIN_IRQL
Section titled “TSA_RELEASES_SPIN_IRQL”#define TSA_RELEASES_SPIN_IRQL TSA_RELEASES(IRQL_RAISED) source TSA_ACQUIRES_SPIN
Section titled “TSA_ACQUIRES_SPIN”#define TSA_ACQUIRES_SPIN(lock) source Expansion
#define TSA_ACQUIRES_SPIN(lock) TSA_ACQUIRES(lock) TSA_RELEASES_SPIN
Section titled “TSA_RELEASES_SPIN”#define TSA_RELEASES_SPIN(lock) source Expansion
#define TSA_RELEASES_SPIN(lock) TSA_RELEASES(lock) TSA_TRY_ACQUIRES_SPIN
Section titled “TSA_TRY_ACQUIRES_SPIN”#define TSA_TRY_ACQUIRES_SPIN(ret, lock) source Expansion
#define TSA_TRY_ACQUIRES_SPIN(ret, lock) TSA_TRY_ACQUIRES(ret, lock) TSA_ACQUIRES_SPIN_IRQL
Section titled “TSA_ACQUIRES_SPIN_IRQL”#define TSA_ACQUIRES_SPIN_IRQL source TSA_RELEASES_SPIN_IRQL
Section titled “TSA_RELEASES_SPIN_IRQL”#define TSA_RELEASES_SPIN_IRQL source TSA_ACQUIRES_IRQS
Section titled “TSA_ACQUIRES_IRQS”#define TSA_ACQUIRES_IRQS TSA_ACQUIRES(IRQS_DISABLED) source TSA_RELEASES_IRQS
Section titled “TSA_RELEASES_IRQS”#define TSA_RELEASES_IRQS TSA_RELEASES(IRQS_DISABLED) source TSA_ACQUIRES_IRQS_LOCK
Section titled “TSA_ACQUIRES_IRQS_LOCK”#define TSA_ACQUIRES_IRQS_LOCK(lock) source Expansion
#define TSA_ACQUIRES_IRQS_LOCK(lock) \
__attribute__((acquire_capability(lock, IRQS_DISABLED))) TSA_RELEASES_IRQS_LOCK
Section titled “TSA_RELEASES_IRQS_LOCK”#define TSA_RELEASES_IRQS_LOCK(lock) source Expansion
#define TSA_RELEASES_IRQS_LOCK(lock) \
__attribute__((release_capability(lock, IRQS_DISABLED))) TSA_MAY_SLEEP
Section titled “TSA_MAY_SLEEP”#define TSA_MAY_SLEEP source Expansion
#define TSA_MAY_SLEEP \
__attribute__((locks_excluded(IRQL_RAISED, IRQS_DISABLED))) TSA_ACQUIRES_IRQS
Section titled “TSA_ACQUIRES_IRQS”#define TSA_ACQUIRES_IRQS source TSA_RELEASES_IRQS
Section titled “TSA_RELEASES_IRQS”#define TSA_RELEASES_IRQS source TSA_ACQUIRES_IRQS_LOCK
Section titled “TSA_ACQUIRES_IRQS_LOCK”#define TSA_ACQUIRES_IRQS_LOCK(lock) source Expansion
#define TSA_ACQUIRES_IRQS_LOCK(lock) TSA_ACQUIRES(lock) TSA_RELEASES_IRQS_LOCK
Section titled “TSA_RELEASES_IRQS_LOCK”#define TSA_RELEASES_IRQS_LOCK(lock) source Expansion
#define TSA_RELEASES_IRQS_LOCK(lock) TSA_RELEASES(lock) TSA_MAY_SLEEP
Section titled “TSA_MAY_SLEEP”#define TSA_MAY_SLEEP TSA_EXCLUDED(IRQL_RAISED) source TSA_CAPABILITY
Section titled “TSA_CAPABILITY”#define TSA_CAPABILITY(kind) source Expansion
#define TSA_CAPABILITY(kind) TSA_GUARDED_BY
Section titled “TSA_GUARDED_BY”#define TSA_GUARDED_BY(...) source Expansion
#define TSA_GUARDED_BY(...) TSA_PT_GUARDED_BY
Section titled “TSA_PT_GUARDED_BY”#define TSA_PT_GUARDED_BY(...) source Expansion
#define TSA_PT_GUARDED_BY(...) TSA_CALLER_HOLDS
Section titled “TSA_CALLER_HOLDS”#define TSA_CALLER_HOLDS(...) source Expansion
#define TSA_CALLER_HOLDS(...) TSA_CALLER_HOLDS_SHARED
Section titled “TSA_CALLER_HOLDS_SHARED”#define TSA_CALLER_HOLDS_SHARED(...) source Expansion
#define TSA_CALLER_HOLDS_SHARED(...) TSA_EXCLUDED
Section titled “TSA_EXCLUDED”#define TSA_EXCLUDED(...) source Expansion
#define TSA_EXCLUDED(...) TSA_ACQUIRES
Section titled “TSA_ACQUIRES”#define TSA_ACQUIRES(...) source Expansion
#define TSA_ACQUIRES(...) TSA_ACQUIRES_SHARED
Section titled “TSA_ACQUIRES_SHARED”#define TSA_ACQUIRES_SHARED(...) source Expansion
#define TSA_ACQUIRES_SHARED(...) TSA_RELEASES
Section titled “TSA_RELEASES”#define TSA_RELEASES(...) source Expansion
#define TSA_RELEASES(...) TSA_RELEASES_SHARED
Section titled “TSA_RELEASES_SHARED”#define TSA_RELEASES_SHARED(...) source Expansion
#define TSA_RELEASES_SHARED(...) TSA_RELEASES_GENERIC
Section titled “TSA_RELEASES_GENERIC”#define TSA_RELEASES_GENERIC(...) source Expansion
#define TSA_RELEASES_GENERIC(...) TSA_TRY_ACQUIRES
Section titled “TSA_TRY_ACQUIRES”#define TSA_TRY_ACQUIRES(ret, ...) source Expansion
#define TSA_TRY_ACQUIRES(ret, ...) TSA_TRY_ACQUIRES_SHARED
Section titled “TSA_TRY_ACQUIRES_SHARED”#define TSA_TRY_ACQUIRES_SHARED(ret, ...) source Expansion
#define TSA_TRY_ACQUIRES_SHARED(ret, ...) TSA_ASSERT_CAPABILITY
Section titled “TSA_ASSERT_CAPABILITY”#define TSA_ASSERT_CAPABILITY(...) source Expansion
#define TSA_ASSERT_CAPABILITY(...) TSA_ASSERT_SHARED_CAPABILITY
Section titled “TSA_ASSERT_SHARED_CAPABILITY”#define TSA_ASSERT_SHARED_CAPABILITY(...) source Expansion
#define TSA_ASSERT_SHARED_CAPABILITY(...) TSA_RETURNS_CAPABILITY
Section titled “TSA_RETURNS_CAPABILITY”#define TSA_RETURNS_CAPABILITY(cap) source Expansion
#define TSA_RETURNS_CAPABILITY(cap) TSA_ACQUIRED_AFTER
Section titled “TSA_ACQUIRED_AFTER”#define TSA_ACQUIRED_AFTER(...) source Expansion
#define TSA_ACQUIRED_AFTER(...) TSA_ACQUIRED_BEFORE
Section titled “TSA_ACQUIRED_BEFORE”#define TSA_ACQUIRED_BEFORE(...) source Expansion
#define TSA_ACQUIRED_BEFORE(...) TSA_NO_ANALYSIS
Section titled “TSA_NO_ANALYSIS”#define TSA_NO_ANALYSIS source TSA_UNSAFE
Section titled “TSA_UNSAFE”#define TSA_UNSAFE(expr) source Expansion
#define TSA_UNSAFE(expr) (expr) TSA_DEFINE_ASSUME
Section titled “TSA_DEFINE_ASSUME”#define TSA_DEFINE_ASSUME(type) source Expansion
#define TSA_DEFINE_ASSUME(type) tsa_unpublished
Section titled “tsa_unpublished”#define tsa_unpublished(cap) source Expansion
#define tsa_unpublished(cap) ((void) (cap)) TSA_CAPABILITY_DECLARE
Section titled “TSA_CAPABILITY_DECLARE”#define TSA_CAPABILITY_DECLARE(name, symbol) source Expansion
#define TSA_CAPABILITY_DECLARE(name, symbol) TSA_IRQL_TRACKS_SPINLOCKS
Section titled “TSA_IRQL_TRACKS_SPINLOCKS”#define TSA_IRQL_TRACKS_SPINLOCKS 0 source TSA_REENTRANT_CAPABILITY_DECLARE
Section titled “TSA_REENTRANT_CAPABILITY_DECLARE”#define TSA_REENTRANT_CAPABILITY_DECLARE(name, symbol) source Expansion
#define TSA_REENTRANT_CAPABILITY_DECLARE(name, symbol) TSA_ACQUIRES_SPIN
Section titled “TSA_ACQUIRES_SPIN”#define TSA_ACQUIRES_SPIN(lock) source Expansion
#define TSA_ACQUIRES_SPIN(lock) TSA_RELEASES_SPIN
Section titled “TSA_RELEASES_SPIN”#define TSA_RELEASES_SPIN(lock) source Expansion
#define TSA_RELEASES_SPIN(lock) TSA_TRY_ACQUIRES_SPIN
Section titled “TSA_TRY_ACQUIRES_SPIN”#define TSA_TRY_ACQUIRES_SPIN(ret, lock) source Expansion
#define TSA_TRY_ACQUIRES_SPIN(ret, lock) TSA_ACQUIRES_SPIN_IRQL
Section titled “TSA_ACQUIRES_SPIN_IRQL”#define TSA_ACQUIRES_SPIN_IRQL source TSA_RELEASES_SPIN_IRQL
Section titled “TSA_RELEASES_SPIN_IRQL”#define TSA_RELEASES_SPIN_IRQL source TSA_ACQUIRES_IRQS
Section titled “TSA_ACQUIRES_IRQS”#define TSA_ACQUIRES_IRQS source TSA_RELEASES_IRQS
Section titled “TSA_RELEASES_IRQS”#define TSA_RELEASES_IRQS source TSA_ACQUIRES_IRQS_LOCK
Section titled “TSA_ACQUIRES_IRQS_LOCK”#define TSA_ACQUIRES_IRQS_LOCK(lock) source Expansion
#define TSA_ACQUIRES_IRQS_LOCK(lock) TSA_RELEASES_IRQS_LOCK
Section titled “TSA_RELEASES_IRQS_LOCK”#define TSA_RELEASES_IRQS_LOCK(lock) source Expansion
#define TSA_RELEASES_IRQS_LOCK(lock) TSA_MAY_SLEEP
Section titled “TSA_MAY_SLEEP”#define TSA_MAY_SLEEP source TSA_OWNER_TOKEN
Section titled “TSA_OWNER_TOKEN”#define TSA_OWNER_TOKEN(name) source Expansion
#define TSA_OWNER_TOKEN(name) struct tsa_owner name