Thread Safety Analysis and the Linux kernel
Marco Elver <[email protected]>
| Newsgroups | org.kernel.vger.linux-toolchains,dev.linux.lists.llvm |
|---|---|
| Message-ID | <CANpmjNPquO=W1JAh1FNQb8pMQjgeZAKCPQUAd7qUg=5pjJ6x=Q@mail.gmail.com> |
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/[email protected]/ Peter Zijlstra's feedback: https://lore.kernel.org/all/[email protected]/ -- 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/[email protected]/ -- 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/[email protected]/ ] 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