Thread Safety Analysis and the Linux kernel

Marco Elver
2025-03-05T11:48:03Z

Hi Aaron ^ 2,

[+Cc a bunch of folks that were involved in discussions.]

After sending v2 of the -Wthread-safety / Capability Analysis patches
for the Linux kernel [1], a number of concrete improvements to
-Wthread-safety will be required sooner or later. It is unclear if
they are blockers to the Linux kernel's adoption because the feature
is currently designed as "opt-in per subsystem", but it's clear the
current state of things is not ideal.

[1] https://lore.kernel.org/all/20250304092417.2873893-1-elver@google.com/

Peter Zijlstra's feedback:
https://lore.kernel.org/all/20250305112041.GA16878@noisy.programming.kicks-ass.net/
-- much of which led to the below requests. Peter also managed to
crash Clang, but that's probably unrelated to -Wthread-safety
directly: https://github.com/llvm/llvm-project/issues/129873

More straightforward requests:

1. Re-entrant acquires: rcu_read_lock(), preempt_disable(), etc. are
all re-entrant locks. My proposal is to introduce an attribute that
can be added to "ACQUIRE(..)" annotated functions to indicate they are
re-entrant. Release-count needs to then match acquire-count to fully
release a capability.

2. Basic alias analysis, e.g. when storing a pointer to a lock in a
function-local variable. [Complaint in:
https://lore.kernel.org/all/569186c5-8663-43df-a01c-d543f57ce5ca@kernel.org/
-- quote: "Fix the analyzer instead."]

3. Ability to refer to locks in returned reference/pointer. For example:
struct foo *ret_lock_struct(void) ACQUIRE(return->somelock);
struct foo *try_ret_lock_struct(void) TRY_ACQUIRE(1,
return->somelock); // locked if non-NULL
I expect this also requires basic alias analysis to work so that
assigning the returned pointer to a function-local variable and then
later use in an unlock function works as expected.

More complex requests:

4. The ability to deal with conditional locking with return values
that are not just true/non-zero and false/zero. A concrete case here
is that a lot of functions return error codes, and if the error code
is < 0, no lock is taken. If the error code is >= 0, the lock is
taken. [ Source:
https://lore.kernel.org/all/569186c5-8663-43df-a01c-d543f57ce5ca@kernel.org/
]

5. Better control-flow handling. Basic understanding of conditional
locking, which is explicitly ruled out in:
https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#conditional-locks
- however, if there's some way to even get basic support, would vastly
improve things for the kernel.

Some of these are more complex than others, and any hints how we might
go about this are appreciated. I'm happy to try and implement some of
them, but if you find that you already know exactly how you'd like an
implementation to look like, rough drafts that we can take over and
polish would be very very helpful, too!

In general, the Linux kernel has some of the most complex
synchronization patterns with numerous synchronization primitives.
Getting this to work for a good chunk of the more complex
synchronization code in the kernel will be quite the achievement if we
get there. :-)

Thanks,
-- Marco