diff options
author | Dmitry Vyukov <dvyukov@google.com> | 2017-05-01 10:01:13 +0000 |
---|---|---|
committer | Dmitry Vyukov <dvyukov@google.com> | 2017-05-01 10:01:13 +0000 |
commit | 1531d487bd209ea8b183db067a0a2161a5db9b4b (patch) | |
tree | ec7dc795a27875eca1f21a6df88d2d9f40d8e303 | |
parent | d816020bbf906c6452e8911151abb688176c2ef5 (diff) |
tsan: support linker init flag in __tsan_mutex_destroy
For a linker init mutex with lazy flag setup
(no __tsan_mutex_create call), it is possible that
no lock/unlock happened before the destroy call.
Then when destroy runs we still don't know that
it is a linker init mutex and will emulate a memory write.
This in turn can lead to false positives as the mutex
is in fact linker initialized.
Support linker init flag in destroy annotation to resolve this.
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@301795 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/sanitizer/tsan_interface.h | 3 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_interface_ann.cc | 2 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_rtl.h | 2 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_rtl_mutex.cc | 4 |
4 files changed, 6 insertions, 5 deletions
diff --git a/include/sanitizer/tsan_interface.h b/include/sanitizer/tsan_interface.h index 45e54f758..a0c702638 100644 --- a/include/sanitizer/tsan_interface.h +++ b/include/sanitizer/tsan_interface.h @@ -68,7 +68,8 @@ const unsigned __tsan_mutex_recursive_unlock = 1 << 7; void __tsan_mutex_create(void *addr, unsigned flags); // Annotate destruction of a mutex. -// Supported flags: none. +// Supported flags: +// - __tsan_mutex_linker_init void __tsan_mutex_destroy(void *addr, unsigned flags); // Annotate start of lock operation. diff --git a/lib/tsan/rtl/tsan_interface_ann.cc b/lib/tsan/rtl/tsan_interface_ann.cc index 810c84025..45ec45bbd 100644 --- a/lib/tsan/rtl/tsan_interface_ann.cc +++ b/lib/tsan/rtl/tsan_interface_ann.cc @@ -471,7 +471,7 @@ void __tsan_mutex_create(void *m, unsigned flagz) { INTERFACE_ATTRIBUTE void __tsan_mutex_destroy(void *m, unsigned flagz) { SCOPED_ANNOTATION(__tsan_mutex_destroy); - MutexDestroy(thr, pc, (uptr)m); + MutexDestroy(thr, pc, (uptr)m, flagz); } INTERFACE_ATTRIBUTE diff --git a/lib/tsan/rtl/tsan_rtl.h b/lib/tsan/rtl/tsan_rtl.h index cc60eb6db..8bf1c191a 100644 --- a/lib/tsan/rtl/tsan_rtl.h +++ b/lib/tsan/rtl/tsan_rtl.h @@ -763,7 +763,7 @@ void ProcUnwire(Processor *proc, ThreadState *thr); // Note: the parameter is called flagz, because flags is already taken // by the global function that returns flags. void MutexCreate(ThreadState *thr, uptr pc, uptr addr, u32 flagz = 0); -void MutexDestroy(ThreadState *thr, uptr pc, uptr addr); +void MutexDestroy(ThreadState *thr, uptr pc, uptr addr, u32 flagz = 0); void MutexPreLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz = 0); void MutexPostLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz = 0, int rec = 1); diff --git a/lib/tsan/rtl/tsan_rtl_mutex.cc b/lib/tsan/rtl/tsan_rtl_mutex.cc index 086b28927..54938f37e 100644 --- a/lib/tsan/rtl/tsan_rtl_mutex.cc +++ b/lib/tsan/rtl/tsan_rtl_mutex.cc @@ -78,13 +78,13 @@ void MutexCreate(ThreadState *thr, uptr pc, uptr addr, u32 flagz) { s->mtx.Unlock(); } -void MutexDestroy(ThreadState *thr, uptr pc, uptr addr) { +void MutexDestroy(ThreadState *thr, uptr pc, uptr addr, u32 flagz) { DPrintf("#%d: MutexDestroy %zx\n", thr->tid, addr); StatInc(thr, StatMutexDestroy); SyncVar *s = ctx->metamap.GetIfExistsAndLock(addr, true); if (s == 0) return; - if (s->IsFlagSet(MutexFlagLinkerInit)) { + if ((flagz & MutexFlagLinkerInit) || s->IsFlagSet(MutexFlagLinkerInit)) { // Destroy is no-op for linker-initialized mutexes. s->mtx.Unlock(); return; |