[llvm-commits] [compiler-rt] r168786 - in /compiler-rt/trunk/lib: sanitizer_common/sanitizer_posix.cc tsan/rtl/tsan_flags.cc tsan/rtl/tsan_flags.h tsan/rtl/tsan_platform_linux.cc tsan/rtl/tsan_rtl.cc tsan/rtl/tsan_rtl.h tsan/rtl/tsan_rtl_report.cc tsan/rtl/tsan_rtl_thread.cc tsan/rtl/tsan_trace.h tsan/tests/unit/tsan_shadow_test.cc

Kostya Serebryany kcc at google.com
Wed Nov 28 04:38:54 PST 2012


Excellent.
Minor comment below.

On Wed, Nov 28, 2012 at 4:19 PM, Dmitry Vyukov <dvyukov at google.com> wrote:

> Author: dvyukov
> Date: Wed Nov 28 06:19:50 2012
> New Revision: 168786
>
> URL: http://llvm.org/viewvc/llvm-project?rev=168786&view=rev
> Log:
> tsan: dynamic history size
> introduces history_size parameter that can be used to control trace size
> at startup
>
> Modified:
>     compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix.cc
>     compiler-rt/trunk/lib/tsan/rtl/tsan_flags.cc
>     compiler-rt/trunk/lib/tsan/rtl/tsan_flags.h
>     compiler-rt/trunk/lib/tsan/rtl/tsan_platform_linux.cc
>     compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.cc
>     compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h
>     compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc
>     compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc
>     compiler-rt/trunk/lib/tsan/rtl/tsan_trace.h
>     compiler-rt/trunk/lib/tsan/tests/unit/tsan_shadow_test.cc
>
> Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix.cc
> URL:
> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix.cc?rev=168786&r1=168785&r2=168786&view=diff
>
> ==============================================================================
> --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix.cc (original)
> +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix.cc Wed Nov 28
> 06:19:50 2012
> @@ -169,7 +169,10 @@
>    struct rlimit rlim;
>    rlim.rlim_cur = limit;
>    rlim.rlim_max = limit;
> -  CHECK_EQ(0, setrlimit(RLIMIT_STACK, &rlim));
> +  if (setrlimit(RLIMIT_STACK, &rlim)) {
> +    Report("setrlimit() failed %d\n", errno);
> +    Die();
> +  }
>    CHECK(!StackSizeIsUnlimited());
>  }
>
>
> Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_flags.cc
> URL:
> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_flags.cc?rev=168786&r1=168785&r2=168786&view=diff
>
> ==============================================================================
> --- compiler-rt/trunk/lib/tsan/rtl/tsan_flags.cc (original)
> +++ compiler-rt/trunk/lib/tsan/rtl/tsan_flags.cc Wed Nov 28 06:19:50 2012
> @@ -56,6 +56,11 @@
>    f->stop_on_start = false;
>    f->running_on_valgrind = false;
>    f->external_symbolizer_path = "";
> +  f->history_size = 2;
> +
> +#ifdef TSAN_GO
>

For such checks I'd prefer to have if (TSAN_GO) instead of #ifdef TSAN_GO.
(here and in other places).



> +  f->history_size = 1;  // There are a lot of goroutines.
> +#endif
>
>    // Let a frontend override.
>    OverrideFlags(f);
> @@ -79,12 +84,19 @@
>    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");
> +  ParseFlag(env, &f->history_size, "history_size");
>
>    if (!f->report_bugs) {
>      f->report_thread_leaks = false;
>      f->report_destroy_locked = false;
>      f->report_signal_unsafe = false;
>    }
> +
> +  if (f->history_size < 0 || f->history_size > 7) {
> +    Printf("ThreadSanitizer: incorrect value for history_size"
> +           " (must be [0..7])\n");
> +    Die();
> +  }
>  }
>
>  }  // namespace __tsan
>
> Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_flags.h
> URL:
> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_flags.h?rev=168786&r1=168785&r2=168786&view=diff
>
> ==============================================================================
> --- compiler-rt/trunk/lib/tsan/rtl/tsan_flags.h (original)
> +++ compiler-rt/trunk/lib/tsan/rtl/tsan_flags.h Wed Nov 28 06:19:50 2012
> @@ -66,6 +66,12 @@
>    bool running_on_valgrind;
>    // Path to external symbolizer.
>    const char *external_symbolizer_path;
> +  // Per-thread history size, controls how many previous memory accesses
> +  // is remembered per thread.  Possible values are [0..7].
>
are remembered


