diff options
author | Dmitry Vyukov <dvyukov@google.com> | 2012-08-31 17:27:49 +0000 |
---|---|---|
committer | Dmitry Vyukov <dvyukov@google.com> | 2012-08-31 17:27:49 +0000 |
commit | 848531192777acecf79747dc7c1ffeedf5c1da9f (patch) | |
tree | 557b970b78bf62eb5d431982a285ef7ebf36be69 /lib/tsan/rtl | |
parent | 1b1de03d493b5d4950988924ee4ad900b6c78008 (diff) | |
download | compiler-rt-848531192777acecf79747dc7c1ffeedf5c1da9f.tar.gz |
tsan: add "as if synchronized via sleep" feature
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@163006 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/tsan/rtl')
-rw-r--r-- | lib/tsan/rtl/tsan_interceptors.cc | 27 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_mman.cc | 6 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_report.cc | 11 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_report.h | 1 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_rtl.cc | 15 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_rtl.h | 9 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_rtl_mutex.cc | 17 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_rtl_report.cc | 18 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_stat.h | 3 |
9 files changed, 99 insertions, 8 deletions
diff --git a/lib/tsan/rtl/tsan_interceptors.cc b/lib/tsan/rtl/tsan_interceptors.cc index 1dce12bca..f0a46ac61 100644 --- a/lib/tsan/rtl/tsan_interceptors.cc +++ b/lib/tsan/rtl/tsan_interceptors.cc @@ -51,7 +51,6 @@ extern "C" void *pthread_self(); extern "C" void _exit(int status); extern "C" int __cxa_atexit(void (*func)(void *arg), void *arg, void *dso); extern "C" int *__errno_location(); -extern "C" int usleep(unsigned usec); const int PTHREAD_MUTEX_RECURSIVE = 1; const int PTHREAD_MUTEX_RECURSIVE_NP = 1; const int kPthreadAttrSize = 56; @@ -213,6 +212,27 @@ static void invoke_free_hook(void *ptr) { __tsan_free_hook(ptr); } +TSAN_INTERCEPTOR(unsigned, sleep, unsigned sec) { + SCOPED_TSAN_INTERCEPTOR(sleep, sec); + unsigned res = sleep(sec); + AfterSleep(thr, pc); + return res; +} + +TSAN_INTERCEPTOR(int, usleep, long_t usec) { + SCOPED_TSAN_INTERCEPTOR(usleep, usec); + int res = 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); + AfterSleep(thr, pc); + return res; +} + class AtExitContext { public: AtExitContext() @@ -269,7 +289,7 @@ static void finalize(void *arg) { { ScopedInRtl in_rtl; DestroyAndFree(atexit_ctx); - usleep(flags()->atexit_sleep_ms * 1000); + REAL(usleep)(flags()->atexit_sleep_ms * 1000); } int status = Finalize(cur_thread()); if (status) @@ -1572,6 +1592,9 @@ void InitializeInterceptors() { TSAN_INTERCEPT(raise); TSAN_INTERCEPT(kill); TSAN_INTERCEPT(pthread_kill); + TSAN_INTERCEPT(sleep); + TSAN_INTERCEPT(usleep); + TSAN_INTERCEPT(nanosleep); atexit_ctx = new(internal_alloc(MBlockAtExit, sizeof(AtExitContext))) AtExitContext(); diff --git a/lib/tsan/rtl/tsan_mman.cc b/lib/tsan/rtl/tsan_mman.cc index ba8972f4c..1e1022bcd 100644 --- a/lib/tsan/rtl/tsan_mman.cc +++ b/lib/tsan/rtl/tsan_mman.cc @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_placement_new.h" -#include "sanitizer_common/sanitizer_stackdepot.h" #include "tsan_mman.h" #include "tsan_rtl.h" #include "tsan_report.h" @@ -51,10 +50,7 @@ void *user_alloc(ThreadState *thr, uptr pc, uptr sz, uptr align) { MBlock *b = (MBlock*)allocator()->GetMetaData(p); b->size = sz; b->alloc_tid = thr->unique_id; - b->alloc_stack_id = 0; - if (thr->shadow_stack_pos) // May happen during bootstrap. - b->alloc_stack_id = StackDepotPut(thr->shadow_stack, - thr->shadow_stack_pos - thr->shadow_stack); + b->alloc_stack_id = CurrentStackId(thr, pc); if (CTX() && CTX()->initialized) { MemoryRangeImitateWrite(thr, pc, (uptr)p, sz); } diff --git a/lib/tsan/rtl/tsan_report.cc b/lib/tsan/rtl/tsan_report.cc index 6ce164bcf..c95ca8f20 100644 --- a/lib/tsan/rtl/tsan_report.cc +++ b/lib/tsan/rtl/tsan_report.cc @@ -21,7 +21,8 @@ ReportDesc::ReportDesc() , mops(MBlockReportMop) , locs(MBlockReportLoc) , mutexes(MBlockReportMutex) - , threads(MBlockReportThread) { + , threads(MBlockReportThread) + , sleep() { } ReportDesc::~ReportDesc() { @@ -110,6 +111,11 @@ static void PrintThread(const ReportThread *rt) { PrintStack(rt->stack); } +static void PrintSleep(const ReportStack *s) { + TsanPrintf(" As if synchronized via sleep:\n"); + PrintStack(s); +} + void PrintReport(const ReportDesc *rep) { TsanPrintf("==================\n"); PrintHeader(rep->typ); @@ -123,6 +129,9 @@ void PrintReport(const ReportDesc *rep) { for (uptr i = 0; i < rep->mops.Size(); i++) PrintMop(rep->mops[i], i == 0); + if (rep->sleep) + PrintSleep(rep->sleep); + for (uptr i = 0; i < rep->locs.Size(); i++) PrintLocation(rep->locs[i]); diff --git a/lib/tsan/rtl/tsan_report.h b/lib/tsan/rtl/tsan_report.h index d139296d5..a447d56b6 100644 --- a/lib/tsan/rtl/tsan_report.h +++ b/lib/tsan/rtl/tsan_report.h @@ -85,6 +85,7 @@ class ReportDesc { Vector<ReportLocation*> locs; Vector<ReportMutex*> mutexes; Vector<ReportThread*> threads; + ReportStack *sleep; ReportDesc(); ~ReportDesc(); diff --git a/lib/tsan/rtl/tsan_rtl.cc b/lib/tsan/rtl/tsan_rtl.cc index 9ca295da8..962c07a5b 100644 --- a/lib/tsan/rtl/tsan_rtl.cc +++ b/lib/tsan/rtl/tsan_rtl.cc @@ -15,6 +15,7 @@ #include "sanitizer_common/sanitizer_atomic.h" #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_libc.h" +#include "sanitizer_common/sanitizer_stackdepot.h" #include "sanitizer_common/sanitizer_placement_new.h" #include "tsan_defs.h" #include "tsan_platform.h" @@ -223,6 +224,20 @@ int Finalize(ThreadState *thr) { return failed ? flags()->exitcode : 0; } +u32 CurrentStackId(ThreadState *thr, uptr pc) { + if (thr->shadow_stack_pos == 0) // May happen during bootstrap. + return 0; + if (pc) { + thr->shadow_stack_pos[0] = pc; + thr->shadow_stack_pos++; + } + u32 id = StackDepotPut(thr->shadow_stack, + thr->shadow_stack_pos - thr->shadow_stack); + if (pc) + thr->shadow_stack_pos--; + return id; +} + void TraceSwitch(ThreadState *thr) { thr->nomalloc++; ScopedInRtl in_rtl; diff --git a/lib/tsan/rtl/tsan_rtl.h b/lib/tsan/rtl/tsan_rtl.h index bc621cd30..d79af1e5c 100644 --- a/lib/tsan/rtl/tsan_rtl.h +++ b/lib/tsan/rtl/tsan_rtl.h @@ -286,6 +286,11 @@ struct ThreadState { bool in_signal_handler; SignalContext *signal_ctx; +#ifndef TSAN_GO + u32 last_sleep_stack_id; + ThreadClock last_sleep_clock; +#endif + // Set in regions of runtime that must be signal-safe and fork-safe. // If set, malloc must not be called. int nomalloc; @@ -405,6 +410,7 @@ class ScopedReport { void AddThread(const ThreadContext *tctx); void AddMutex(const SyncVar *s); void AddLocation(uptr addr, uptr size); + void AddSleep(u32 stack_id); const ReportDesc *GetReport() const; @@ -446,6 +452,8 @@ bool IsExpectedReport(uptr addr, uptr size); # define DPrintf2(...) #endif +u32 CurrentStackId(ThreadState *thr, uptr pc); + void Initialize(ThreadState *thr); int Finalize(ThreadState *thr); @@ -489,6 +497,7 @@ void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr); void Acquire(ThreadState *thr, uptr pc, uptr addr); void Release(ThreadState *thr, uptr pc, uptr addr); void ReleaseStore(ThreadState *thr, uptr pc, uptr addr); +void AfterSleep(ThreadState *thr, uptr pc); // The hacky call uses custom calling convention and an assembly thunk. // It is considerably faster that a normal call for the caller diff --git a/lib/tsan/rtl/tsan_rtl_mutex.cc b/lib/tsan/rtl/tsan_rtl_mutex.cc index 167541f0f..a743924db 100644 --- a/lib/tsan/rtl/tsan_rtl_mutex.cc +++ b/lib/tsan/rtl/tsan_rtl_mutex.cc @@ -230,4 +230,21 @@ void ReleaseStore(ThreadState *thr, uptr pc, uptr addr) { s->mtx.Unlock(); } +#ifndef TSAN_GO +void AfterSleep(ThreadState *thr, uptr pc) { + Context *ctx = CTX(); + thr->last_sleep_stack_id = CurrentStackId(thr, pc); + 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->last_sleep_clock.set(i, tctx->thr->fast_state.epoch()); + else + thr->last_sleep_clock.set(i, tctx->epoch1); + } +} +#endif + } // namespace __tsan diff --git a/lib/tsan/rtl/tsan_rtl_report.cc b/lib/tsan/rtl/tsan_rtl_report.cc index a32d30a1b..8173700d0 100644 --- a/lib/tsan/rtl/tsan_rtl_report.cc +++ b/lib/tsan/rtl/tsan_rtl_report.cc @@ -230,6 +230,16 @@ void ScopedReport::AddLocation(uptr addr, uptr size) { } } +void ScopedReport::AddSleep(u32 stack_id) { + uptr ssz = 0; + const uptr *stack = StackDepotGet(stack_id, &ssz); + if (stack) { + StackTrace trace; + trace.Init(stack, ssz); + rep_->sleep = SymbolizeStack(trace); + } +} + const ReportDesc *ScopedReport::GetReport() const { return rep_; } @@ -411,6 +421,14 @@ void ReportRace(ThreadState *thr) { rep.AddLocation(addr_min, addr_max - addr_min); +#ifndef TSAN_GO + { // NOLINT + Shadow s(thr->racy_state[1]); + if (s.epoch() <= thr->last_sleep_clock.get(s.tid())) + rep.AddSleep(thr->last_sleep_stack_id); + } +#endif + if (!OutputReport(rep, rep.GetReport()->mops[0]->stack)) return; diff --git a/lib/tsan/rtl/tsan_stat.h b/lib/tsan/rtl/tsan_stat.h index 6bc5d230f..d99491f74 100644 --- a/lib/tsan/rtl/tsan_stat.h +++ b/lib/tsan/rtl/tsan_stat.h @@ -199,6 +199,9 @@ enum StatType { StatInt_raise, StatInt_kill, StatInt_pthread_kill, + StatInt_sleep, + StatInt_usleep, + StatInt_nanosleep, // Dynamic annotations. StatAnnotation, |