summaryrefslogtreecommitdiff
path: root/libsanitizer/tsan
diff options
context:
space:
mode:
authorkcc <kcc@138bc75d-0d04-0410-961f-82ee72b054a4>2012-11-23 14:46:25 +0000
committerkcc <kcc@138bc75d-0d04-0410-961f-82ee72b054a4>2012-11-23 14:46:25 +0000
commit0d996a11d9b5be7a52d77016de51910146ceaa90 (patch)
treea354102cd1c27b09eefe0b04f517d4ecac5bc566 /libsanitizer/tsan
parenta46419387192ae39f45cfeca2ec0afe6f872956e (diff)
[libsanitizer] merge from upstream r168514
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@193756 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libsanitizer/tsan')
-rw-r--r--libsanitizer/tsan/Makefile.am1
-rw-r--r--libsanitizer/tsan/Makefile.in4
-rw-r--r--libsanitizer/tsan/tsan_clock.cc7
-rw-r--r--libsanitizer/tsan/tsan_clock.h2
-rw-r--r--libsanitizer/tsan/tsan_defs.h17
-rw-r--r--libsanitizer/tsan/tsan_flags.cc10
-rw-r--r--libsanitizer/tsan/tsan_flags.h2
-rw-r--r--libsanitizer/tsan/tsan_interceptors.cc78
-rw-r--r--libsanitizer/tsan/tsan_interface.h29
-rw-r--r--libsanitizer/tsan/tsan_interface_ann.cc45
-rw-r--r--libsanitizer/tsan/tsan_interface_atomic.cc62
-rw-r--r--libsanitizer/tsan/tsan_interface_atomic.h155
-rw-r--r--libsanitizer/tsan/tsan_mutex.cc24
-rw-r--r--libsanitizer/tsan/tsan_platform.h8
-rw-r--r--libsanitizer/tsan/tsan_platform_linux.cc22
-rw-r--r--libsanitizer/tsan/tsan_platform_mac.cc10
-rw-r--r--libsanitizer/tsan/tsan_platform_windows.cc56
-rw-r--r--libsanitizer/tsan/tsan_printf.cc38
-rw-r--r--libsanitizer/tsan/tsan_report.cc80
-rw-r--r--libsanitizer/tsan/tsan_rtl.cc50
-rw-r--r--libsanitizer/tsan/tsan_rtl.h26
-rw-r--r--libsanitizer/tsan/tsan_rtl_mutex.cc26
-rw-r--r--libsanitizer/tsan/tsan_rtl_report.cc8
-rw-r--r--libsanitizer/tsan/tsan_rtl_thread.cc41
-rw-r--r--libsanitizer/tsan/tsan_stat.cc9
-rw-r--r--libsanitizer/tsan/tsan_stat.h2
-rw-r--r--libsanitizer/tsan/tsan_suppressions.cc8
-rw-r--r--libsanitizer/tsan/tsan_symbolize_addr2line_linux.cc12
-rw-r--r--libsanitizer/tsan/tsan_update_shadow_word_inl.h4
29 files changed, 470 insertions, 366 deletions
diff --git a/libsanitizer/tsan/Makefile.am b/libsanitizer/tsan/Makefile.am
index a307502c97ae..c4fbad9b74df 100644
--- a/libsanitizer/tsan/Makefile.am
+++ b/libsanitizer/tsan/Makefile.am
@@ -26,7 +26,6 @@ tsan_files = \
tsan_suppressions.cc \
tsan_interface_ann.cc \
tsan_mman.cc \
- tsan_printf.cc \
tsan_rtl_report.cc \
tsan_symbolize_addr2line_linux.cc
diff --git a/libsanitizer/tsan/Makefile.in b/libsanitizer/tsan/Makefile.in
index a893bccd5ef5..b919969cf474 100644
--- a/libsanitizer/tsan/Makefile.in
+++ b/libsanitizer/tsan/Makefile.in
@@ -84,7 +84,7 @@ am__objects_1 = tsan_clock.lo tsan_interface_atomic.lo tsan_mutex.lo \
tsan_rtl.lo tsan_stat.lo tsan_sync.lo tsan_interceptors.lo \
tsan_md5.lo tsan_platform_mac.lo tsan_rtl_mutex.lo \
tsan_suppressions.lo tsan_interface_ann.lo tsan_mman.lo \
- tsan_printf.lo tsan_rtl_report.lo \
+ tsan_rtl_report.lo \
tsan_symbolize_addr2line_linux.lo
am_libtsan_la_OBJECTS = $(am__objects_1)
libtsan_la_OBJECTS = $(am_libtsan_la_OBJECTS)
@@ -261,7 +261,6 @@ tsan_files = \
tsan_suppressions.cc \
tsan_interface_ann.cc \
tsan_mman.cc \
- tsan_printf.cc \
tsan_rtl_report.cc \
tsan_symbolize_addr2line_linux.cc
@@ -395,7 +394,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_mutex.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_platform_linux.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_platform_mac.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_printf.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_report.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_rtl.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_rtl_mutex.Plo@am__quote@
diff --git a/libsanitizer/tsan/tsan_clock.cc b/libsanitizer/tsan/tsan_clock.cc
index 937f861477fa..5d45a5d15fb4 100644
--- a/libsanitizer/tsan/tsan_clock.cc
+++ b/libsanitizer/tsan/tsan_clock.cc
@@ -103,13 +103,6 @@ void ThreadClock::acq_rel(SyncClock *dst) {
release(dst);
}
-void ThreadClock::Disable(unsigned tid) {
- u64 c0 = clk_[tid];
- for (uptr i = 0; i < kMaxTidInClock; i++)
- clk_[i] = (u64)-1;
- clk_[tid] = c0;
-}
-
SyncClock::SyncClock()
: clk_(MBlockClock) {
}
diff --git a/libsanitizer/tsan/tsan_clock.h b/libsanitizer/tsan/tsan_clock.h
index d5c17305b315..8e4bf99ca896 100644
--- a/libsanitizer/tsan/tsan_clock.h
+++ b/libsanitizer/tsan/tsan_clock.h
@@ -59,8 +59,6 @@ struct ThreadClock {
nclk_ = tid + 1;
}
- void Disable(unsigned tid);
-
uptr size() const {
return nclk_;
}
diff --git a/libsanitizer/tsan/tsan_defs.h b/libsanitizer/tsan/tsan_defs.h
index 6a6f6b978327..6f3fd21e246d 100644
--- a/libsanitizer/tsan/tsan_defs.h
+++ b/libsanitizer/tsan/tsan_defs.h
@@ -22,6 +22,12 @@
namespace __tsan {
+#ifdef TSAN_GO
+const char *const kTsanOptionsEnv = "GORACE";
+#else
+const char *const kTsanOptionsEnv = "TSAN_OPTIONS";
+#endif
+
const int kTidBits = 13;
const unsigned kMaxTid = 1 << kTidBits;
const unsigned kMaxTidInClock = kMaxTid * 2; // This includes msb 'freed' bit.
@@ -34,20 +40,23 @@ const int kTraceStackSize = 256;
#ifdef TSAN_SHADOW_COUNT
# if TSAN_SHADOW_COUNT == 2 \
|| TSAN_SHADOW_COUNT == 4 || TSAN_SHADOW_COUNT == 8
-const unsigned kShadowCnt = TSAN_SHADOW_COUNT;
+const uptr kShadowCnt = TSAN_SHADOW_COUNT;
# else
# error "TSAN_SHADOW_COUNT must be one of 2,4,8"
# endif
#else
// Count of shadow values in a shadow cell.
-const unsigned kShadowCnt = 8;
+const uptr kShadowCnt = 4;
#endif
// That many user bytes are mapped onto a single shadow cell.
-const unsigned kShadowCell = 8;
+const uptr kShadowCell = 8;
// Size of a single shadow value (u64).
-const unsigned kShadowSize = 8;
+const uptr kShadowSize = 8;
+
+// Shadow memory is kShadowMultiplier times larger than user memory.
+const uptr kShadowMultiplier = kShadowSize * kShadowCnt / kShadowCell;
#if defined(TSAN_COLLECT_STATS) && TSAN_COLLECT_STATS
const bool kCollectStats = true;
diff --git a/libsanitizer/tsan/tsan_flags.cc b/libsanitizer/tsan/tsan_flags.cc
index e8563f5f8770..a69c6a6b545e 100644
--- a/libsanitizer/tsan/tsan_flags.cc
+++ b/libsanitizer/tsan/tsan_flags.cc
@@ -38,6 +38,7 @@ void InitializeFlags(Flags *f, const char *env) {
f->enable_annotations = true;
f->suppress_equal_stacks = true;
f->suppress_equal_addresses = true;
+ f->report_bugs = true;
f->report_thread_leaks = true;
f->report_destroy_locked = true;
f->report_signal_unsafe = true;
@@ -45,7 +46,7 @@ void InitializeFlags(Flags *f, const char *env) {
f->strip_path_prefix = "";
f->suppressions = "";
f->exitcode = 66;
- f->log_fileno = 2;
+ f->log_fileno = kStderrFd;
f->atexit_sleep_ms = 1000;
f->verbosity = 0;
f->profile_memory = "";
@@ -61,6 +62,7 @@ void InitializeFlags(Flags *f, const char *env) {
ParseFlag(env, &f->enable_annotations, "enable_annotations");
ParseFlag(env, &f->suppress_equal_stacks, "suppress_equal_stacks");
ParseFlag(env, &f->suppress_equal_addresses, "suppress_equal_addresses");
+ ParseFlag(env, &f->report_bugs, "report_bugs");
ParseFlag(env, &f->report_thread_leaks, "report_thread_leaks");
ParseFlag(env, &f->report_destroy_locked, "report_destroy_locked");
ParseFlag(env, &f->report_signal_unsafe, "report_signal_unsafe");
@@ -75,6 +77,12 @@ void InitializeFlags(Flags *f, const char *env) {
ParseFlag(env, &f->flush_memory_ms, "flush_memory_ms");
ParseFlag(env, &f->stop_on_start, "stop_on_start");
ParseFlag(env, &f->external_symbolizer_path, "external_symbolizer_path");
+
+ if (!f->report_bugs) {
+ f->report_thread_leaks = false;
+ f->report_destroy_locked = false;
+ f->report_signal_unsafe = false;
+ }
}
} // namespace __tsan
diff --git a/libsanitizer/tsan/tsan_flags.h b/libsanitizer/tsan/tsan_flags.h
index a6310e3ce6cd..451d3684729b 100644
--- a/libsanitizer/tsan/tsan_flags.h
+++ b/libsanitizer/tsan/tsan_flags.h
@@ -29,6 +29,8 @@ struct Flags {
// Supress a race report if we've already output another race report
// on the same address.
bool suppress_equal_addresses;
+ // Turns off bug reporting entirely (useful for benchmarking).
+ bool report_bugs;
// Report thread leaks at exit?
bool report_thread_leaks;
// Report destruction of a locked mutex?
diff --git a/libsanitizer/tsan/tsan_interceptors.cc b/libsanitizer/tsan/tsan_interceptors.cc
index 194e236ece7a..191dea7387a1 100644
--- a/libsanitizer/tsan/tsan_interceptors.cc
+++ b/libsanitizer/tsan/tsan_interceptors.cc
@@ -113,6 +113,7 @@ struct SignalDesc {
};
struct SignalContext {
+ int in_blocking_func;
int int_signal_send;
int pending_signal_count;
SignalDesc pending_signals[kSigCount];
@@ -134,8 +135,6 @@ static SignalContext *SigCtx(ThreadState *thr) {
static unsigned g_thread_finalize_key;
-static void process_pending_signals(ThreadState *thr);
-
ScopedInterceptor::ScopedInterceptor(ThreadState *thr, const char *fname,
uptr pc)
: thr_(thr)
@@ -154,28 +153,43 @@ ScopedInterceptor::~ScopedInterceptor() {
thr_->in_rtl--;
if (thr_->in_rtl == 0) {
FuncExit(thr_);
- process_pending_signals(thr_);
+ ProcessPendingSignals(thr_);
}
CHECK_EQ(in_rtl_, thr_->in_rtl);
}
+#define BLOCK_REAL(name) (BlockingCall(thr), REAL(name))
+
+struct BlockingCall {
+ explicit BlockingCall(ThreadState *thr)
+ : ctx(SigCtx(thr)) {
+ ctx->in_blocking_func++;
+ }
+
+ ~BlockingCall() {
+ ctx->in_blocking_func--;
+ }
+
+ SignalContext *ctx;
+};
+
TSAN_INTERCEPTOR(unsigned, sleep, unsigned sec) {
SCOPED_TSAN_INTERCEPTOR(sleep, sec);
- unsigned res = sleep(sec);
+ unsigned res = BLOCK_REAL(sleep)(sec);
AfterSleep(thr, pc);
return res;
}
TSAN_INTERCEPTOR(int, usleep, long_t usec) {
SCOPED_TSAN_INTERCEPTOR(usleep, usec);
- int res = usleep(usec);
+ int res = BLOCK_REAL(usleep)(usec);
AfterSleep(thr, pc);
return res;
}
TSAN_INTERCEPTOR(int, nanosleep, void *req, void *rem) {
SCOPED_TSAN_INTERCEPTOR(nanosleep, req, rem);
- int res = nanosleep(req, rem);
+ int res = BLOCK_REAL(nanosleep)(req, rem);
AfterSleep(thr, pc);
return res;
}
@@ -236,7 +250,6 @@ static void finalize(void *arg) {
{
ScopedInRtl in_rtl;
DestroyAndFree(atexit_ctx);
- REAL(usleep)(flags()->atexit_sleep_ms * 1000);
}
int status = Finalize(cur_thread());
if (status)
@@ -251,13 +264,13 @@ TSAN_INTERCEPTOR(int, atexit, void (*f)()) {
TSAN_INTERCEPTOR(void, longjmp, void *env, int val) {
SCOPED_TSAN_INTERCEPTOR(longjmp, env, val);
- TsanPrintf("ThreadSanitizer: longjmp() is not supported\n");
+ Printf("ThreadSanitizer: longjmp() is not supported\n");
Die();
}
TSAN_INTERCEPTOR(void, siglongjmp, void *env, int val) {
SCOPED_TSAN_INTERCEPTOR(siglongjmp, env, val);
- TsanPrintf("ThreadSanitizer: siglongjmp() is not supported\n");
+ Printf("ThreadSanitizer: siglongjmp() is not supported\n");
Die();
}
@@ -588,7 +601,7 @@ static void thread_finalize(void *v) {
uptr iter = (uptr)v;
if (iter > 1) {
if (pthread_setspecific(g_thread_finalize_key, (void*)(iter - 1))) {
- TsanPrintf("ThreadSanitizer: failed to set thread key\n");
+ Printf("ThreadSanitizer: failed to set thread key\n");
Die();
}
return;
@@ -621,7 +634,7 @@ extern "C" void *__tsan_thread_start_func(void *arg) {
ThreadState *thr = cur_thread();
ScopedInRtl in_rtl;
if (pthread_setspecific(g_thread_finalize_key, (void*)4)) {
- TsanPrintf("ThreadSanitizer: failed to set thread key\n");
+ Printf("ThreadSanitizer: failed to set thread key\n");
Die();
}
while ((tid = atomic_load(&p->tid, memory_order_acquire)) == 0)
@@ -676,7 +689,7 @@ TSAN_INTERCEPTOR(int, pthread_create,
TSAN_INTERCEPTOR(int, pthread_join, void *th, void **ret) {
SCOPED_TSAN_INTERCEPTOR(pthread_join, th, ret);
int tid = ThreadTid(thr, pc, (uptr)th);
- int res = REAL(pthread_join)(th, ret);
+ int res = BLOCK_REAL(pthread_join)(th, ret);
if (res == 0) {
ThreadJoin(thr, pc, tid);
}
@@ -979,7 +992,7 @@ TSAN_INTERCEPTOR(int, sem_destroy, void *s) {
TSAN_INTERCEPTOR(int, sem_wait, void *s) {
SCOPED_TSAN_INTERCEPTOR(sem_wait, s);
- int res = REAL(sem_wait)(s);
+ int res = BLOCK_REAL(sem_wait)(s);
if (res == 0) {
Acquire(thr, pc, (uptr)s);
}
@@ -988,7 +1001,7 @@ TSAN_INTERCEPTOR(int, sem_wait, void *s) {
TSAN_INTERCEPTOR(int, sem_trywait, void *s) {
SCOPED_TSAN_INTERCEPTOR(sem_trywait, s);
- int res = REAL(sem_trywait)(s);
+ int res = BLOCK_REAL(sem_trywait)(s);
if (res == 0) {
Acquire(thr, pc, (uptr)s);
}
@@ -997,7 +1010,7 @@ TSAN_INTERCEPTOR(int, sem_trywait, void *s) {
TSAN_INTERCEPTOR(int, sem_timedwait, void *s, void *abstime) {
SCOPED_TSAN_INTERCEPTOR(sem_timedwait, s, abstime);
- int res = REAL(sem_timedwait)(s, abstime);
+ int res = BLOCK_REAL(sem_timedwait)(s, abstime);
if (res == 0) {
Acquire(thr, pc, (uptr)s);
}
@@ -1189,13 +1202,19 @@ TSAN_INTERCEPTOR(int, epoll_ctl, int epfd, int op, int fd, void *ev) {
TSAN_INTERCEPTOR(int, epoll_wait, int epfd, void *ev, int cnt, int timeout) {
SCOPED_TSAN_INTERCEPTOR(epoll_wait, epfd, ev, cnt, timeout);
- int res = REAL(epoll_wait)(epfd, ev, cnt, timeout);
+ int res = BLOCK_REAL(epoll_wait)(epfd, ev, cnt, timeout);
if (res > 0) {
Acquire(thr, pc, epollfd2addr(epfd));
}
return res;
}
+TSAN_INTERCEPTOR(int, poll, void *fds, long_t nfds, int timeout) {
+ SCOPED_TSAN_INTERCEPTOR(poll, fds, nfds, timeout);
+ int res = BLOCK_REAL(poll)(fds, nfds, timeout);
+ return res;
+}
+
static void ALWAYS_INLINE rtl_generic_sighandler(bool sigact, int sig,
my_siginfo_t *info, void *ctx) {
ThreadState *thr = cur_thread();
@@ -1203,7 +1222,12 @@ static void ALWAYS_INLINE rtl_generic_sighandler(bool sigact, int sig,
// Don't mess with synchronous signals.
if (sig == SIGSEGV || sig == SIGBUS || sig == SIGILL ||
sig == SIGABRT || sig == SIGFPE || sig == SIGPIPE ||
- (sctx && sig == sctx->int_signal_send)) {
+ // If we are sending signal to ourselves, we must process it now.
+ (sctx && sig == sctx->int_signal_send) ||
+ // If we are in blocking function, we can safely process it now
+ // (but check if we are in a recursive interceptor,
+ // i.e. pthread_join()->munmap()).
+ (sctx && sctx->in_blocking_func == 1 && thr->in_rtl == 1)) {
CHECK(thr->in_rtl == 0 || thr->in_rtl == 1);
int in_rtl = thr->in_rtl;
thr->in_rtl = 0;
@@ -1317,7 +1341,15 @@ TSAN_INTERCEPTOR(int, pthread_kill, void *tid, int sig) {
return res;
}
-static void process_pending_signals(ThreadState *thr) {
+TSAN_INTERCEPTOR(int, gettimeofday, void *tv, void *tz) {
+ SCOPED_TSAN_INTERCEPTOR(gettimeofday, tv, tz);
+ // It's intercepted merely to process pending signals.
+ return REAL(gettimeofday)(tv, tz);
+}
+
+namespace __tsan {
+
+void ProcessPendingSignals(ThreadState *thr) {
CHECK_EQ(thr->in_rtl, 0);
SignalContext *sctx = SigCtx(thr);
if (sctx == 0 || sctx->pending_signal_count == 0 || thr->in_signal_handler)
@@ -1342,7 +1374,7 @@ static void process_pending_signals(ThreadState *thr) {
sigactions[sig].sa_sigaction(sig, &signal->siginfo, &signal->ctx);
else
sigactions[sig].sa_handler(sig);
- if (errno != 0) {
+ if (flags()->report_bugs && errno != 0) {
ScopedInRtl in_rtl;
__tsan::StackTrace stack;
uptr pc = signal->sigaction ?
@@ -1364,8 +1396,6 @@ static void process_pending_signals(ThreadState *thr) {
thr->in_signal_handler = false;
}
-namespace __tsan {
-
void InitializeInterceptors() {
CHECK_GT(cur_thread()->in_rtl, 0);
@@ -1482,6 +1512,7 @@ void InitializeInterceptors() {
TSAN_INTERCEPT(epoll_ctl);
TSAN_INTERCEPT(epoll_wait);
+ TSAN_INTERCEPT(poll);
TSAN_INTERCEPT(sigaction);
TSAN_INTERCEPT(signal);
@@ -1491,17 +1522,18 @@ void InitializeInterceptors() {
TSAN_INTERCEPT(sleep);
TSAN_INTERCEPT(usleep);
TSAN_INTERCEPT(nanosleep);
+ TSAN_INTERCEPT(gettimeofday);
atexit_ctx = new(internal_alloc(MBlockAtExit, sizeof(AtExitContext)))
AtExitContext();
if (__cxa_atexit(&finalize, 0, 0)) {
- TsanPrintf("ThreadSanitizer: failed to setup atexit callback\n");
+ Printf("ThreadSanitizer: failed to setup atexit callback\n");
Die();
}
if (pthread_key_create(&g_thread_finalize_key, &thread_finalize)) {
- TsanPrintf("ThreadSanitizer: failed to create thread key\n");
+ Printf("ThreadSanitizer: failed to create thread key\n");
Die();
}
}
diff --git a/libsanitizer/tsan/tsan_interface.h b/libsanitizer/tsan/tsan_interface.h
index 72bb1e91c3da..dede9be5f06d 100644
--- a/libsanitizer/tsan/tsan_interface.h
+++ b/libsanitizer/tsan/tsan_interface.h
@@ -14,7 +14,6 @@
#ifndef TSAN_INTERFACE_H
#define TSAN_INTERFACE_H
-#include <sanitizer/common_interface_defs.h>
// This header should NOT include any other headers.
// All functions in this header are extern "C" and start with __tsan_.
@@ -24,24 +23,24 @@ extern "C" {
// This function should be called at the very beginning of the process,
// before any instrumented code is executed and before any call to malloc.
-void __tsan_init() SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+void __tsan_init();
-void __tsan_read1(void *addr) SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
-void __tsan_read2(void *addr) SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
-void __tsan_read4(void *addr) SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
-void __tsan_read8(void *addr) SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
-void __tsan_read16(void *addr) SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+void __tsan_read1(void *addr);
+void __tsan_read2(void *addr);
+void __tsan_read4(void *addr);
+void __tsan_read8(void *addr);
+void __tsan_read16(void *addr);
-void __tsan_write1(void *addr) SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
-void __tsan_write2(void *addr) SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
-void __tsan_write4(void *addr) SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
-void __tsan_write8(void *addr) SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
-void __tsan_write16(void *addr) SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+void __tsan_write1(void *addr);
+void __tsan_write2(void *addr);
+void __tsan_write4(void *addr);
+void __tsan_write8(void *addr);
+void __tsan_write16(void *addr);
-void __tsan_vptr_update(void **vptr_p, void *new_val) SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+void __tsan_vptr_update(void **vptr_p, void *new_val);
-void __tsan_func_entry(void *call_pc) SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
-void __tsan_func_exit() SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+void __tsan_func_entry(void *call_pc);
+void __tsan_func_exit();
#ifdef __cplusplus
} // extern "C"
diff --git a/libsanitizer/tsan/tsan_interface_ann.cc b/libsanitizer/tsan/tsan_interface_ann.cc
index fd5c1cc6cd43..b9e084b7327d 100644
--- a/libsanitizer/tsan/tsan_interface_ann.cc
+++ b/libsanitizer/tsan/tsan_interface_ann.cc
@@ -157,57 +157,47 @@ bool IsExpectedReport(uptr addr, uptr size) {
using namespace __tsan; // NOLINT
extern "C" {
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
void AnnotateHappensBefore(char *f, int l, uptr addr) {
SCOPED_ANNOTATION(AnnotateHappensBefore);
Release(cur_thread(), CALLERPC, addr);
}
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
void AnnotateHappensAfter(char *f, int l, uptr addr) {
SCOPED_ANNOTATION(AnnotateHappensAfter);
Acquire(cur_thread(), CALLERPC, addr);
}
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
void AnnotateCondVarSignal(char *f, int l, uptr cv) {
SCOPED_ANNOTATION(AnnotateCondVarSignal);
}
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
void AnnotateCondVarSignalAll(char *f, int l, uptr cv) {
SCOPED_ANNOTATION(AnnotateCondVarSignalAll);
}
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
void AnnotateMutexIsNotPHB(char *f, int l, uptr mu) {
SCOPED_ANNOTATION(AnnotateMutexIsNotPHB);
}
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
void AnnotateCondVarWait(char *f, int l, uptr cv, uptr lock) {
SCOPED_ANNOTATION(AnnotateCondVarWait);
}
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
void AnnotateRWLockCreate(char *f, int l, uptr m) {
SCOPED_ANNOTATION(AnnotateRWLockCreate);
MutexCreate(thr, pc, m, true, true, false);
}
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
void AnnotateRWLockCreateStatic(char *f, int l, uptr m) {
SCOPED_ANNOTATION(AnnotateRWLockCreateStatic);
MutexCreate(thr, pc, m, true, true, true);
}
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
void AnnotateRWLockDestroy(char *f, int l, uptr m) {
SCOPED_ANNOTATION(AnnotateRWLockDestroy);
MutexDestroy(thr, pc, m);
}
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
void AnnotateRWLockAcquired(char *f, int l, uptr m, uptr is_w) {
SCOPED_ANNOTATION(AnnotateRWLockAcquired);
if (is_w)
@@ -216,7 +206,6 @@ void AnnotateRWLockAcquired(char *f, int l, uptr m, uptr is_w) {
MutexReadLock(thr, pc, m);
}
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
void AnnotateRWLockReleased(char *f, int l, uptr m, uptr is_w) {
SCOPED_ANNOTATION(AnnotateRWLockReleased);
if (is_w)
@@ -225,35 +214,30 @@ void AnnotateRWLockReleased(char *f, int l, uptr m, uptr is_w) {
MutexReadUnlock(thr, pc, m);
}
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
void AnnotateTraceMemory(char *f, int l, uptr mem) {
SCOPED_ANNOTATION(AnnotateTraceMemory);
}
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
void AnnotateFlushState(char *f, int l) {
SCOPED_ANNOTATION(AnnotateFlushState);
}
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
void AnnotateNewMemory(char *f, int l, uptr mem, uptr size) {
SCOPED_ANNOTATION(AnnotateNewMemory);
}
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
void AnnotateNoOp(char *f, int l, uptr mem) {
SCOPED_ANNOTATION(AnnotateNoOp);
}
static void ReportMissedExpectedRace(ExpectRace *race) {
- TsanPrintf("==================\n");
- TsanPrintf("WARNING: ThreadSanitizer: missed expected data race\n");
- TsanPrintf(" %s addr=%zx %s:%d\n",
+ Printf("==================\n");
+ Printf("WARNING: ThreadSanitizer: missed expected data race\n");
+ Printf(" %s addr=%zx %s:%d\n",
race->desc, race->addr, race->file, race->line);
- TsanPrintf("==================\n");
+ Printf("==================\n");
}
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
void AnnotateFlushExpectedRaces(char *f, int l) {
SCOPED_ANNOTATION(AnnotateFlushExpectedRaces);
Lock lock(&dyn_ann_ctx->mtx);
@@ -269,38 +253,31 @@ void AnnotateFlushExpectedRaces(char *f, int l) {
}
}
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
void AnnotateEnableRaceDetection(char *f, int l, int enable) {
SCOPED_ANNOTATION(AnnotateEnableRaceDetection);
// FIXME: Reconsider this functionality later. It may be irrelevant.
}
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
void AnnotateMutexIsUsedAsCondVar(char *f, int l, uptr mu) {
SCOPED_ANNOTATION(AnnotateMutexIsUsedAsCondVar);
}
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
void AnnotatePCQGet(char *f, int l, uptr pcq) {
SCOPED_ANNOTATION(AnnotatePCQGet);
}
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
void AnnotatePCQPut(char *f, int l, uptr pcq) {
SCOPED_ANNOTATION(AnnotatePCQPut);
}
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
void AnnotatePCQDestroy(char *f, int l, uptr pcq) {
SCOPED_ANNOTATION(AnnotatePCQDestroy);
}
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
void AnnotatePCQCreate(char *f, int l, uptr pcq) {
SCOPED_ANNOTATION(AnnotatePCQCreate);
}
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
void AnnotateExpectRace(char *f, int l, uptr mem, char *desc) {
SCOPED_ANNOTATION(AnnotateExpectRace);
Lock lock(&dyn_ann_ctx->mtx);
@@ -317,73 +294,60 @@ static void BenignRaceImpl(char *f, int l, uptr mem, uptr size, char *desc) {
}
// FIXME: Turn it off later. WTF is benign race?1?? Go talk to Hans Boehm.
-// SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
void AnnotateBenignRaceSized(char *f, int l, uptr mem, uptr size, char *desc) {
SCOPED_ANNOTATION(AnnotateBenignRaceSized);
BenignRaceImpl(f, l, mem, size, desc);
}
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
void AnnotateBenignRace(char *f, int l, uptr mem, char *desc) {
SCOPED_ANNOTATION(AnnotateBenignRace);
BenignRaceImpl(f, l, mem, 1, desc);
}
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
void AnnotateIgnoreReadsBegin(char *f, int l) {
SCOPED_ANNOTATION(AnnotateIgnoreReadsBegin);
IgnoreCtl(cur_thread(), false, true);
}
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
void AnnotateIgnoreReadsEnd(char *f, int l) {
SCOPED_ANNOTATION(AnnotateIgnoreReadsEnd);
IgnoreCtl(cur_thread(), false, false);
}
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
void AnnotateIgnoreWritesBegin(char *f, int l) {
SCOPED_ANNOTATION(AnnotateIgnoreWritesBegin);
IgnoreCtl(cur_thread(), true, true);
}
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
void AnnotateIgnoreWritesEnd(char *f, int l) {
SCOPED_ANNOTATION(AnnotateIgnoreWritesEnd);
IgnoreCtl(cur_thread(), true, false);
}
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
void AnnotatePublishMemoryRange(char *f, int l, uptr addr, uptr size) {
SCOPED_ANNOTATION(AnnotatePublishMemoryRange);
}
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
void AnnotateUnpublishMemoryRange(char *f, int l, uptr addr, uptr size) {
SCOPED_ANNOTATION(AnnotateUnpublishMemoryRange);
}
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
void AnnotateThreadName(char *f, int l, char *name) {
SCOPED_ANNOTATION(AnnotateThreadName);
}
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
void WTFAnnotateHappensBefore(char *f, int l, uptr addr) {
SCOPED_ANNOTATION(AnnotateHappensBefore);
}
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
void WTFAnnotateHappensAfter(char *f, int l, uptr addr) {
SCOPED_ANNOTATION(AnnotateHappensAfter);
}
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
void WTFAnnotateBenignRaceSized(char *f, int l, uptr mem, uptr sz, char *desc) {
SCOPED_ANNOTATION(AnnotateBenignRaceSized);
}
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
int RunningOnValgrind() {
return flags()->running_on_valgrind;
}
@@ -392,7 +356,6 @@ double __attribute__((weak)) ValgrindSlowdown(void) {
return 10.0;
}
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
const char *ThreadSanitizerQuery(const char *query) {
if (internal_strcmp(query, "pure_happens_before") == 0)
return "1";
diff --git a/libsanitizer/tsan/tsan_interface_atomic.cc b/libsanitizer/tsan/tsan_interface_atomic.cc
index 7b459f15d466..037a080da67d 100644
--- a/libsanitizer/tsan/tsan_interface_atomic.cc
+++ b/libsanitizer/tsan/tsan_interface_atomic.cc
@@ -37,12 +37,12 @@ typedef __tsan_atomic8 a8;
typedef __tsan_atomic16 a16;
typedef __tsan_atomic32 a32;
typedef __tsan_atomic64 a64;
-const int mo_relaxed = __tsan_memory_order_relaxed;
-const int mo_consume = __tsan_memory_order_consume;
-const int mo_acquire = __tsan_memory_order_acquire;
-const int mo_release = __tsan_memory_order_release;
-const int mo_acq_rel = __tsan_memory_order_acq_rel;
-const int mo_seq_cst = __tsan_memory_order_seq_cst;
+const morder mo_relaxed = __tsan_memory_order_relaxed;
+const morder mo_consume = __tsan_memory_order_consume;
+const morder mo_acquire = __tsan_memory_order_acquire;
+const morder mo_release = __tsan_memory_order_release;
+const morder mo_acq_rel = __tsan_memory_order_acq_rel;
+const morder mo_seq_cst = __tsan_memory_order_seq_cst;
static void AtomicStatInc(ThreadState *thr, uptr size, morder mo, StatType t) {
StatInc(thr, StatAtomic);
@@ -77,10 +77,32 @@ static bool IsAcquireOrder(morder mo) {
|| mo == mo_acq_rel || mo == mo_seq_cst;
}
+static morder ConvertOrder(morder mo) {
+ if (mo > (morder)100500) {
+ mo = morder(mo - 100500);
+ if (mo == morder(1 << 0))
+ mo = mo_relaxed;
+ else if (mo == morder(1 << 1))
+ mo = mo_consume;
+ else if (mo == morder(1 << 2))
+ mo = mo_acquire;
+ else if (mo == morder(1 << 3))
+ mo = mo_release;
+ else if (mo == morder(1 << 4))
+ mo = mo_acq_rel;
+ else if (mo == morder(1 << 5))
+ mo = mo_seq_cst;
+ }
+ CHECK_GE(mo, mo_relaxed);
+ CHECK_LE(mo, mo_seq_cst);
+ return mo;
+}
+
#define SCOPED_ATOMIC(func, ...) \
- if ((u32)mo > 100500) mo = (morder)((u32)mo - 100500); \
+ mo = ConvertOrder(mo); \
mo = flags()->force_seq_cst_atomics ? (morder)mo_seq_cst : mo; \
ThreadState *const thr = cur_thread(); \
+ ProcessPendingSignals(thr); \
const uptr pc = (uptr)__builtin_return_address(0); \
AtomicStatInc(thr, sizeof(*a), mo, StatAtomic##func); \
ScopedAtomic sa(thr, pc, __FUNCTION__); \
@@ -187,6 +209,13 @@ static bool AtomicCAS(ThreadState *thr, uptr pc,
return false;
}
+template<typename T>
+static T AtomicCAS(ThreadState *thr, uptr pc,
+ volatile T *a, T c, T v, morder mo) {
+ AtomicCAS(thr, pc, a, &c, v, mo);
+ return c;
+}
+
static void AtomicFence(ThreadState *thr, uptr pc, morder mo) {
__sync_synchronize();
}
@@ -359,6 +388,25 @@ int __tsan_atomic64_compare_exchange_weak(volatile a64 *a, a64 *c, a64 v,
SCOPED_ATOMIC(CAS, a, c, v, mo);
}
+a8 __tsan_atomic8_compare_exchange_val(volatile a8 *a, a8 c, a8 v,
+ morder mo) {
+ SCOPED_ATOMIC(CAS, a, c, v, mo);
+}
+a16 __tsan_atomic16_compare_exchange_val(volatile a16 *a, a16 c, a16 v,
+ morder mo) {
+ SCOPED_ATOMIC(CAS, a, c, v, mo);
+}
+
+a32 __tsan_atomic32_compare_exchange_val(volatile a32 *a, a32 c, a32 v,
+ morder mo) {
+ SCOPED_ATOMIC(CAS, a, c, v, mo);
+}
+
+a64 __tsan_atomic64_compare_exchange_val(volatile a64 *a, a64 c, a64 v,
+ morder mo) {
+ SCOPED_ATOMIC(CAS, a, c, v, mo);
+}
+
void __tsan_atomic_thread_fence(morder mo) {
char* a;
SCOPED_ATOMIC(Fence, mo);
diff --git a/libsanitizer/tsan/tsan_interface_atomic.h b/libsanitizer/tsan/tsan_interface_atomic.h
index 37532ce41856..fea97b69debf 100644
--- a/libsanitizer/tsan/tsan_interface_atomic.h
+++ b/libsanitizer/tsan/tsan_interface_atomic.h
@@ -23,148 +23,119 @@ typedef long __tsan_atomic64; // NOLINT
// Part of ABI, do not change.
// http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/atomic?view=markup
typedef enum {
- __tsan_memory_order_relaxed = 1 << 0,
- __tsan_memory_order_consume = 1 << 1,
- __tsan_memory_order_acquire = 1 << 2,
- __tsan_memory_order_release = 1 << 3,
- __tsan_memory_order_acq_rel = 1 << 4,
- __tsan_memory_order_seq_cst = 1 << 5
+ __tsan_memory_order_relaxed,
+ __tsan_memory_order_consume,
+ __tsan_memory_order_acquire,
+ __tsan_memory_order_release,
+ __tsan_memory_order_acq_rel,
+ __tsan_memory_order_seq_cst
} __tsan_memory_order;
__tsan_atomic8 __tsan_atomic8_load(const volatile __tsan_atomic8 *a,
- __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_memory_order mo);
__tsan_atomic16 __tsan_atomic16_load(const volatile __tsan_atomic16 *a,
- __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_memory_order mo);
__tsan_atomic32 __tsan_atomic32_load(const volatile __tsan_atomic32 *a,
- __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_memory_order mo);
__tsan_atomic64 __tsan_atomic64_load(const volatile __tsan_atomic64 *a,
- __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_memory_order mo);
void __tsan_atomic8_store(volatile __tsan_atomic8 *a, __tsan_atomic8 v,
- __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_memory_order mo);
void __tsan_atomic16_store(volatile __tsan_atomic16 *a, __tsan_atomic16 v,
- __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_memory_order mo);
void __tsan_atomic32_store(volatile __tsan_atomic32 *a, __tsan_atomic32 v,
- __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_memory_order mo);
void __tsan_atomic64_store(volatile __tsan_atomic64 *a, __tsan_atomic64 v,
- __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_memory_order mo);
__tsan_atomic8 __tsan_atomic8_exchange(volatile __tsan_atomic8 *a,
- __tsan_atomic8 v, __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_atomic8 v, __tsan_memory_order mo);
__tsan_atomic16 __tsan_atomic16_exchange(volatile __tsan_atomic16 *a,
- __tsan_atomic16 v, __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_atomic16 v, __tsan_memory_order mo);
__tsan_atomic32 __tsan_atomic32_exchange(volatile __tsan_atomic32 *a,
- __tsan_atomic32 v, __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
-__tsan_atomic64 __tsan_atomic64_exchange(volatile __tsan_atomic64 *a,
- __tsan_atomic64 v, __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_atomic32 v, __tsan_memory_order mo);
+__tsan_atomic64 __tsan_atomic64_exchange(volatile __tsan_atomic64 *a,
+ __tsan_atomic64 v, __tsan_memory_order mo);
__tsan_atomic8 __tsan_atomic8_fetch_add(volatile __tsan_atomic8 *a,
- __tsan_atomic8 v, __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_atomic8 v, __tsan_memory_order mo);
__tsan_atomic16 __tsan_atomic16_fetch_add(volatile __tsan_atomic16 *a,
- __tsan_atomic16 v, __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_atomic16 v, __tsan_memory_order mo);
__tsan_atomic32 __tsan_atomic32_fetch_add(volatile __tsan_atomic32 *a,
- __tsan_atomic32 v, __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_atomic32 v, __tsan_memory_order mo);
__tsan_atomic64 __tsan_atomic64_fetch_add(volatile __tsan_atomic64 *a,
- __tsan_atomic64 v, __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_atomic64 v, __tsan_memory_order mo);
__tsan_atomic8 __tsan_atomic8_fetch_sub(volatile __tsan_atomic8 *a,
- __tsan_atomic8 v, __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_atomic8 v, __tsan_memory_order mo);
__tsan_atomic16 __tsan_atomic16_fetch_sub(volatile __tsan_atomic16 *a,
- __tsan_atomic16 v, __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_atomic16 v, __tsan_memory_order mo);
__tsan_atomic32 __tsan_atomic32_fetch_sub(volatile __tsan_atomic32 *a,
- __tsan_atomic32 v, __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_atomic32 v, __tsan_memory_order mo);
__tsan_atomic64 __tsan_atomic64_fetch_sub(volatile __tsan_atomic64 *a,
- __tsan_atomic64 v, __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_atomic64 v, __tsan_memory_order mo);
__tsan_atomic8 __tsan_atomic8_fetch_and(volatile __tsan_atomic8 *a,
- __tsan_atomic8 v, __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_atomic8 v, __tsan_memory_order mo);
__tsan_atomic16 __tsan_atomic16_fetch_and(volatile __tsan_atomic16 *a,
- __tsan_atomic16 v, __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_atomic16 v, __tsan_memory_order mo);
__tsan_atomic32 __tsan_atomic32_fetch_and(volatile __tsan_atomic32 *a,
- __tsan_atomic32 v, __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_atomic32 v, __tsan_memory_order mo);
__tsan_atomic64 __tsan_atomic64_fetch_and(volatile __tsan_atomic64 *a,
- __tsan_atomic64 v, __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_atomic64 v, __tsan_memory_order mo);
__tsan_atomic8 __tsan_atomic8_fetch_or(volatile __tsan_atomic8 *a,
- __tsan_atomic8 v, __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_atomic8 v, __tsan_memory_order mo);
__tsan_atomic16 __tsan_atomic16_fetch_or(volatile __tsan_atomic16 *a,
- __tsan_atomic16 v, __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_atomic16 v, __tsan_memory_order mo);
__tsan_atomic32 __tsan_atomic32_fetch_or(volatile __tsan_atomic32 *a,
- __tsan_atomic32 v, __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_atomic32 v, __tsan_memory_order mo);
__tsan_atomic64 __tsan_atomic64_fetch_or(volatile __tsan_atomic64 *a,
- __tsan_atomic64 v, __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_atomic64 v, __tsan_memory_order mo);
__tsan_atomic8 __tsan_atomic8_fetch_xor(volatile __tsan_atomic8 *a,
- __tsan_atomic8 v, __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_atomic8 v, __tsan_memory_order mo);
__tsan_atomic16 __tsan_atomic16_fetch_xor(volatile __tsan_atomic16 *a,
- __tsan_atomic16 v, __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_atomic16 v, __tsan_memory_order mo);
__tsan_atomic32 __tsan_atomic32_fetch_xor(volatile __tsan_atomic32 *a,
- __tsan_atomic32 v, __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_atomic32 v, __tsan_memory_order mo);
__tsan_atomic64 __tsan_atomic64_fetch_xor(volatile __tsan_atomic64 *a,
- __tsan_atomic64 v, __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_atomic64 v, __tsan_memory_order mo);
int __tsan_atomic8_compare_exchange_weak(volatile __tsan_atomic8 *a,
- __tsan_atomic8 *c, __tsan_atomic8 v, __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_atomic8 *c, __tsan_atomic8 v, __tsan_memory_order mo);
int __tsan_atomic16_compare_exchange_weak(volatile __tsan_atomic16 *a,
- __tsan_atomic16 *c, __tsan_atomic16 v, __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_atomic16 *c, __tsan_atomic16 v, __tsan_memory_order mo);
int __tsan_atomic32_compare_exchange_weak(volatile __tsan_atomic32 *a,
- __tsan_atomic32 *c, __tsan_atomic32 v, __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_atomic32 *c, __tsan_atomic32 v, __tsan_memory_order mo);
int __tsan_atomic64_compare_exchange_weak(volatile __tsan_atomic64 *a,
- __tsan_atomic64 *c, __tsan_atomic64 v, __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_atomic64 *c, __tsan_atomic64 v, __tsan_memory_order mo);
int __tsan_atomic8_compare_exchange_strong(volatile __tsan_atomic8 *a,
- __tsan_atomic8 *c, __tsan_atomic8 v, __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_atomic8 *c, __tsan_atomic8 v, __tsan_memory_order mo);
int __tsan_atomic16_compare_exchange_strong(volatile __tsan_atomic16 *a,
- __tsan_atomic16 *c, __tsan_atomic16 v, __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_atomic16 *c, __tsan_atomic16 v, __tsan_memory_order mo);
int __tsan_atomic32_compare_exchange_strong(volatile __tsan_atomic32 *a,
- __tsan_atomic32 *c, __tsan_atomic32 v, __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_atomic32 *c, __tsan_atomic32 v, __tsan_memory_order mo);
int __tsan_atomic64_compare_exchange_strong(volatile __tsan_atomic64 *a,
- __tsan_atomic64 *c, __tsan_atomic64 v, __tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
-
-void __tsan_atomic_thread_fence(__tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
-void __tsan_atomic_signal_fence(__tsan_memory_order mo)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ __tsan_atomic64 *c, __tsan_atomic64 v, __tsan_memory_order mo);
+
+__tsan_atomic8 __tsan_atomic8_compare_exchange_val(
+ volatile __tsan_atomic8 *a, __tsan_atomic8 c, __tsan_atomic8 v,
+ __tsan_memory_order mo);
+__tsan_atomic16 __tsan_atomic16_compare_exchange_val(
+ volatile __tsan_atomic16 *a, __tsan_atomic16 c, __tsan_atomic16 v,
+ __tsan_memory_order mo);
+__tsan_atomic32 __tsan_atomic32_compare_exchange_val(
+ volatile __tsan_atomic32 *a, __tsan_atomic32 c, __tsan_atomic32 v,
+ __tsan_memory_order mo);
+__tsan_atomic64 __tsan_atomic64_compare_exchange_val(
+ volatile __tsan_atomic64 *a, __tsan_atomic64 c, __tsan_atomic64 v,
+ __tsan_memory_order mo);
+
+void __tsan_atomic_thread_fence(__tsan_memory_order mo);
+void __tsan_atomic_signal_fence(__tsan_memory_order mo);
#ifdef __cplusplus
} // extern "C"
diff --git a/libsanitizer/tsan/tsan_mutex.cc b/libsanitizer/tsan/tsan_mutex.cc
index 83af02992b49..6a1e0cec53ad 100644
--- a/libsanitizer/tsan/tsan_mutex.cc
+++ b/libsanitizer/tsan/tsan_mutex.cc
@@ -90,25 +90,25 @@ void InitializeMutex() {
}
}
#if 0
- TsanPrintf("Can lock graph:\n");
+ Printf("Can lock graph:\n");
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
- TsanPrintf("%d ", CanLockAdj[i][j]);
+ Printf("%d ", CanLockAdj[i][j]);
}
- TsanPrintf("\n");
+ Printf("\n");
}
- TsanPrintf("Can lock graph closure:\n");
+ Printf("Can lock graph closure:\n");
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
- TsanPrintf("%d ", CanLockAdj2[i][j]);
+ Printf("%d ", CanLockAdj2[i][j]);
}
- TsanPrintf("\n");
+ Printf("\n");
}
#endif
// Verify that the graph is acyclic.
for (int i = 0; i < N; i++) {
if (CanLockAdj2[i][i]) {
- TsanPrintf("Mutex %d participates in a cycle\n", i);
+ Printf("Mutex %d participates in a cycle\n", i);
Die();
}
}
@@ -119,7 +119,7 @@ DeadlockDetector::DeadlockDetector() {
}
void DeadlockDetector::Lock(MutexType t) {
- // TsanPrintf("LOCK %d @%zu\n", t, seq_ + 1);
+ // Printf("LOCK %d @%zu\n", t, seq_ + 1);
u64 max_seq = 0;
u64 max_idx = MutexTypeInvalid;
for (int i = 0; i != MutexTypeCount; i++) {
@@ -134,17 +134,17 @@ void DeadlockDetector::Lock(MutexType t) {
locked_[t] = ++seq_;
if (max_idx == MutexTypeInvalid)
return;
- // TsanPrintf(" last %d @%zu\n", max_idx, max_seq);
+ // Printf(" last %d @%zu\n", max_idx, max_seq);
if (!CanLockAdj[max_idx][t]) {
- TsanPrintf("ThreadSanitizer: internal deadlock detected\n");
- TsanPrintf("ThreadSanitizer: can't lock %d while under %zu\n",
+ Printf("ThreadSanitizer: internal deadlock detected\n");
+ Printf("ThreadSanitizer: can't lock %d while under %zu\n",
t, (uptr)max_idx);
CHECK(0);
}
}
void DeadlockDetector::Unlock(MutexType t) {
- // TsanPrintf("UNLO %d @%zu #%zu\n", t, seq_, locked_[t]);
+ // Printf("UNLO %d @%zu #%zu\n", t, seq_, locked_[t]);
CHECK(locked_[t]);
locked_[t] = 0;
}
diff --git a/libsanitizer/tsan/tsan_platform.h b/libsanitizer/tsan/tsan_platform.h
index d7a4cf7b0e93..f849182503c9 100644
--- a/libsanitizer/tsan/tsan_platform.h
+++ b/libsanitizer/tsan/tsan_platform.h
@@ -15,13 +15,17 @@
#include "tsan_rtl.h"
-#if __LP64__
+#if defined(__LP64__) || defined(_WIN64)
namespace __tsan {
#if defined(TSAN_GO)
static const uptr kLinuxAppMemBeg = 0x000000000000ULL;
static const uptr kLinuxAppMemEnd = 0x00fcffffffffULL;
+# if defined(_WIN32)
+static const uptr kLinuxShadowMsk = 0x010000000000ULL;
+# else
static const uptr kLinuxShadowMsk = 0x100000000000ULL;
+# endif
// TSAN_COMPAT_SHADOW is intended for COMPAT virtual memory layout,
// when memory addresses are of the 0x2axxxxxxxxxx form.
// The option is enabled with 'setarch x86_64 -L'.
@@ -93,7 +97,7 @@ void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
} // namespace __tsan
-#else // __LP64__
+#else // defined(__LP64__) || defined(_WIN64)
# error "Only 64-bit is supported"
#endif
diff --git a/libsanitizer/tsan/tsan_platform_linux.cc b/libsanitizer/tsan/tsan_platform_linux.cc
index d7de503c51d2..b26065543fe5 100644
--- a/libsanitizer/tsan/tsan_platform_linux.cc
+++ b/libsanitizer/tsan/tsan_platform_linux.cc
@@ -81,46 +81,42 @@ static void ProtectRange(uptr beg, uptr end) {
if (beg == end)
return;
if (beg != (uptr)Mprotect(beg, end - beg)) {
- TsanPrintf("FATAL: ThreadSanitizer can not protect [%zx,%zx]\n", beg, end);
- TsanPrintf("FATAL: Make sure you are not using unlimited stack\n");
+ Printf("FATAL: ThreadSanitizer can not protect [%zx,%zx]\n", beg, end);
+ Printf("FATAL: Make sure you are not using unlimited stack\n");
Die();
}
}
#endif
+#ifndef TSAN_GO
void InitializeShadowMemory() {
uptr shadow = (uptr)MmapFixedNoReserve(kLinuxShadowBeg,
kLinuxShadowEnd - kLinuxShadowBeg);
if (shadow != kLinuxShadowBeg) {
- TsanPrintf("FATAL: ThreadSanitizer can not mmap the shadow memory\n");
- TsanPrintf("FATAL: Make sure to compile with -fPIE and "
+ Printf("FATAL: ThreadSanitizer can not mmap the shadow memory\n");
+ Printf("FATAL: Make sure to compile with -fPIE and "
"to link with -pie (%p, %p).\n", shadow, kLinuxShadowBeg);
Die();
}
-#ifndef TSAN_GO
const uptr kClosedLowBeg = 0x200000;
const uptr kClosedLowEnd = kLinuxShadowBeg - 1;
const uptr kClosedMidBeg = kLinuxShadowEnd + 1;
const uptr kClosedMidEnd = kLinuxAppMemBeg - 1;
ProtectRange(kClosedLowBeg, kClosedLowEnd);
ProtectRange(kClosedMidBeg, kClosedMidEnd);
-#endif
-#ifndef TSAN_GO
DPrintf("kClosedLow %zx-%zx (%zuGB)\n",
kClosedLowBeg, kClosedLowEnd, (kClosedLowEnd - kClosedLowBeg) >> 30);
-#endif
DPrintf("kLinuxShadow %zx-%zx (%zuGB)\n",
kLinuxShadowBeg, kLinuxShadowEnd,
(kLinuxShadowEnd - kLinuxShadowBeg) >> 30);
-#ifndef TSAN_GO
DPrintf("kClosedMid %zx-%zx (%zuGB)\n",
kClosedMidBeg, kClosedMidEnd, (kClosedMidEnd - kClosedMidBeg) >> 30);
-#endif
DPrintf("kLinuxAppMem %zx-%zx (%zuGB)\n",
kLinuxAppMemBeg, kLinuxAppMemEnd,
(kLinuxAppMemEnd - kLinuxAppMemBeg) >> 30);
DPrintf("stack %zx\n", (uptr)&shadow);
}
+#endif
static uptr g_data_start;
static uptr g_data_end;
@@ -133,10 +129,10 @@ static void CheckPIE() {
if (proc_maps.Next(&start, &end,
/*offset*/0, /*filename*/0, /*filename_size*/0)) {
if ((u64)start < kLinuxAppMemBeg) {
- TsanPrintf("FATAL: ThreadSanitizer can not mmap the shadow memory ("
+ Printf("FATAL: ThreadSanitizer can not mmap the shadow memory ("
"something is mapped at 0x%zx < 0x%zx)\n",
start, kLinuxAppMemBeg);
- TsanPrintf("FATAL: Make sure to compile with -fPIE"
+ Printf("FATAL: Make sure to compile with -fPIE"
" and to link with -pie.\n");
Die();
}
@@ -221,7 +217,7 @@ const char *InitializePlatform() {
g_tls_size = (uptr)InitTlsSize();
InitDataSeg();
#endif
- return getenv("TSAN_OPTIONS");
+ return getenv(kTsanOptionsEnv);
}
void FinalizePlatform() {
diff --git a/libsanitizer/tsan/tsan_platform_mac.cc b/libsanitizer/tsan/tsan_platform_mac.cc
index e22a500cf15b..808d99c0207f 100644
--- a/libsanitizer/tsan/tsan_platform_mac.cc
+++ b/libsanitizer/tsan/tsan_platform_mac.cc
@@ -50,13 +50,14 @@ uptr GetShadowMemoryConsumption() {
void FlushShadowMemory() {
}
+#ifndef TSAN_GO
void InitializeShadowMemory() {
uptr shadow = (uptr)MmapFixedNoReserve(kLinuxShadowBeg,
kLinuxShadowEnd - kLinuxShadowBeg);
if (shadow != kLinuxShadowBeg) {
- TsanPrintf("FATAL: ThreadSanitizer can not mmap the shadow memory\n");
- TsanPrintf("FATAL: Make sure to compile with -fPIE and "
- "to link with -pie.\n");
+ Printf("FATAL: ThreadSanitizer can not mmap the shadow memory\n");
+ Printf("FATAL: Make sure to compile with -fPIE and "
+ "to link with -pie.\n");
Die();
}
DPrintf("kLinuxShadow %zx-%zx (%zuGB)\n",
@@ -66,6 +67,7 @@ void InitializeShadowMemory() {
kLinuxAppMemBeg, kLinuxAppMemEnd,
(kLinuxAppMemEnd - kLinuxAppMemBeg) >> 30);
}
+#endif
const char *InitializePlatform() {
void *p = 0;
@@ -78,7 +80,7 @@ const char *InitializePlatform() {
setrlimit(RLIMIT_CORE, (rlimit*)&lim);
}
- return getenv("TSAN_OPTIONS");
+ return getenv(kTsanOptionsEnv);
}
void FinalizePlatform() {
diff --git a/libsanitizer/tsan/tsan_platform_windows.cc b/libsanitizer/tsan/tsan_platform_windows.cc
new file mode 100644
index 000000000000..74b9020d0774
--- /dev/null
+++ b/libsanitizer/tsan/tsan_platform_windows.cc
@@ -0,0 +1,56 @@
+//===-- tsan_platform_windows.cc ------------------------------------------===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+// Windows-specific code.
+//===----------------------------------------------------------------------===//
+
+#ifdef _WIN32
+
+#include "tsan_platform.h"
+
+#include <stdlib.h>
+
+namespace __tsan {
+
+ScopedInRtl::ScopedInRtl() {
+}
+
+ScopedInRtl::~ScopedInRtl() {
+}
+
+uptr GetShadowMemoryConsumption() {
+ return 0;
+}
+
+void FlushShadowMemory() {
+}
+
+const char *InitializePlatform() {
+ return getenv(kTsanOptionsEnv);
+}
+
+void FinalizePlatform() {
+ fflush(0);
+}
+
+uptr GetTlsSize() {
+ return 0;
+}
+
+void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
+ uptr *tls_addr, uptr *tls_size) {
+ *stk_addr = 0;
+ *stk_size = 0;
+ *tls_addr = 0;
+ *tls_size = 0;
+}
+
+} // namespace __tsan
+
+#endif // #ifdef _WIN32
diff --git a/libsanitizer/tsan/tsan_printf.cc b/libsanitizer/tsan/tsan_printf.cc
deleted file mode 100644
index 982e2925dc3d..000000000000
--- a/libsanitizer/tsan/tsan_printf.cc
+++ /dev/null
@@ -1,38 +0,0 @@
-//===-- tsan_printf.cc ----------------------------------------------------===//
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is a part of ThreadSanitizer (TSan), a race detector.
-//
-//===----------------------------------------------------------------------===//
-
-#include "sanitizer_common/sanitizer_common.h"
-#include "sanitizer_common/sanitizer_libc.h"
-#include "tsan_defs.h"
-#include "tsan_mman.h"
-#include "tsan_platform.h"
-
-#include <stdarg.h> // va_list
-
-namespace __sanitizer {
-int VSNPrintf(char *buff, int buff_length, const char *format, va_list args);
-} // namespace __sanitizer
-
-namespace __tsan {
-
-void TsanPrintf(const char *format, ...) {
- ScopedInRtl in_rtl;
- const uptr kMaxLen = 16 * 1024;
- InternalScopedBuffer<char> buffer(kMaxLen);
- va_list args;
- va_start(args, format);
- uptr len = VSNPrintf(buffer.data(), buffer.size(), format, args);
- va_end(args);
- internal_write(CTX() ? flags()->log_fileno : 2,
- buffer.data(), len < buffer.size() ? len : buffer.size() - 1);
-}
-
-} // namespace __tsan
diff --git a/libsanitizer/tsan/tsan_report.cc b/libsanitizer/tsan/tsan_report.cc
index 716a20f1213f..62e0b0c33142 100644
--- a/libsanitizer/tsan/tsan_report.cc
+++ b/libsanitizer/tsan/tsan_report.cc
@@ -29,98 +29,102 @@ ReportDesc::~ReportDesc() {
#ifndef TSAN_GO
static void PrintHeader(ReportType typ) {
- TsanPrintf("WARNING: ThreadSanitizer: ");
+ Printf("WARNING: ThreadSanitizer: ");
if (typ == ReportTypeRace)
- TsanPrintf("data race");
+ Printf("data race");
else if (typ == ReportTypeUseAfterFree)
- TsanPrintf("heap-use-after-free");
+ Printf("heap-use-after-free");
else if (typ == ReportTypeThreadLeak)
- TsanPrintf("thread leak");
+ Printf("thread leak");
else if (typ == ReportTypeMutexDestroyLocked)
- TsanPrintf("destroy of a locked mutex");
+ Printf("destroy of a locked mutex");
else if (typ == ReportTypeSignalUnsafe)
- TsanPrintf("signal-unsafe call inside of a signal");
+ Printf("signal-unsafe call inside of a signal");
else if (typ == ReportTypeErrnoInSignal)
- TsanPrintf("signal handler spoils errno");
+ Printf("signal handler spoils errno");
- TsanPrintf(" (pid=%d)\n", GetPid());
+ Printf(" (pid=%d)\n", GetPid());
}
void PrintStack(const ReportStack *ent) {
+ if (ent == 0) {
+ Printf(" [failed to restore the stack]\n\n");
+ return;
+ }
for (int i = 0; ent; ent = ent->next, i++) {
- TsanPrintf(" #%d %s %s:%d", i, ent->func, ent->file, ent->line);
+ Printf(" #%d %s %s:%d", i, ent->func, ent->file, ent->line);
if (ent->col)
- TsanPrintf(":%d", ent->col);
+ Printf(":%d", ent->col);
if (ent->module && ent->offset)
- TsanPrintf(" (%s+%p)\n", ent->module, (void*)ent->offset);
+ Printf(" (%s+%p)\n", ent->module, (void*)ent->offset);
else
- TsanPrintf(" (%p)\n", (void*)ent->pc);
+ Printf(" (%p)\n", (void*)ent->pc);
}
- TsanPrintf("\n");
+ Printf("\n");
}
static void PrintMop(const ReportMop *mop, bool first) {
- TsanPrintf(" %s of size %d at %p",
+ Printf(" %s of size %d at %p",
(first ? (mop->write ? "Write" : "Read")
: (mop->write ? "Previous write" : "Previous read")),
mop->size, (void*)mop->addr);
if (mop->tid == 0)
- TsanPrintf(" by main thread:\n");
+ Printf(" by main thread:\n");
else
- TsanPrintf(" by thread %d:\n", mop->tid);
+ Printf(" by thread %d:\n", mop->tid);
PrintStack(mop->stack);
}
static void PrintLocation(const ReportLocation *loc) {
if (loc->type == ReportLocationGlobal) {
- TsanPrintf(" Location is global '%s' of size %zu at %zx %s:%d\n",
+ Printf(" Location is global '%s' of size %zu at %zx %s:%d\n",
loc->name, loc->size, loc->addr, loc->file, loc->line);
} else if (loc->type == ReportLocationHeap) {
- TsanPrintf(" Location is heap block of size %zu at %p allocated",
+ Printf(" Location is heap block of size %zu at %p allocated",
loc->size, loc->addr);
if (loc->tid == 0)
- TsanPrintf(" by main thread:\n");
+ Printf(" by main thread:\n");
else
- TsanPrintf(" by thread %d:\n", loc->tid);
+ Printf(" by thread %d:\n", loc->tid);
PrintStack(loc->stack);
} else if (loc->type == ReportLocationStack) {
- TsanPrintf(" Location is stack of thread %d:\n", loc->tid);
+ Printf(" Location is stack of thread %d:\n", loc->tid);
}
}
static void PrintMutex(const ReportMutex *rm) {
if (rm->stack == 0)
return;
- TsanPrintf(" Mutex %d created at:\n", rm->id);
+ Printf(" Mutex %d created at:\n", rm->id);
PrintStack(rm->stack);
}
static void PrintThread(const ReportThread *rt) {
if (rt->id == 0) // Little sense in describing the main thread.
return;
- TsanPrintf(" Thread %d", rt->id);
+ Printf(" Thread %d", rt->id);
if (rt->name)
- TsanPrintf(" '%s'", rt->name);
- TsanPrintf(" (tid=%zu, %s)", rt->pid, rt->running ? "running" : "finished");
+ Printf(" '%s'", rt->name);
+ Printf(" (tid=%zu, %s)", rt->pid, rt->running ? "running" : "finished");
if (rt->stack)
- TsanPrintf(" created at:");
- TsanPrintf("\n");
+ Printf(" created at:");
+ Printf("\n");
PrintStack(rt->stack);
}
static void PrintSleep(const ReportStack *s) {
- TsanPrintf(" As if synchronized via sleep:\n");
+ Printf(" As if synchronized via sleep:\n");
PrintStack(s);
}
void PrintReport(const ReportDesc *rep) {
- TsanPrintf("==================\n");
+ Printf("==================\n");
PrintHeader(rep->typ);
for (uptr i = 0; i < rep->stacks.Size(); i++) {
if (i)
- TsanPrintf(" and:\n");
+ Printf(" and:\n");
PrintStack(rep->stacks[i]);
}
@@ -139,21 +143,21 @@ void PrintReport(const ReportDesc *rep) {
for (uptr i = 0; i < rep->threads.Size(); i++)
PrintThread(rep->threads[i]);
- TsanPrintf("==================\n");
+ Printf("==================\n");
}
#else
void PrintStack(const ReportStack *ent) {
for (int i = 0; ent; ent = ent->next, i++) {
- TsanPrintf(" %s()\n %s:%d +0x%zx\n",
+ Printf(" %s()\n %s:%d +0x%zx\n",
ent->func, ent->file, ent->line, (void*)ent->offset);
}
- TsanPrintf("\n");
+ Printf("\n");
}
static void PrintMop(const ReportMop *mop, bool first) {
- TsanPrintf("%s by goroutine %d:\n",
+ Printf("%s by goroutine %d:\n",
(first ? (mop->write ? "Write" : "Read")
: (mop->write ? "Previous write" : "Previous read")),
mop->tid);
@@ -163,19 +167,19 @@ static void PrintMop(const ReportMop *mop, bool first) {
static void PrintThread(const ReportThread *rt) {
if (rt->id == 0) // Little sense in describing the main thread.
return;
- TsanPrintf("Goroutine %d (%s) created at:\n",
+ Printf("Goroutine %d (%s) created at:\n",
rt->id, rt->running ? "running" : "finished");
PrintStack(rt->stack);
}
void PrintReport(const ReportDesc *rep) {
- TsanPrintf("==================\n");
- TsanPrintf("WARNING: DATA RACE\n");
+ Printf("==================\n");
+ Printf("WARNING: DATA RACE\n");
for (uptr i = 0; i < rep->mops.Size(); i++)
PrintMop(rep->mops[i], i == 0);
for (uptr i = 0; i < rep->threads.Size(); i++)
PrintThread(rep->threads[i]);
- TsanPrintf("==================\n");
+ Printf("==================\n");
}
#endif
diff --git a/libsanitizer/tsan/tsan_rtl.cc b/libsanitizer/tsan/tsan_rtl.cc
index 4ff26973ce3e..a3e82710d901 100644
--- a/libsanitizer/tsan/tsan_rtl.cc
+++ b/libsanitizer/tsan/tsan_rtl.cc
@@ -137,7 +137,7 @@ static void InitializeMemoryProfile() {
flags()->profile_memory, GetPid());
fd_t fd = internal_open(filename.data(), true);
if (fd == kInvalidFd) {
- TsanPrintf("Failed to open memory profile file '%s'\n", &filename[0]);
+ Printf("Failed to open memory profile file '%s'\n", &filename[0]);
Die();
}
internal_start_thread(&MemoryProfileThread, (void*)(uptr)fd);
@@ -159,6 +159,10 @@ static void InitializeMemoryFlush() {
internal_start_thread(&MemoryFlushThread, 0);
}
+void MapShadow(uptr addr, uptr size) {
+ MmapFixedNoReserve(MemToShadow(addr), size * kShadowMultiplier);
+}
+
void Initialize(ThreadState *thr) {
// Thread safe because done before all threads exist.
static bool is_initialized = false;
@@ -177,24 +181,32 @@ void Initialize(ThreadState *thr) {
InitializeMutex();
InitializeDynamicAnnotations();
ctx = new(ctx_placeholder) Context;
+#ifndef TSAN_GO
InitializeShadowMemory();
+#endif
ctx->dead_list_size = 0;
ctx->dead_list_head = 0;
ctx->dead_list_tail = 0;
InitializeFlags(&ctx->flags, env);
+ // Setup correct file descriptor for error reports.
+ __sanitizer_set_report_fd(flags()->log_fileno);
InitializeSuppressions();
#ifndef TSAN_GO
// Initialize external symbolizer before internal threads are started.
const char *external_symbolizer = flags()->external_symbolizer_path;
if (external_symbolizer != 0 && external_symbolizer[0] != '\0') {
- InitializeExternalSymbolizer(external_symbolizer);
+ if (!InitializeExternalSymbolizer(external_symbolizer)) {
+ Printf("Failed to start external symbolizer: '%s'\n",
+ external_symbolizer);
+ Die();
+ }
}
#endif
InitializeMemoryProfile();
InitializeMemoryFlush();
if (ctx->flags.verbosity)
- TsanPrintf("***** Running under ThreadSanitizer v2 (pid %d) *****\n",
+ Printf("***** Running under ThreadSanitizer v2 (pid %d) *****\n",
GetPid());
// Initialize thread 0.
@@ -206,7 +218,7 @@ void Initialize(ThreadState *thr) {
ctx->initialized = true;
if (flags()->stop_on_start) {
- TsanPrintf("ThreadSanitizer is suspended at startup (pid %d)."
+ Printf("ThreadSanitizer is suspended at startup (pid %d)."
" Call __tsan_resume().\n",
GetPid());
while (__tsan_resumed == 0);
@@ -218,6 +230,9 @@ int Finalize(ThreadState *thr) {
Context *ctx = __tsan::ctx;
bool failed = false;
+ if (flags()->atexit_sleep_ms > 0 && ThreadCount(thr) > 1)
+ SleepForMillis(flags()->atexit_sleep_ms);
+
// Wait for pending reports.
ctx->report_mtx.Lock();
ctx->report_mtx.Unlock();
@@ -226,15 +241,20 @@ int Finalize(ThreadState *thr) {
if (ctx->nreported) {
failed = true;
- TsanPrintf("ThreadSanitizer: reported %d warnings\n", ctx->nreported);
+#ifndef TSAN_GO
+ Printf("ThreadSanitizer: reported %d warnings\n", ctx->nreported);
+#else
+ Printf("Found %d data race(s)\n", ctx->nreported);
+#endif
}
if (ctx->nmissed_expected) {
failed = true;
- TsanPrintf("ThreadSanitizer: missed %d expected races\n",
+ Printf("ThreadSanitizer: missed %d expected races\n",
ctx->nmissed_expected);
}
+ StatAggregate(ctx->stat, thr->stat);
StatOutput(ctx->stat);
return failed ? flags()->exitcode : 0;
}
@@ -298,18 +318,22 @@ static inline void HandleRace(ThreadState *thr, u64 *shadow_mem,
thr->racy_state[0] = cur.raw();
thr->racy_state[1] = old.raw();
thr->racy_shadow_addr = shadow_mem;
+#ifndef TSAN_GO
+ HACKY_CALL(__tsan_report_race);
+#else
ReportRace(thr);
+#endif
}
static inline bool BothReads(Shadow s, int kAccessIsWrite) {
return !kAccessIsWrite && !s.is_write();
}
-static inline bool OldIsRWStronger(Shadow old, int kAccessIsWrite) {
+static inline bool OldIsRWNotWeaker(Shadow old, int kAccessIsWrite) {
return old.is_write() || !kAccessIsWrite;
}
-static inline bool OldIsRWWeaker(Shadow old, int kAccessIsWrite) {
+static inline bool OldIsRWWeakerOrEqual(Shadow old, int kAccessIsWrite) {
return !old.is_write() || kAccessIsWrite;
}
@@ -323,7 +347,7 @@ static inline bool HappensBefore(Shadow old, ThreadState *thr) {
ALWAYS_INLINE
void MemoryAccessImpl(ThreadState *thr, uptr addr,
- int kAccessSizeLog, bool kAccessIsWrite, FastState fast_state,
+ int kAccessSizeLog, bool kAccessIsWrite,
u64 *shadow_mem, Shadow cur) {
StatInc(thr, StatMop);
StatInc(thr, kAccessIsWrite ? StatMopWrite : StatMopRead);
@@ -407,11 +431,11 @@ void MemoryAccess(ThreadState *thr, uptr pc, uptr addr,
(uptr)shadow_mem[2], (uptr)shadow_mem[3]);
#if TSAN_DEBUG
if (!IsAppMem(addr)) {
- TsanPrintf("Access to non app mem %zx\n", addr);
+ Printf("Access to non app mem %zx\n", addr);
DCHECK(IsAppMem(addr));
}
if (!IsShadowMem((uptr)shadow_mem)) {
- TsanPrintf("Bad shadow addr %p (%zx)\n", shadow_mem, addr);
+ Printf("Bad shadow addr %p (%zx)\n", shadow_mem, addr);
DCHECK(IsShadowMem((uptr)shadow_mem));
}
#endif
@@ -429,7 +453,7 @@ void MemoryAccess(ThreadState *thr, uptr pc, uptr addr,
// That is, this call must be moved somewhere below.
TraceAddEvent(thr, fast_state.epoch(), EventTypeMop, pc);
- MemoryAccessImpl(thr, addr, kAccessSizeLog, kAccessIsWrite, fast_state,
+ MemoryAccessImpl(thr, addr, kAccessSizeLog, kAccessIsWrite,
shadow_mem, cur);
}
@@ -491,6 +515,7 @@ void MemoryRangeImitateWrite(ThreadState *thr, uptr pc, uptr addr, uptr size) {
MemoryRangeSet(thr, pc, addr, size, s.raw());
}
+ALWAYS_INLINE
void FuncEntry(ThreadState *thr, uptr pc) {
DCHECK_EQ(thr->in_rtl, 0);
StatInc(thr, StatFuncEnter);
@@ -520,6 +545,7 @@ void FuncEntry(ThreadState *thr, uptr pc) {
thr->shadow_stack_pos++;
}
+ALWAYS_INLINE
void FuncExit(ThreadState *thr) {
DCHECK_EQ(thr->in_rtl, 0);
StatInc(thr, StatFuncExit);
diff --git a/libsanitizer/tsan/tsan_rtl.h b/libsanitizer/tsan/tsan_rtl.h
index 3df229c88441..de357a5d5a0e 100644
--- a/libsanitizer/tsan/tsan_rtl.h
+++ b/libsanitizer/tsan/tsan_rtl.h
@@ -25,11 +25,7 @@
#define TSAN_RTL_H
#include "sanitizer_common/sanitizer_common.h"
-#if __WORDSIZE == 64
#include "sanitizer_common/sanitizer_allocator64.h"
-#else
-#include "sanitizer_common/sanitizer_allocator.h"
-#endif
#include "tsan_clock.h"
#include "tsan_defs.h"
#include "tsan_flags.h"
@@ -69,7 +65,6 @@ Allocator *allocator();
void TsanCheckFailed(const char *file, int line, const char *cond,
u64 v1, u64 v2);
-void TsanPrintf(const char *format, ...);
// FastState (from most significant bit):
// unused : 1
@@ -234,10 +229,6 @@ class Shadow : public FastState {
}
};
-// Freed memory.
-// As if 8-byte write by thread 0xff..f at epoch 0xff..f, races with everything.
-const u64 kShadowFreed = 0xfffffffffffffff8ull;
-
struct SignalContext;
// This struct is stored in TLS.
@@ -442,6 +433,7 @@ void ALWAYS_INLINE INLINE StatInc(ThreadState *thr, StatType typ, u64 n = 1) {
thr->stat[typ] += n;
}
+void MapShadow(uptr addr, uptr size);
void InitializeShadowMemory();
void InitializeInterceptors();
void InitializeDynamicAnnotations();
@@ -456,13 +448,13 @@ bool IsFiredSuppression(Context *ctx,
bool IsExpectedReport(uptr addr, uptr size);
#if defined(TSAN_DEBUG_OUTPUT) && TSAN_DEBUG_OUTPUT >= 1
-# define DPrintf TsanPrintf
+# define DPrintf Printf
#else
# define DPrintf(...)
#endif
#if defined(TSAN_DEBUG_OUTPUT) && TSAN_DEBUG_OUTPUT >= 2
-# define DPrintf2 TsanPrintf
+# define DPrintf2 Printf
#else
# define DPrintf2(...)
#endif
@@ -476,7 +468,7 @@ int Finalize(ThreadState *thr);
void MemoryAccess(ThreadState *thr, uptr pc, uptr addr,
int kAccessSizeLog, bool kAccessIsWrite);
void MemoryAccessImpl(ThreadState *thr, uptr addr,
- int kAccessSizeLog, bool kAccessIsWrite, FastState fast_state,
+ int kAccessSizeLog, bool kAccessIsWrite,
u64 *shadow_mem, Shadow cur);
void MemoryRead1Byte(ThreadState *thr, uptr pc, uptr addr);
void MemoryWrite1Byte(ThreadState *thr, uptr pc, uptr addr);
@@ -499,7 +491,8 @@ int ThreadTid(ThreadState *thr, uptr pc, uptr uid);
void ThreadJoin(ThreadState *thr, uptr pc, int tid);
void ThreadDetach(ThreadState *thr, uptr pc, int tid);
void ThreadFinalize(ThreadState *thr);
-void ThreadFinalizerGoroutine(ThreadState *thr);
+int ThreadCount(ThreadState *thr);
+void ProcessPendingSignals(ThreadState *thr);
void MutexCreate(ThreadState *thr, uptr pc, uptr addr,
bool rw, bool recursive, bool linker_init);
@@ -511,6 +504,7 @@ void MutexReadUnlock(ThreadState *thr, uptr pc, uptr addr);
void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr);
void Acquire(ThreadState *thr, uptr pc, uptr addr);
+void AcquireGlobal(ThreadState *thr, uptr pc);
void Release(ThreadState *thr, uptr pc, uptr addr);
void ReleaseStore(ThreadState *thr, uptr pc, uptr addr);
void AfterSleep(ThreadState *thr, uptr pc);
@@ -521,7 +515,7 @@ void AfterSleep(ThreadState *thr, uptr pc);
// The trick is that the call preserves all registers and the compiler
// does not treat it as a call.
// If it does not work for you, use normal call.
-#if TSAN_DEBUG == 0
+#if 0 && TSAN_DEBUG == 0
// The caller may not create the stack frame for itself at all,
// so we create a reserve stack frame for it (1024b must be enough).
#define HACKY_CALL(f) \
@@ -542,7 +536,11 @@ void ALWAYS_INLINE INLINE TraceAddEvent(ThreadState *thr, u64 epoch,
EventType typ, uptr addr) {
StatInc(thr, StatEvents);
if (UNLIKELY((epoch % kTracePartSize) == 0)) {
+#ifndef TSAN_GO
+ HACKY_CALL(__tsan_trace_switch);
+#else
TraceSwitch(thr);
+#endif
}
Event *evp = &thr->trace.events[epoch % kTraceSize];
Event ev = (u64)addr | ((u64)typ << 61);
diff --git a/libsanitizer/tsan/tsan_rtl_mutex.cc b/libsanitizer/tsan/tsan_rtl_mutex.cc
index 098894f5caa8..9ace430bc586 100644
--- a/libsanitizer/tsan/tsan_rtl_mutex.cc
+++ b/libsanitizer/tsan/tsan_rtl_mutex.cc
@@ -82,7 +82,7 @@ void MutexLock(ThreadState *thr, uptr pc, uptr addr) {
} else if (s->owner_tid == thr->tid) {
CHECK_GT(s->recursion, 0);
} else {
- TsanPrintf("ThreadSanitizer WARNING: double lock\n");
+ Printf("ThreadSanitizer WARNING: double lock\n");
PrintCurrentStack(thr, pc);
}
if (s->recursion == 0) {
@@ -110,13 +110,13 @@ void MutexUnlock(ThreadState *thr, uptr pc, uptr addr) {
if (s->recursion == 0) {
if (!s->is_broken) {
s->is_broken = true;
- TsanPrintf("ThreadSanitizer WARNING: unlock of unlocked mutex\n");
+ Printf("ThreadSanitizer WARNING: unlock of unlocked mutex\n");
PrintCurrentStack(thr, pc);
}
} else if (s->owner_tid != thr->tid) {
if (!s->is_broken) {
s->is_broken = true;
- TsanPrintf("ThreadSanitizer WARNING: mutex unlock by another thread\n");
+ Printf("ThreadSanitizer WARNING: mutex unlock by another thread\n");
PrintCurrentStack(thr, pc);
}
} else {
@@ -145,7 +145,7 @@ void MutexReadLock(ThreadState *thr, uptr pc, uptr addr) {
TraceAddEvent(thr, thr->fast_state.epoch(), EventTypeRLock, addr);
SyncVar *s = CTX()->synctab.GetAndLock(thr, pc, addr, false);
if (s->owner_tid != SyncVar::kInvalidTid) {
- TsanPrintf("ThreadSanitizer WARNING: read lock of a write locked mutex\n");
+ Printf("ThreadSanitizer WARNING: read lock of a write locked mutex\n");
PrintCurrentStack(thr, pc);
}
thr->clock.set(thr->tid, thr->fast_state.epoch());
@@ -165,7 +165,7 @@ void MutexReadUnlock(ThreadState *thr, uptr pc, uptr addr) {
TraceAddEvent(thr, thr->fast_state.epoch(), EventTypeRUnlock, addr);
SyncVar *s = CTX()->synctab.GetAndLock(thr, pc, addr, true);
if (s->owner_tid != SyncVar::kInvalidTid) {
- TsanPrintf("ThreadSanitizer WARNING: read unlock of a write "
+ Printf("ThreadSanitizer WARNING: read unlock of a write "
"locked mutex\n");
PrintCurrentStack(thr, pc);
}
@@ -213,7 +213,7 @@ void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr) {
}
} else if (!s->is_broken) {
s->is_broken = true;
- TsanPrintf("ThreadSanitizer WARNING: mutex unlock by another thread\n");
+ Printf("ThreadSanitizer WARNING: mutex unlock by another thread\n");
PrintCurrentStack(thr, pc);
}
s->mtx.Unlock();
@@ -229,6 +229,20 @@ void Acquire(ThreadState *thr, uptr pc, uptr addr) {
s->mtx.ReadUnlock();
}
+void AcquireGlobal(ThreadState *thr, uptr pc) {
+ Context *ctx = CTX();
+ Lock l(&ctx->thread_mtx);
+ for (unsigned i = 0; i < kMaxTid; i++) {
+ ThreadContext *tctx = ctx->threads[i];
+ if (tctx == 0)
+ continue;
+ if (tctx->status == ThreadStatusRunning)
+ thr->clock.set(i, tctx->thr->fast_state.epoch());
+ else
+ thr->clock.set(i, tctx->epoch1);
+ }
+}
+
void Release(ThreadState *thr, uptr pc, uptr addr) {
CHECK_GT(thr->in_rtl, 0);
DPrintf("#%d: Release %zx\n", thr->tid, addr);
diff --git a/libsanitizer/tsan/tsan_rtl_report.cc b/libsanitizer/tsan/tsan_rtl_report.cc
index 1511913d7428..24e29d25400c 100644
--- a/libsanitizer/tsan/tsan_rtl_report.cc
+++ b/libsanitizer/tsan/tsan_rtl_report.cc
@@ -26,9 +26,9 @@ namespace __tsan {
void TsanCheckFailed(const char *file, int line, const char *cond,
u64 v1, u64 v2) {
ScopedInRtl in_rtl;
- TsanPrintf("FATAL: ThreadSanitizer CHECK failed: "
- "%s:%d \"%s\" (0x%zx, 0x%zx)\n",
- file, line, cond, (uptr)v1, (uptr)v2);
+ Printf("FATAL: ThreadSanitizer CHECK failed: "
+ "%s:%d \"%s\" (0x%zx, 0x%zx)\n",
+ file, line, cond, (uptr)v1, (uptr)v2);
Die();
}
@@ -383,6 +383,8 @@ bool IsFiredSuppression(Context *ctx,
}
void ReportRace(ThreadState *thr) {
+ if (!flags()->report_bugs)
+ return;
ScopedInRtl in_rtl;
bool freed = false;
diff --git a/libsanitizer/tsan/tsan_rtl_thread.cc b/libsanitizer/tsan/tsan_rtl_thread.cc
index 0ae658c17438..bb7f35c24ed4 100644
--- a/libsanitizer/tsan/tsan_rtl_thread.cc
+++ b/libsanitizer/tsan/tsan_rtl_thread.cc
@@ -50,6 +50,23 @@ void ThreadFinalize(ThreadState *thr) {
}
}
+int ThreadCount(ThreadState *thr) {
+ CHECK_GT(thr->in_rtl, 0);
+ Context *ctx = CTX();
+ Lock l(&ctx->thread_mtx);
+ int cnt = 0;
+ for (unsigned i = 0; i < kMaxTid; i++) {
+ ThreadContext *tctx = ctx->threads[i];
+ if (tctx == 0)
+ continue;
+ if (tctx->status != ThreadStatusCreated
+ && tctx->status != ThreadStatusRunning)
+ continue;
+ cnt++;
+ }
+ return cnt;
+}
+
static void ThreadDead(ThreadState *thr, ThreadContext *tctx) {
Context *ctx = CTX();
CHECK_GT(thr->in_rtl, 0);
@@ -80,7 +97,7 @@ int ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached) {
if (ctx->dead_list_size > kThreadQuarantineSize
|| ctx->thread_seq >= kMaxTid) {
if (ctx->dead_list_size == 0) {
- TsanPrintf("ThreadSanitizer: %d thread limit exceeded. Dying.\n",
+ Printf("ThreadSanitizer: %d thread limit exceeded. Dying.\n",
kMaxTid);
Die();
}
@@ -273,7 +290,7 @@ void ThreadJoin(ThreadState *thr, uptr pc, int tid) {
Lock l(&ctx->thread_mtx);
ThreadContext *tctx = ctx->threads[tid];
if (tctx->status == ThreadStatusInvalid) {
- TsanPrintf("ThreadSanitizer: join of non-existent thread\n");
+ Printf("ThreadSanitizer: join of non-existent thread\n");
return;
}
CHECK_EQ(tctx->detached, false);
@@ -291,7 +308,7 @@ void ThreadDetach(ThreadState *thr, uptr pc, int tid) {
Lock l(&ctx->thread_mtx);
ThreadContext *tctx = ctx->threads[tid];
if (tctx->status == ThreadStatusInvalid) {
- TsanPrintf("ThreadSanitizer: detach of non-existent thread\n");
+ Printf("ThreadSanitizer: detach of non-existent thread\n");
return;
}
if (tctx->status == ThreadStatusFinished) {
@@ -301,10 +318,6 @@ void ThreadDetach(ThreadState *thr, uptr pc, int tid) {
}
}
-void ThreadFinalizerGoroutine(ThreadState *thr) {
- thr->clock.Disable(thr->tid);
-}
-
void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr,
uptr size, bool is_write) {
if (size == 0)
@@ -317,19 +330,19 @@ void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr,
#if TSAN_DEBUG
if (!IsAppMem(addr)) {
- TsanPrintf("Access to non app mem %zx\n", addr);
+ Printf("Access to non app mem %zx\n", addr);
DCHECK(IsAppMem(addr));
}
if (!IsAppMem(addr + size - 1)) {
- TsanPrintf("Access to non app mem %zx\n", addr + size - 1);
+ Printf("Access to non app mem %zx\n", addr + size - 1);
DCHECK(IsAppMem(addr + size - 1));
}
if (!IsShadowMem((uptr)shadow_mem)) {
- TsanPrintf("Bad shadow addr %p (%zx)\n", shadow_mem, addr);
+ Printf("Bad shadow addr %p (%zx)\n", shadow_mem, addr);
DCHECK(IsShadowMem((uptr)shadow_mem));
}
if (!IsShadowMem((uptr)(shadow_mem + size * kShadowCnt / 8 - 1))) {
- TsanPrintf("Bad shadow addr %p (%zx)\n",
+ Printf("Bad shadow addr %p (%zx)\n",
shadow_mem + size * kShadowCnt / 8 - 1, addr + size - 1);
DCHECK(IsShadowMem((uptr)(shadow_mem + size * kShadowCnt / 8 - 1)));
}
@@ -353,7 +366,7 @@ void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr,
Shadow cur(fast_state);
cur.SetWrite(is_write);
cur.SetAddr0AndSizeLog(addr & (kShadowCell - 1), kAccessSizeLog);
- MemoryAccessImpl(thr, addr, kAccessSizeLog, is_write, fast_state,
+ MemoryAccessImpl(thr, addr, kAccessSizeLog, is_write,
shadow_mem, cur);
}
if (unaligned)
@@ -364,7 +377,7 @@ void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr,
Shadow cur(fast_state);
cur.SetWrite(is_write);
cur.SetAddr0AndSizeLog(0, kAccessSizeLog);
- MemoryAccessImpl(thr, addr, kAccessSizeLog, is_write, fast_state,
+ MemoryAccessImpl(thr, addr, kAccessSizeLog, is_write,
shadow_mem, cur);
shadow_mem += kShadowCnt;
}
@@ -374,7 +387,7 @@ void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr,
Shadow cur(fast_state);
cur.SetWrite(is_write);
cur.SetAddr0AndSizeLog(addr & (kShadowCell - 1), kAccessSizeLog);
- MemoryAccessImpl(thr, addr, kAccessSizeLog, is_write, fast_state,
+ MemoryAccessImpl(thr, addr, kAccessSizeLog, is_write,
shadow_mem, cur);
}
}
diff --git a/libsanitizer/tsan/tsan_stat.cc b/libsanitizer/tsan/tsan_stat.cc
index fcbc631e086d..68acae81e666 100644
--- a/libsanitizer/tsan/tsan_stat.cc
+++ b/libsanitizer/tsan/tsan_stat.cc
@@ -194,7 +194,12 @@ void StatOutput(u64 *stat) {
name[StatInt_opendir] = " opendir ";
name[StatInt_epoll_ctl] = " epoll_ctl ";
name[StatInt_epoll_wait] = " epoll_wait ";
+ name[StatInt_poll] = " poll ";
name[StatInt_sigaction] = " sigaction ";
+ name[StatInt_sleep] = " sleep ";
+ name[StatInt_usleep] = " usleep ";
+ name[StatInt_nanosleep] = " nanosleep ";
+ name[StatInt_gettimeofday] = " gettimeofday ";
name[StatAnnotation] = "Dynamic annotations ";
name[StatAnnotateHappensBefore] = " HappensBefore ";
@@ -239,9 +244,9 @@ void StatOutput(u64 *stat) {
name[StatMtxAtExit] = " Atexit ";
name[StatMtxAnnotations] = " Annotations ";
- TsanPrintf("Statistics:\n");
+ Printf("Statistics:\n");
for (int i = 0; i < StatCnt; i++)
- TsanPrintf("%s: %zu\n", name[i], (uptr)stat[i]);
+ Printf("%s: %zu\n", name[i], (uptr)stat[i]);
}
} // namespace __tsan
diff --git a/libsanitizer/tsan/tsan_stat.h b/libsanitizer/tsan/tsan_stat.h
index b194343a08a9..25bff8b7080b 100644
--- a/libsanitizer/tsan/tsan_stat.h
+++ b/libsanitizer/tsan/tsan_stat.h
@@ -193,6 +193,7 @@ enum StatType {
StatInt_opendir,
StatInt_epoll_ctl,
StatInt_epoll_wait,
+ StatInt_poll,
StatInt_sigaction,
StatInt_signal,
StatInt_raise,
@@ -201,6 +202,7 @@ enum StatType {
StatInt_sleep,
StatInt_usleep,
StatInt_nanosleep,
+ StatInt_gettimeofday,
// Dynamic annotations.
StatAnnotation,
diff --git a/libsanitizer/tsan/tsan_suppressions.cc b/libsanitizer/tsan/tsan_suppressions.cc
index 9b087add3c26..3f825a804a13 100644
--- a/libsanitizer/tsan/tsan_suppressions.cc
+++ b/libsanitizer/tsan/tsan_suppressions.cc
@@ -31,19 +31,19 @@ static char *ReadFile(const char *filename) {
internal_snprintf(tmp.data(), tmp.size(), "%s/%s", GetPwd(), filename);
fd_t fd = internal_open(tmp.data(), false);
if (fd == kInvalidFd) {
- TsanPrintf("ThreadSanitizer: failed to open suppressions file '%s'\n",
+ Printf("ThreadSanitizer: failed to open suppressions file '%s'\n",
tmp.data());
Die();
}
const uptr fsize = internal_filesize(fd);
if (fsize == (uptr)-1) {
- TsanPrintf("ThreadSanitizer: failed to stat suppressions file '%s'\n",
+ Printf("ThreadSanitizer: failed to stat suppressions file '%s'\n",
tmp.data());
Die();
}
char *buf = (char*)internal_alloc(MBlockSuppression, fsize + 1);
if (fsize != internal_read(fd, buf, fsize)) {
- TsanPrintf("ThreadSanitizer: failed to read suppressions file '%s'\n",
+ Printf("ThreadSanitizer: failed to read suppressions file '%s'\n",
tmp.data());
Die();
}
@@ -108,7 +108,7 @@ Suppression *SuppressionParse(const char* supp) {
stype = SuppressionSignal;
line += sizeof("signal:") - 1;
} else {
- TsanPrintf("ThreadSanitizer: failed to parse suppressions file\n");
+ Printf("ThreadSanitizer: failed to parse suppressions file\n");
Die();
}
Suppression *s = (Suppression*)internal_alloc(MBlockSuppression,
diff --git a/libsanitizer/tsan/tsan_symbolize_addr2line_linux.cc b/libsanitizer/tsan/tsan_symbolize_addr2line_linux.cc
index 9caf091fecf8..23540c07ca93 100644
--- a/libsanitizer/tsan/tsan_symbolize_addr2line_linux.cc
+++ b/libsanitizer/tsan/tsan_symbolize_addr2line_linux.cc
@@ -48,17 +48,17 @@ struct DlIteratePhdrCtx {
static void NOINLINE InitModule(ModuleDesc *m) {
int outfd[2] = {};
if (pipe(&outfd[0])) {
- TsanPrintf("ThreadSanitizer: outfd pipe() failed (%d)\n", errno);
+ Printf("ThreadSanitizer: outfd pipe() failed (%d)\n", errno);
Die();
}
int infd[2] = {};
if (pipe(&infd[0])) {
- TsanPrintf("ThreadSanitizer: infd pipe() failed (%d)\n", errno);
+ Printf("ThreadSanitizer: infd pipe() failed (%d)\n", errno);
Die();
}
int pid = fork();
if (pid == 0) {
- flags()->log_fileno = STDERR_FILENO;
+ __sanitizer_set_report_fd(STDERR_FILENO);
internal_close(STDOUT_FILENO);
internal_close(STDIN_FILENO);
internal_dup2(outfd[0], STDIN_FILENO);
@@ -72,7 +72,7 @@ static void NOINLINE InitModule(ModuleDesc *m) {
execl("/usr/bin/addr2line", "/usr/bin/addr2line", "-Cfe", m->fullname, 0);
_exit(0);
} else if (pid < 0) {
- TsanPrintf("ThreadSanitizer: failed to fork symbolizer\n");
+ Printf("ThreadSanitizer: failed to fork symbolizer\n");
Die();
}
internal_close(outfd[0]);
@@ -153,14 +153,14 @@ ReportStack *SymbolizeCodeAddr2Line(uptr addr) {
char addrstr[32];
internal_snprintf(addrstr, sizeof(addrstr), "%p\n", (void*)offset);
if (0 >= internal_write(m->out_fd, addrstr, internal_strlen(addrstr))) {
- TsanPrintf("ThreadSanitizer: can't write from symbolizer (%d, %d)\n",
+ Printf("ThreadSanitizer: can't write from symbolizer (%d, %d)\n",
m->out_fd, errno);
Die();
}
InternalScopedBuffer<char> func(1024);
ssize_t len = internal_read(m->inp_fd, func.data(), func.size() - 1);
if (len <= 0) {
- TsanPrintf("ThreadSanitizer: can't read from symbolizer (%d, %d)\n",
+ Printf("ThreadSanitizer: can't read from symbolizer (%d, %d)\n",
m->inp_fd, errno);
Die();
}
diff --git a/libsanitizer/tsan/tsan_update_shadow_word_inl.h b/libsanitizer/tsan/tsan_update_shadow_word_inl.h
index ae4a318f9525..e22859c1ddeb 100644
--- a/libsanitizer/tsan/tsan_update_shadow_word_inl.h
+++ b/libsanitizer/tsan/tsan_update_shadow_word_inl.h
@@ -32,7 +32,7 @@ do {
if (Shadow::TidsAreEqual(old, cur)) {
StatInc(thr, StatShadowSameThread);
if (OldIsInSameSynchEpoch(old, thr)) {
- if (OldIsRWStronger(old, kAccessIsWrite)) {
+ if (OldIsRWNotWeaker(old, kAccessIsWrite)) {
// found a slot that holds effectively the same info
// (that is, same tid, same sync epoch and same size)
StatInc(thr, StatMopSame);
@@ -41,7 +41,7 @@ do {
StoreIfNotYetStored(sp, &store_word);
break;
}
- if (OldIsRWWeaker(old, kAccessIsWrite))
+ if (OldIsRWWeakerOrEqual(old, kAccessIsWrite))
StoreIfNotYetStored(sp, &store_word);
break;
}