This is an archive of the discontinued LLVM Phabricator instance.

[tsan] Add interceptors for Darwin-specific locking APIs
ClosedPublic

Authored by kubamracek on Nov 25 2015, 7:54 AM.

Details

Summary

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.

Diff Detail

Repository
rL LLVM

Event Timeline

kubamracek updated this revision to Diff 41143.Nov 25 2015, 7:54 AM
kubamracek retitled this revision from to [tsan] Add interceptors for Darwin-specific locking APIs.
kubamracek updated this object.
kubamracek added reviewers: dvyukov, kcc, glider, samsonov.
dvyukov added inline comments.Nov 30 2015, 6:28 AM
lib/tsan/rtl/tsan_platform_mac.cc
190 ↗(On Diff #41143)

This all should go into tsan_interceptors_mac.cc.
tsan_platform_* is portability layer, not meant to contain any race-detection logic.
Also, tsan_platform_mac.cc is built in Go mode, but Go does not need any of these interceptors.

191 ↗(On Diff #41143)

I wonder whether this interceptors can come when thr->is_dead?
Add CHECK(!thr->is_dead) so that we are sure that it does not happen.

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

kubamracek updated this revision to Diff 41740.Dec 3 2015, 4:48 AM

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.

kubamracek added inline comments.Dec 3 2015, 4:58 AM
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.

dvyukov accepted this revision.Dec 3 2015, 6:35 AM
dvyukov edited edge metadata.

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?

This revision is now accepted and ready to land.Dec 3 2015, 6:35 AM

So please do MutexLock/MutexUnlock in a subsequent patch. The issue with double lock is not specific to only these mutexes

OK, I'll try to extract a test case where I see the issue and then replace Acquire/Release with MutexLock/MutexUnlock.

This revision was automatically updated to reflect the committed changes.

OK, I'll try to extract a test case where I see the issue

Just lock it recursively?