On OS X, there are other-than-pthread locking APIs that are used quite extensively - OSSpinLock and os_lock_lock. Let's add interceptors for those.
Details
Diff Detail
- Repository
- rL LLVM
Event Timeline
lib/tsan/rtl/tsan_platform_mac.cc | ||
---|---|---|
190 ↗ | (On Diff #41143) | This all should go into tsan_interceptors_mac.cc. |
191 ↗ | (On Diff #41143) | I wonder whether this interceptors can come when thr->is_dead? Not sure how widely os_lock_lock is used, maybe it needs the same. |
test/tsan/Darwin/osspinlock-norace.cc | ||
1 ↗ | (On Diff #41143) | please also add a similar test for os_lock_lock |
Updating patch to move interceptors into tsan_interceptors_mac.cc, added checks for thr->is_dead.
However, I also needed to change calls to MutexLock/MutexUnlock to just Acquire/Release, because they are used as a low-level primitive in the implementation of pthread mutexes and it caused false "double-locked mutex" warnings.
test/tsan/Darwin/osspinlock-norace.cc | ||
---|---|---|
2 ↗ | (On Diff #41740) | os_lock_lock actually isn't declared in public headers, so we can't have a test for it without manually declaring the functions and structures. However, the Obj-C runtime uses os_lock_lock heavily, so any Obj-C code will exercise the wrappers for os_lock_lock. |
LGTM
But MutexLock/MutexUnlock annotations are actually super useful for several reasons:
- they allow to detect deadlocks
- the allow to detect unsafe publication of objects with mutexes (which are usually undetectable otherwise, because a first mutex lock synchronizes the rest of the accesses)
- they allow to detect mutex unlock racing with free (which is a very frequent bug: last touch of object is an unlock)
- they allow to print sets of locked mutexes in reports
- they allow to report misuses of mutexes
and there can be other reasons and future improvements.
So please do MutexLock/MutexUnlock in a subsequent patch. The issue with double lock is not specific to only these mutexes. Go mutexes are also just zero chunks of memory without an explicit ctor. Java mutexes are the same. Tsan also allows to annotate user mutexes, which well can well be the same.
I see that in java interface (tsan_interface_java.cc) I do the following hack to set recursive flag on mutex:
MutexCreate(thr, pc, addr, true, true, true); MutexLock(thr, pc, addr);
This is somewhat ugly and slow. I was thinking about a better solution to allow MutexLock to also update mutex flags. But the complication here is that for pthread mutexes/condvars we don't know whether the mutex is recursive or not. I think we need something along the following lines. MutexLocks accepts a tri-state recursive flag which can be Yes, No or DontKnow. If it DontKnow then we assume that MutexCreate has initialized it. If it is Yes or No then we update the mutex flag. Should not be too difficult to do, there are few existing callers but for them you can just pass DontKnow as it won't change existing behavior.
Does it sound good to you?
OK, I'll try to extract a test case where I see the issue and then replace Acquire/Release with MutexLock/MutexUnlock.