[cfe-dev] Who is working on/has worked on Capability analysis (-Wthread-safety)?

Randell Jesup via cfe-dev cfe-dev at lists.llvm.org
Wed Nov 3 20:40:28 PDT 2021


On 10/31/2021 3:36 PM, Aaron Puchert wrote:
> Thanks for letting me know. (I barely follow the list.)
>>> On Sat, Oct 30, 2021 at 9:28 PM Randell Jesup via cfe-dev 
>>> <cfe-dev at lists.llvm.org> wrote:
>>>> One way to possibly handle the reader/writer vs readers case (where 
>>>> reads on the writing thread don't need to lock) would be to be able 
>>>> to say "guarded by this or that", in this case something like 
>>>> GUARDED_BY(mMutex, MainThread) (GUARDED_BY(mMutex || MainThread) ??).
>
> There has been some work on logical expressions in capability 
> attributes in 
> https://reviews.llvm.org/rG7c192b452fa2b3c63ed547e0ff88a5e62765b59f, 
> but I believe it's not functional yet. I thought about the semantics 
> of this a bit, but don't have a good understanding yet.
>
> If you want accesses to a resource to be protected, it's in general 
> not sufficient to have one of a set of capabilities. There can only be 
> one. What happens in this scenario is that there is a certain period 
> of time where the resource is exclusive to the main thread, and 
> another where it's only accessible via mutex (even if the main thread 
> were to access it). So maybe logical expressions aren't the right way 
> to understand this situation, but rather there should be different 
> types, one that has GUARDED_BY(MainThread) and another that has 
> GUARDED_BY(mMutex), and at some point we convert between them. In some 
> sense the protection regime changes throughout the lifetime, and for 
> static analysis that means we need a new (static) type.


Well, the example I gave doesn't match that, I believe.  This is a value 
only written on Thread 1, and read on Thread 1 and on other threads. The 
requirements for locking would be the lock around all writes (on thread 
1), and lock around all reads from threads *other* than thread 1.  Reads 
from Thread 1 don't need to lock, since they're on the only thread that 
ever writes to the value.   This is conceptually GUARDED_BY(mMutex || 
OnThread1).

The case you're referencing sounds more like "value is freely written 
and read on thread 1, then at some point later access to it is provided 
to other threads, and after that happens access is controlled by a 
mutex" - where the protection regime changes over time (and may also 
correlate with specific methods, like an Init() method).


We have another pattern that's interesting, where a method may use 
Maybe<MutexAutoLock> lock(std::in_place, mMutex); (Maybe<> is 
effectively std::optional).   This allows us to lock.reset() instead of 
using MutexAutoUnlock lock(mLock), which will lead to an extra 
lock/unlock pair compared to Maybe<> and lock.reset().

We also have an RAII MutexAutoTryLock class, which is like MutexAutoLock 
but does a trylock operation, and also you can convert it to bool to see 
if it obtained the lock.   I don't think this is easily representable in 
the current system.  (I'll note that we use it 4 times in our codebase, 
and 3 of those are in Mutext test code, so I don't care that much ;-) .)


Randell Jesup, Mozilla
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20211103/39d821c1/attachment.html>


More information about the cfe-dev mailing list