summaryrefslogtreecommitdiff
path: root/lib/tsan/rtl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/tsan/rtl')
-rw-r--r--lib/tsan/rtl/tsan_interceptors.cc50
-rw-r--r--lib/tsan/rtl/tsan_interceptors.h4
-rw-r--r--lib/tsan/rtl/tsan_interceptors_mac.cc2
-rw-r--r--lib/tsan/rtl/tsan_platform.h38
-rw-r--r--lib/tsan/rtl/tsan_rtl.cc4
-rw-r--r--lib/tsan/rtl/tsan_rtl.h8
-rw-r--r--lib/tsan/rtl/tsan_rtl_thread.cc6
7 files changed, 79 insertions, 33 deletions
diff --git a/lib/tsan/rtl/tsan_interceptors.cc b/lib/tsan/rtl/tsan_interceptors.cc
index 5e64d11f3..cc6dab8f1 100644
--- a/lib/tsan/rtl/tsan_interceptors.cc
+++ b/lib/tsan/rtl/tsan_interceptors.cc
@@ -53,6 +53,8 @@ using namespace __tsan; // NOLINT
#define stdout ((char*)&__sF + (__sF_size * 1))
#define stderr ((char*)&__sF + (__sF_size * 2))
+#define nanosleep __nanosleep50
+#define vfork __vfork14
#endif
#if SANITIZER_ANDROID
@@ -226,6 +228,16 @@ void InitializeLibIgnore() {
libignore()->OnLibraryLoaded(0);
}
+// The following two hooks can be used by for cooperative scheduling when
+// locking.
+#ifdef TSAN_EXTERNAL_HOOKS
+void OnPotentiallyBlockingRegionBegin();
+void OnPotentiallyBlockingRegionEnd();
+#else
+SANITIZER_WEAK_CXX_DEFAULT_IMPL void OnPotentiallyBlockingRegionBegin() {}
+SANITIZER_WEAK_CXX_DEFAULT_IMPL void OnPotentiallyBlockingRegionEnd() {}
+#endif
+
} // namespace __tsan
static ThreadSignalContext *SigCtx(ThreadState *thr) {
@@ -864,6 +876,8 @@ TSAN_INTERCEPTOR(int, posix_memalign, void **memptr, uptr align, uptr sz) {
// Used in thread-safe function static initialization.
STDCXX_INTERCEPTOR(int, __cxa_guard_acquire, atomic_uint32_t *g) {
SCOPED_INTERCEPTOR_RAW(__cxa_guard_acquire, g);
+ OnPotentiallyBlockingRegionBegin();
+ auto on_exit = at_scope_exit(&OnPotentiallyBlockingRegionEnd);
for (;;) {
u32 cmp = atomic_load(g, memory_order_acquire);
if (cmp == 0) {
@@ -1042,6 +1056,35 @@ TSAN_INTERCEPTOR(int, pthread_detach, void *th) {
return res;
}
+#if SANITIZER_LINUX
+TSAN_INTERCEPTOR(int, pthread_tryjoin_np, void *th, void **ret) {
+ SCOPED_TSAN_INTERCEPTOR(pthread_tryjoin_np, th, ret);
+ int tid = ThreadTid(thr, pc, (uptr)th);
+ ThreadIgnoreBegin(thr, pc);
+ int res = REAL(pthread_tryjoin_np)(th, ret);
+ ThreadIgnoreEnd(thr, pc);
+ if (res == 0)
+ ThreadJoin(thr, pc, tid);
+ else
+ ThreadNotJoined(thr, pc, tid, (uptr)th);
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, pthread_timedjoin_np, void *th, void **ret,
+ const struct timespec *abstime) {
+ SCOPED_TSAN_INTERCEPTOR(pthread_timedjoin_np, th, ret, abstime);
+ int tid = ThreadTid(thr, pc, (uptr)th);
+ ThreadIgnoreBegin(thr, pc);
+ int res = BLOCK_REAL(pthread_timedjoin_np)(th, ret, abstime);
+ ThreadIgnoreEnd(thr, pc);
+ if (res == 0)
+ ThreadJoin(thr, pc, tid);
+ else
+ ThreadNotJoined(thr, pc, tid, (uptr)th);
+ return res;
+}
+#endif
+
// Problem:
// NPTL implementation of pthread_cond has 2 versions (2.2.5 and 2.3.2).
// pthread_cond_t has different size in the different versions.
@@ -2560,6 +2603,8 @@ TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_wrlock, void *m)
TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_trywrlock, void *m)
TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_unlock, void *m)
TSAN_INTERCEPTOR_NETBSD_ALIAS_THR(int, once, void *o, void (*f)())
+TSAN_INTERCEPTOR_NETBSD_ALIAS_THR2(int, sigsetmask, sigmask, int a, void *b,
+ void *c)
namespace __tsan {
@@ -2636,6 +2681,10 @@ void InitializeInterceptors() {
TSAN_INTERCEPT(pthread_create);
TSAN_INTERCEPT(pthread_join);
TSAN_INTERCEPT(pthread_detach);
+ #if SANITIZER_LINUX
+ TSAN_INTERCEPT(pthread_tryjoin_np);
+ TSAN_INTERCEPT(pthread_timedjoin_np);
+ #endif
TSAN_INTERCEPT_VER(pthread_cond_init, PTHREAD_ABI_BASE);
TSAN_INTERCEPT_VER(pthread_cond_signal, PTHREAD_ABI_BASE);
@@ -2769,6 +2818,7 @@ void InitializeInterceptors() {
TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_trywrlock);
TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_unlock);
TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS_THR(once);
+ TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS_THR(sigsetmask);
FdInit();
}
diff --git a/lib/tsan/rtl/tsan_interceptors.h b/lib/tsan/rtl/tsan_interceptors.h
index 959a39465..763b46b88 100644
--- a/lib/tsan/rtl/tsan_interceptors.h
+++ b/lib/tsan/rtl/tsan_interceptors.h
@@ -56,9 +56,13 @@ LibIgnore *libignore();
# define TSAN_INTERCEPTOR_NETBSD_ALIAS_THR(ret, func, ...) \
TSAN_INTERCEPTOR(ret, __libc_thr_##func, __VA_ARGS__) \
ALIAS(WRAPPER_NAME(pthread_##func));
+# define TSAN_INTERCEPTOR_NETBSD_ALIAS_THR2(ret, func, func2, ...) \
+ TSAN_INTERCEPTOR(ret, __libc_thr_##func, __VA_ARGS__) \
+ ALIAS(WRAPPER_NAME(pthread_##func2));
#else
# define TSAN_INTERCEPTOR_NETBSD_ALIAS(ret, func, ...)
# define TSAN_INTERCEPTOR_NETBSD_ALIAS_THR(ret, func, ...)
+# define TSAN_INTERCEPTOR_NETBSD_ALIAS_THR2(ret, func, func2, ...)
#endif
#endif // TSAN_INTERCEPTORS_H
diff --git a/lib/tsan/rtl/tsan_interceptors_mac.cc b/lib/tsan/rtl/tsan_interceptors_mac.cc
index b58e6b707..5e8b58fc2 100644
--- a/lib/tsan/rtl/tsan_interceptors_mac.cc
+++ b/lib/tsan/rtl/tsan_interceptors_mac.cc
@@ -326,7 +326,7 @@ TSAN_INTERCEPTOR(int, objc_sync_enter, void *obj) {
}
TSAN_INTERCEPTOR(int, objc_sync_exit, void *obj) {
- SCOPED_TSAN_INTERCEPTOR(objc_sync_enter, obj);
+ SCOPED_TSAN_INTERCEPTOR(objc_sync_exit, obj);
if (obj) Release(thr, pc, SyncAddressForObjCObject(obj));
return REAL(objc_sync_exit)(obj);
}
diff --git a/lib/tsan/rtl/tsan_platform.h b/lib/tsan/rtl/tsan_platform.h
index 70ae6170a..8303c2418 100644
--- a/lib/tsan/rtl/tsan_platform.h
+++ b/lib/tsan/rtl/tsan_platform.h
@@ -473,7 +473,7 @@ struct Mapping47 {
6200 0000 0000 - 8000 0000 0000: -
*/
-struct Mapping48 {
+struct Mapping {
static const uptr kMetaShadowBeg = 0x300000000000ull;
static const uptr kMetaShadowEnd = 0x400000000000ull;
static const uptr kTraceMemBeg = 0x600000000000ull;
@@ -549,12 +549,10 @@ uptr MappingImpl(void) {
template<int Type>
uptr MappingArchImpl(void) {
-#if defined(__aarch64__) && !defined(__APPLE__)
+#if defined(__aarch64__) && !defined(__APPLE__) && !SANITIZER_GO
switch (vmaSize) {
-#if !SANITIZER_GO
case 39: return MappingImpl<Mapping39, Type>();
case 42: return MappingImpl<Mapping42, Type>();
-#endif
case 48: return MappingImpl<Mapping48, Type>();
}
DCHECK(0);
@@ -708,12 +706,10 @@ bool IsAppMemImpl(uptr mem) {
ALWAYS_INLINE
bool IsAppMem(uptr mem) {
-#if defined(__aarch64__) && !defined(__APPLE__)
+#if defined(__aarch64__) && !defined(__APPLE__) && !SANITIZER_GO
switch (vmaSize) {
-#if !SANITIZER_GO
case 39: return IsAppMemImpl<Mapping39>(mem);
case 42: return IsAppMemImpl<Mapping42>(mem);
-#endif
case 48: return IsAppMemImpl<Mapping48>(mem);
}
DCHECK(0);
@@ -741,12 +737,10 @@ bool IsShadowMemImpl(uptr mem) {
ALWAYS_INLINE
bool IsShadowMem(uptr mem) {
-#if defined(__aarch64__) && !defined(__APPLE__)
+#if defined(__aarch64__) && !defined(__APPLE__) && !SANITIZER_GO
switch (vmaSize) {
-#if !SANITIZER_GO
case 39: return IsShadowMemImpl<Mapping39>(mem);
case 42: return IsShadowMemImpl<Mapping42>(mem);
-#endif
case 48: return IsShadowMemImpl<Mapping48>(mem);
}
DCHECK(0);
@@ -774,12 +768,10 @@ bool IsMetaMemImpl(uptr mem) {
ALWAYS_INLINE
bool IsMetaMem(uptr mem) {
-#if defined(__aarch64__) && !defined(__APPLE__)
+#if defined(__aarch64__) && !defined(__APPLE__) && !SANITIZER_GO
switch (vmaSize) {
-#if !SANITIZER_GO
case 39: return IsMetaMemImpl<Mapping39>(mem);
case 42: return IsMetaMemImpl<Mapping42>(mem);
-#endif
case 48: return IsMetaMemImpl<Mapping48>(mem);
}
DCHECK(0);
@@ -817,12 +809,10 @@ uptr MemToShadowImpl(uptr x) {
ALWAYS_INLINE
uptr MemToShadow(uptr x) {
-#if defined(__aarch64__) && !defined(__APPLE__)
+#if defined(__aarch64__) && !defined(__APPLE__) && !SANITIZER_GO
switch (vmaSize) {
-#if !SANITIZER_GO
case 39: return MemToShadowImpl<Mapping39>(x);
case 42: return MemToShadowImpl<Mapping42>(x);
-#endif
case 48: return MemToShadowImpl<Mapping48>(x);
}
DCHECK(0);
@@ -862,12 +852,10 @@ u32 *MemToMetaImpl(uptr x) {
ALWAYS_INLINE
u32 *MemToMeta(uptr x) {
-#if defined(__aarch64__) && !defined(__APPLE__)
+#if defined(__aarch64__) && !defined(__APPLE__) && !SANITIZER_GO
switch (vmaSize) {
-#if !SANITIZER_GO
case 39: return MemToMetaImpl<Mapping39>(x);
case 42: return MemToMetaImpl<Mapping42>(x);
-#endif
case 48: return MemToMetaImpl<Mapping48>(x);
}
DCHECK(0);
@@ -920,12 +908,10 @@ uptr ShadowToMemImpl(uptr s) {
ALWAYS_INLINE
uptr ShadowToMem(uptr s) {
-#if defined(__aarch64__) && !defined(__APPLE__)
+#if defined(__aarch64__) && !defined(__APPLE__) && !SANITIZER_GO
switch (vmaSize) {
-#if !SANITIZER_GO
case 39: return ShadowToMemImpl<Mapping39>(s);
case 42: return ShadowToMemImpl<Mapping42>(s);
-#endif
case 48: return ShadowToMemImpl<Mapping48>(s);
}
DCHECK(0);
@@ -961,12 +947,10 @@ uptr GetThreadTraceImpl(int tid) {
ALWAYS_INLINE
uptr GetThreadTrace(int tid) {
-#if defined(__aarch64__) && !defined(__APPLE__)
+#if defined(__aarch64__) && !defined(__APPLE__) && !SANITIZER_GO
switch (vmaSize) {
-#if !SANITIZER_GO
case 39: return GetThreadTraceImpl<Mapping39>(tid);
case 42: return GetThreadTraceImpl<Mapping42>(tid);
-#endif
case 48: return GetThreadTraceImpl<Mapping48>(tid);
}
DCHECK(0);
@@ -997,12 +981,10 @@ uptr GetThreadTraceHeaderImpl(int tid) {
ALWAYS_INLINE
uptr GetThreadTraceHeader(int tid) {
-#if defined(__aarch64__) && !defined(__APPLE__)
+#if defined(__aarch64__) && !defined(__APPLE__) && !SANITIZER_GO
switch (vmaSize) {
-#if !SANITIZER_GO
case 39: return GetThreadTraceHeaderImpl<Mapping39>(tid);
case 42: return GetThreadTraceHeaderImpl<Mapping42>(tid);
-#endif
case 48: return GetThreadTraceHeaderImpl<Mapping48>(tid);
}
DCHECK(0);
diff --git a/lib/tsan/rtl/tsan_rtl.cc b/lib/tsan/rtl/tsan_rtl.cc
index 584122292..f038e9682 100644
--- a/lib/tsan/rtl/tsan_rtl.cc
+++ b/lib/tsan/rtl/tsan_rtl.cc
@@ -359,7 +359,9 @@ void Initialize(ThreadState *thr) {
CheckASLR();
InitializeFlags(&ctx->flags, options);
AvoidCVE_2016_2143();
- InitializePlatformEarly();
+ __sanitizer::InitializePlatformEarly();
+ __tsan::InitializePlatformEarly();
+
#if !SANITIZER_GO
// Re-exec ourselves if we need to set additional env or command line args.
MaybeReexec();
diff --git a/lib/tsan/rtl/tsan_rtl.h b/lib/tsan/rtl/tsan_rtl.h
index 523b69aaa..60e6f82f7 100644
--- a/lib/tsan/rtl/tsan_rtl.h
+++ b/lib/tsan/rtl/tsan_rtl.h
@@ -59,15 +59,16 @@ struct MapUnmapCallback;
static const uptr kAllocatorRegionSizeLog = 20;
static const uptr kAllocatorNumRegions =
SANITIZER_MMAP_RANGE_SIZE >> kAllocatorRegionSizeLog;
-typedef TwoLevelByteMap<(kAllocatorNumRegions >> 12), 1 << 12,
- MapUnmapCallback> ByteMap;
+using ByteMap = TwoLevelByteMap<(kAllocatorNumRegions >> 12), 1 << 12,
+ LocalAddressSpaceView, MapUnmapCallback>;
struct AP32 {
static const uptr kSpaceBeg = 0;
static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE;
static const uptr kMetadataSize = 0;
typedef __sanitizer::CompactSizeClassMap SizeClassMap;
static const uptr kRegionSizeLog = kAllocatorRegionSizeLog;
- typedef __tsan::ByteMap ByteMap;
+ using AddressSpaceView = LocalAddressSpaceView;
+ using ByteMap = __tsan::ByteMap;
typedef __tsan::MapUnmapCallback MapUnmapCallback;
static const uptr kFlags = 0;
};
@@ -772,6 +773,7 @@ void ThreadFinalize(ThreadState *thr);
void ThreadSetName(ThreadState *thr, const char *name);
int ThreadCount(ThreadState *thr);
void ProcessPendingSignals(ThreadState *thr);
+void ThreadNotJoined(ThreadState *thr, uptr pc, int tid, uptr uid);
Processor *ProcCreate();
void ProcDestroy(Processor *proc);
diff --git a/lib/tsan/rtl/tsan_rtl_thread.cc b/lib/tsan/rtl/tsan_rtl_thread.cc
index e4d65b9a9..766a0f5a5 100644
--- a/lib/tsan/rtl/tsan_rtl_thread.cc
+++ b/lib/tsan/rtl/tsan_rtl_thread.cc
@@ -312,6 +312,12 @@ void ThreadDetach(ThreadState *thr, uptr pc, int tid) {
ctx->thread_registry->DetachThread(tid, thr);
}
+void ThreadNotJoined(ThreadState *thr, uptr pc, int tid, uptr uid) {
+ CHECK_GT(tid, 0);
+ CHECK_LT(tid, kMaxTid);
+ ctx->thread_registry->SetThreadUserId(tid, uid);
+}
+
void ThreadSetName(ThreadState *thr, const char *name) {
ctx->thread_registry->SetThreadName(thr->tid, name);
}