diff options
author | Kostya Serebryany <kcc@google.com> | 2013-12-05 09:18:38 +0000 |
---|---|---|
committer | Kostya Serebryany <kcc@gcc.gnu.org> | 2013-12-05 09:18:38 +0000 |
commit | df77f0e4ec043bc4fa155efbd5c1c74ce73d2b50 (patch) | |
tree | 20d85354103063e38b162a6a90b7ae51fb4b6104 /libsanitizer/tsan/tsan_rtl.cc | |
parent | 649d196dbd78a119786f204d36b7c5d4dcb3a949 (diff) | |
download | gcc-df77f0e4ec043bc4fa155efbd5c1c74ce73d2b50.zip gcc-df77f0e4ec043bc4fa155efbd5c1c74ce73d2b50.tar.gz gcc-df77f0e4ec043bc4fa155efbd5c1c74ce73d2b50.tar.bz2 |
libsanitizer merge from upstream r196090
From-SVN: r205695
Diffstat (limited to 'libsanitizer/tsan/tsan_rtl.cc')
-rw-r--r-- | libsanitizer/tsan/tsan_rtl.cc | 100 |
1 files changed, 75 insertions, 25 deletions
diff --git a/libsanitizer/tsan/tsan_rtl.cc b/libsanitizer/tsan/tsan_rtl.cc index 7f18064..a0f3267 100644 --- a/libsanitizer/tsan/tsan_rtl.cc +++ b/libsanitizer/tsan/tsan_rtl.cc @@ -37,9 +37,13 @@ THREADLOCAL char cur_thread_placeholder[sizeof(ThreadState)] ALIGNED(64); static char ctx_placeholder[sizeof(Context)] ALIGNED(64); // Can be overriden by a front-end. -bool CPP_WEAK OnFinalize(bool failed) { +#ifdef TSAN_EXTERNAL_HOOKS +bool OnFinalize(bool failed); +#else +bool WEAK OnFinalize(bool failed) { return failed; } +#endif static Context *ctx; Context *CTX() { @@ -84,7 +88,6 @@ ThreadState::ThreadState(Context *ctx, int tid, int unique_id, u64 epoch, // they may be accessed before the ctor. // , ignore_reads_and_writes() // , in_rtl() - , shadow_stack_pos(&shadow_stack[0]) #ifndef TSAN_GO , jmp_bufs(MBlockJmpBuf) #endif @@ -128,17 +131,38 @@ static void BackgroundThread(void *arg) { } u64 last_flush = NanoTime(); + uptr last_rss = 0; for (int i = 0; ; i++) { SleepForSeconds(1); u64 now = NanoTime(); // Flush memory if requested. - if (flags()->flush_memory_ms) { + if (flags()->flush_memory_ms > 0) { if (last_flush + flags()->flush_memory_ms * kMs2Ns < now) { + if (flags()->verbosity > 0) + Printf("ThreadSanitizer: periodic memory flush\n"); FlushShadowMemory(); last_flush = NanoTime(); } } + if (flags()->memory_limit_mb > 0) { + uptr rss = GetRSS(); + uptr limit = uptr(flags()->memory_limit_mb) << 20; + if (flags()->verbosity > 0) { + Printf("ThreadSanitizer: memory flush check" + " RSS=%llu LAST=%llu LIMIT=%llu\n", + (u64)rss>>20, (u64)last_rss>>20, (u64)limit>>20); + } + if (2 * rss > limit + last_rss) { + if (flags()->verbosity > 0) + Printf("ThreadSanitizer: flushing memory due to RSS\n"); + FlushShadowMemory(); + rss = GetRSS(); + if (flags()->verbosity > 0) + Printf("ThreadSanitizer: memory flushed RSS=%llu\n", (u64)rss>>20); + } + last_rss = rss; + } // Write memory profile if requested. if (mprof_fd != kInvalidFd) @@ -174,8 +198,10 @@ void MapThreadTrace(uptr addr, uptr size) { DPrintf("#0: Mapping trace at %p-%p(0x%zx)\n", addr, addr + size, size); CHECK_GE(addr, kTraceMemBegin); CHECK_LE(addr + size, kTraceMemBegin + kTraceMemSize); - if (addr != (uptr)MmapFixedNoReserve(addr, size)) { - Printf("FATAL: ThreadSanitizer can not mmap thread trace\n"); + uptr addr1 = (uptr)MmapFixedNoReserve(addr, size); + if (addr1 != addr) { + Printf("FATAL: ThreadSanitizer can not mmap thread trace (%p/%p->%p)\n", + addr, size, addr1); Die(); } } @@ -204,23 +230,21 @@ void Initialize(ThreadState *thr) { #endif InitializeFlags(&ctx->flags, env); // Setup correct file descriptor for error reports. - if (internal_strcmp(flags()->log_path, "stdout") == 0) - __sanitizer_set_report_fd(kStdoutFd); - else if (internal_strcmp(flags()->log_path, "stderr") == 0) - __sanitizer_set_report_fd(kStderrFd); - else - __sanitizer_set_report_path(flags()->log_path); + __sanitizer_set_report_path(flags()->log_path); InitializeSuppressions(); #ifndef TSAN_GO + InitializeLibIgnore(); // Initialize external symbolizer before internal threads are started. const char *external_symbolizer = flags()->external_symbolizer_path; - if (external_symbolizer != 0 && external_symbolizer[0] != '\0') { - if (!getSymbolizer()->InitializeExternal(external_symbolizer)) { - Printf("Failed to start external symbolizer: '%s'\n", - external_symbolizer); - Die(); - } + bool external_symbolizer_started = + Symbolizer::Init(external_symbolizer)->IsExternalAvailable(); + if (external_symbolizer != 0 && external_symbolizer[0] != '\0' && + !external_symbolizer_started) { + Printf("Failed to start external symbolizer: '%s'\n", + external_symbolizer); + Die(); } + Symbolizer::Get()->AddHooks(EnterSymbolizer, ExitSymbolizer); #endif internal_start_thread(&BackgroundThread, 0); @@ -636,9 +660,9 @@ void FuncEntry(ThreadState *thr, uptr pc) { // Shadow stack maintenance can be replaced with // stack unwinding during trace switch (which presumably must be faster). - DCHECK_GE(thr->shadow_stack_pos, &thr->shadow_stack[0]); + DCHECK_GE(thr->shadow_stack_pos, thr->shadow_stack); #ifndef TSAN_GO - DCHECK_LT(thr->shadow_stack_pos, &thr->shadow_stack[kShadowStackSize]); + DCHECK_LT(thr->shadow_stack_pos, thr->shadow_stack_end); #else if (thr->shadow_stack_pos == thr->shadow_stack_end) { const int sz = thr->shadow_stack_end - thr->shadow_stack; @@ -664,26 +688,52 @@ void FuncExit(ThreadState *thr) { thr->fast_state.IncrementEpoch(); TraceAddEvent(thr, thr->fast_state, EventTypeFuncExit, 0); - DCHECK_GT(thr->shadow_stack_pos, &thr->shadow_stack[0]); + DCHECK_GT(thr->shadow_stack_pos, thr->shadow_stack); #ifndef TSAN_GO - DCHECK_LT(thr->shadow_stack_pos, &thr->shadow_stack[kShadowStackSize]); + DCHECK_LT(thr->shadow_stack_pos, thr->shadow_stack_end); #endif thr->shadow_stack_pos--; } -void ThreadIgnoreBegin(ThreadState *thr) { +void ThreadIgnoreBegin(ThreadState *thr, uptr pc) { DPrintf("#%d: ThreadIgnoreBegin\n", thr->tid); thr->ignore_reads_and_writes++; - CHECK_GE(thr->ignore_reads_and_writes, 0); + CHECK_GT(thr->ignore_reads_and_writes, 0); thr->fast_state.SetIgnoreBit(); +#ifndef TSAN_GO + thr->mop_ignore_set.Add(CurrentStackId(thr, pc)); +#endif } -void ThreadIgnoreEnd(ThreadState *thr) { +void ThreadIgnoreEnd(ThreadState *thr, uptr pc) { DPrintf("#%d: ThreadIgnoreEnd\n", thr->tid); thr->ignore_reads_and_writes--; CHECK_GE(thr->ignore_reads_and_writes, 0); - if (thr->ignore_reads_and_writes == 0) + if (thr->ignore_reads_and_writes == 0) { thr->fast_state.ClearIgnoreBit(); +#ifndef TSAN_GO + thr->mop_ignore_set.Reset(); +#endif + } +} + +void ThreadIgnoreSyncBegin(ThreadState *thr, uptr pc) { + DPrintf("#%d: ThreadIgnoreSyncBegin\n", thr->tid); + thr->ignore_sync++; + CHECK_GT(thr->ignore_sync, 0); +#ifndef TSAN_GO + thr->sync_ignore_set.Add(CurrentStackId(thr, pc)); +#endif +} + +void ThreadIgnoreSyncEnd(ThreadState *thr, uptr pc) { + DPrintf("#%d: ThreadIgnoreSyncEnd\n", thr->tid); + thr->ignore_sync--; + CHECK_GE(thr->ignore_sync, 0); +#ifndef TSAN_GO + if (thr->ignore_sync == 0) + thr->mop_ignore_set.Reset(); +#endif } bool MD5Hash::operator==(const MD5Hash &other) const { |