> +  // history_size=0 amounts to 32K memory accesses.  Each next value
> doubles
> +  // the amount of memory accesses, up to history_size=7 that amounts to
> +  // 4M memory accesses.  The default value is 2 (128K memory accesses).
> +  int history_size;
>  };
>
>  Flags *flags();
>
> Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_platform_linux.cc
> URL:
> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_platform_linux.cc?rev=168786&r1=168785&r2=168786&view=diff
>
> ==============================================================================
> --- compiler-rt/trunk/lib/tsan/rtl/tsan_platform_linux.cc (original)
> +++ compiler-rt/trunk/lib/tsan/rtl/tsan_platform_linux.cc Wed Nov 28
> 06:19:50 2012
> @@ -202,28 +202,50 @@
>  }
>  #endif  // #ifndef TSAN_GO
>
> +static rlim_t getlim(int res) {
> +  rlimit rlim;
> +  CHECK_EQ(0, getrlimit(res, &rlim));
> +  return rlim.rlim_cur;
> +}
> +
> +static void setlim(int res, rlim_t lim) {
> +  // The following magic is to prevent clang from replacing it with
> memset.
> +  volatile rlimit rlim;
> +  rlim.rlim_cur = lim;
> +  rlim.rlim_max = lim;
> +  setrlimit(res, (rlimit*)&rlim);
> +}
> +
>  const char *InitializePlatform() {
>    void *p = 0;
>    if (sizeof(p) == 8) {
>      // Disable core dumps, dumping of 16TB usually takes a bit long.
> -    // The following magic is to prevent clang from replacing it with
> memset.
> -    volatile rlimit lim;
> -    lim.rlim_cur = 0;
> -    lim.rlim_max = 0;
> -    setrlimit(RLIMIT_CORE, (rlimit*)&lim);
> +    setlim(RLIMIT_CORE, 0);
>    }
> +  bool reexec = false;
>    // TSan doesn't play well with unlimited stack size (as stack
>    // overlaps with shadow memory). If we detect unlimited stack size,
>    // we re-exec the program with limited stack size as a best effort.
> -  if (StackSizeIsUnlimited()) {
> -    const uptr kMaxStackSize = 32 * 1024 * 1024;  // 32 Mb
> +  if (getlim(RLIMIT_STACK) == (rlim_t)-1) {
> +    const uptr kMaxStackSize = 32 * 1024 * 1024;
>      Report("WARNING: Program is run with unlimited stack size, which "
>             "wouldn't work with ThreadSanitizer.\n");
>      Report("Re-execing with stack size limited to %zd bytes.\n",
> kMaxStackSize);
>      SetStackSizeLimitInBytes(kMaxStackSize);
> -    ReExec();
> +    reexec = true;
>    }
>
> +  if (getlim(RLIMIT_AS) != (rlim_t)-1) {
> +    Report("WARNING: Program is run with limited virtual address space,
> which "
> +           "wouldn't work with ThreadSanitizer.\n");
> +    Report("Re-execing with unlimited virtual address space.\n");
> +    setlim(RLIMIT_AS, -1);
> +    reexec = true;
> +  }
> +
> +  if (reexec)
> +    ReExec();
> +
>  #ifndef TSAN_GO
>    CheckPIE();
>    g_tls_size = (uptr)InitTlsSize();
>
> Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.cc
> URL:
> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.cc?rev=168786&r1=168785&r2=168786&view=diff
>
> ==============================================================================
> --- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.cc (original)
> +++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.cc Wed Nov 28 06:19:50 2012
> @@ -290,11 +290,14 @@
>
>  uptr TraceTopPC(ThreadState *thr) {
>    Event *events = (Event*)GetThreadTrace(thr->tid);
> -  uptr pc = events[thr->fast_state.epoch() % kTraceSize]
> -      & ((1ull << 61) - 1);
> +  uptr pc = events[thr->fast_state.GetTracePos()];
>    return pc;
>  }
>
> +uptr TraceSize() {
> +  return (uptr)(1ull << (kTracePartSizeBits + flags()->history_size + 1));
> +}
> +
>  #ifndef TSAN_GO
>  extern "C" void __tsan_trace_switch() {
>    TraceSwitch(cur_thread());
>
> Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h
> URL:
> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h?rev=168786&r1=168785&r2=168786&view=diff
>
> ==============================================================================
> --- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h (original)
> +++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h Wed Nov 28 06:19:50 2012
> @@ -74,6 +74,7 @@
>  //   tid             : kTidBits
>  //   epoch           : kClkBits
>  //   unused          : -
> +//   history_size    : 3
>  class FastState {
>   public:
>    FastState(u64 tid, u64 epoch) {
> @@ -113,6 +114,27 @@
>    void ClearIgnoreBit() { x_ &= ~kIgnoreBit; }
>    bool GetIgnoreBit() const { return (s64)x_ < 0; }
>
> +  void SetHistorySize(int hs) {
> +    CHECK_GE(hs, 0);
> +    CHECK_LE(hs, 7);
> +    x_ = (x_ & ~7) | hs;
> +  }
> +
> +  int GetHistorySize() const {
> +    return (int)(x_ & 7);
> +  }
> +
> +  void ClearHistorySize() {
> +    x_ &= ~7;
> +  }
> +
> +  u64 GetTracePos() const {
> +    const int hs = GetHistorySize();
> +    // When hs == 0, the trace consists of 2 parts.
>
+    const u64 mask = (1ull << (kTracePartSizeBits + hs + 1)) - 1;
> +    return epoch() & mask;
> +  }
> +
>   private:
>    friend class Shadow;
>    static const int kTidShift = 64 - kTidBits - 1;
> @@ -131,9 +153,14 @@
>  //   addr0           : 3
>  class Shadow : public FastState {
>   public:
> -  explicit Shadow(u64 x) : FastState(x) { }
> +  explicit Shadow(u64 x)
> +      : FastState(x) {
> +  }
>
> -  explicit Shadow(const FastState &s) : FastState(s.x_) { }
> +  explicit Shadow(const FastState &s)
> +      : FastState(s.x_) {
> +    ClearHistorySize();
> +  }
>
>    void SetAddr0AndSizeLog(u64 addr0, unsigned kAccessSizeLog) {
>      DCHECK_EQ(x_ & 31, 0);
> @@ -535,12 +562,13 @@
>
>  void TraceSwitch(ThreadState *thr);
>  uptr TraceTopPC(ThreadState *thr);
> +uptr TraceSize();
>
>  extern "C" void __tsan_trace_switch();
>  void ALWAYS_INLINE INLINE TraceAddEvent(ThreadState *thr, FastState fs,
>                                          EventType typ, uptr addr) {
>    StatInc(thr, StatEvents);
> -  u64 epoch = fs.epoch();
> +  u64 epoch = fs.GetTracePos();
>

Should this be named epoch then?


>    if (UNLIKELY((epoch % kTracePartSize) == 0)) {
>  #ifndef TSAN_GO
>      HACKY_CALL(__tsan_trace_switch);
> @@ -549,7 +577,7 @@
>  #endif
>    }
>    Event *trace = (Event*)GetThreadTrace(fs.tid());
> -  Event *evp = &trace[epoch % kTraceSize];
> +  Event *evp = &trace[epoch];
>    Event ev = (u64)addr | ((u64)typ << 61);
>    *evp = ev;
>  }
>
> Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc
> URL:
> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc?rev=168786&r1=168785&r2=168786&view=diff
>
> ==============================================================================
> --- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc (original)
> +++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc Wed Nov 28 06:19:50
> 2012
> @@ -263,11 +263,11 @@
>      return;
>    }
>    Lock l(&trace->mtx);
> -  const int partidx = (epoch / (kTraceSize / kTraceParts)) % kTraceParts;
> +  const int partidx = (epoch / (TraceSize() / kTraceParts)) % kTraceParts;
>    TraceHeader* hdr = &trace->headers[partidx];
>    if (epoch < hdr->epoch0)
>      return;
> -  const u64 eend = epoch % kTraceSize;
> +  const u64 eend = epoch % TraceSize();
>    const u64 ebegin = eend / kTracePartSize * kTracePartSize;
>    DPrintf("#%d: RestoreStack epoch=%zu ebegin=%zu eend=%zu partidx=%d\n",
>            tid, (uptr)epoch, (uptr)ebegin, (uptr)eend, partidx);
>
> Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc
> URL:
> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc?rev=168786&r1=168785&r2=168786&view=diff
>
> ==============================================================================
> --- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc (original)
> +++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc Wed Nov 28 06:19:50
> 2012
> @@ -123,7 +123,7 @@
>      void *mem = internal_alloc(MBlockThreadContex, sizeof(ThreadContext));
>      tctx = new(mem) ThreadContext(tid);
>      ctx->threads[tid] = tctx;
> -    MapThreadTrace(GetThreadTrace(tid), kTraceSize * sizeof(Event));
> +    MapThreadTrace(GetThreadTrace(tid), TraceSize() * sizeof(Event));
>    }
>    CHECK_NE(tctx, 0);
>    CHECK_GE(tid, 0);
> @@ -149,7 +149,6 @@
>      thr->fast_synch_epoch = thr->fast_state.epoch();
>      thr->clock.release(&tctx->sync);
>      StatInc(thr, StatSyncRelease);
> -
>      tctx->creation_stack.ObtainCurrent(thr, pc);
>    }
>    return tid;
> @@ -205,6 +204,7 @@
>    thr->fast_synch_epoch = tctx->epoch0;
>    thr->clock.set(tid, tctx->epoch0);
>    thr->clock.acquire(&tctx->sync);
> +  thr->fast_state.SetHistorySize(flags()->history_size);
>    StatInc(thr, StatSyncAcquire);
>    DPrintf("#%d: ThreadStart epoch=%zu stk_addr=%zx stk_size=%zx "
>            "tls_addr=%zx tls_size=%zx\n",
>
> Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_trace.h
> URL:
> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_trace.h?rev=168786&r1=168785&r2=168786&view=diff
>
> ==============================================================================
> --- compiler-rt/trunk/lib/tsan/rtl/tsan_trace.h (original)
> +++ compiler-rt/trunk/lib/tsan/rtl/tsan_trace.h Wed Nov 28 06:19:50 2012
> @@ -19,12 +19,9 @@
>
>  namespace __tsan {
>
> -#ifndef TSAN_HISTORY_SIZE  // in kibitraces
> -#define TSAN_HISTORY_SIZE 128
> -#endif
> -
> -const int kTracePartSize = 16 * 1024;
> -const int kTraceParts = TSAN_HISTORY_SIZE * 1024 / kTracePartSize;
> +const int kTracePartSizeBits = 14;
> +const int kTracePartSize = 1 << kTracePartSizeBits;
> +const int kTraceParts = 4 * 1024 * 1024 / kTracePartSize;
>  const int kTraceSize = kTracePartSize * kTraceParts;
>
>  // Must fit into 3 bits.
>
> Modified: compiler-rt/trunk/lib/tsan/tests/unit/tsan_shadow_test.cc
> URL:
> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/tests/unit/tsan_shadow_test.cc?rev=168786&r1=168785&r2=168786&view=diff
>
> ==============================================================================
> --- compiler-rt/trunk/lib/tsan/tests/unit/tsan_shadow_test.cc (original)
> +++ compiler-rt/trunk/lib/tsan/tests/unit/tsan_shadow_test.cc Wed Nov 28
> 06:19:50 2012
> @@ -22,6 +22,7 @@
>    EXPECT_EQ(s.epoch(), (u64)22);
>    EXPECT_EQ(s.GetIgnoreBit(), false);
>    EXPECT_EQ(s.GetFreedAndReset(), false);
> +  EXPECT_EQ(s.GetHistorySize(), 0);
>    EXPECT_EQ(s.addr0(), (u64)0);
>    EXPECT_EQ(s.size(), (u64)1);
>    EXPECT_EQ(s.is_write(), false);
> @@ -35,6 +36,14 @@
>    EXPECT_EQ(s.GetIgnoreBit(), true);
>    s.ClearIgnoreBit();
>    EXPECT_EQ(s.GetIgnoreBit(), false);
> +
> +  for (int i = 0; i < 8; i++) {
> +    s.SetHistorySize(i);
> +    EXPECT_EQ(s.GetHistorySize(), i);
> +  }
> +  s.SetHistorySize(2);
> +  s.ClearHistorySize();
> +  EXPECT_EQ(s.GetHistorySize(), 0);
>  }
>
>  TEST(Shadow, Mapping) {
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20121128/0d4f826e/attachment.html>


More information about the llvm-commits mailing list