[llvm-commits] [compiler-rt] r170707 - in /compiler-rt/trunk/lib/tsan/rtl: tsan_interface_java.cc tsan_mutex.h tsan_rtl.h tsan_stat.h tsan_sync.cc tsan_sync.h

Kostya Serebryany kcc at google.com
Thu Dec 20 20:46:31 PST 2012


tests and/or comments are welcome here!


On Thu, Dec 20, 2012 at 9:29 PM, Dmitry Vyukov <dvyukov at google.com> wrote:

> Author: dvyukov
> Date: Thu Dec 20 11:29:34 2012
> New Revision: 170707
>
> URL: http://llvm.org/viewvc/llvm-project?rev=170707&view=rev
> Log:
> tsan: java interface implementation skeleton
>
> Modified:
>     compiler-rt/trunk/lib/tsan/rtl/tsan_interface_java.cc
>     compiler-rt/trunk/lib/tsan/rtl/tsan_mutex.h
>     compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h
>     compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h
>     compiler-rt/trunk/lib/tsan/rtl/tsan_sync.cc
>     compiler-rt/trunk/lib/tsan/rtl/tsan_sync.h
>
> Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_interface_java.cc
> URL:
> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_interface_java.cc?rev=170707&r1=170706&r2=170707&view=diff
>
> ==============================================================================
> --- compiler-rt/trunk/lib/tsan/rtl/tsan_interface_java.cc (original)
> +++ compiler-rt/trunk/lib/tsan/rtl/tsan_interface_java.cc Thu Dec 20
> 11:29:34 2012
> @@ -13,34 +13,261 @@
>
>  #include "tsan_interface_java.h"
>  #include "tsan_rtl.h"
> +#include "tsan_mutex.h"
> +#include "sanitizer_common/sanitizer_internal_defs.h"
> +#include "sanitizer_common/sanitizer_common.h"
> +#include "sanitizer_common/sanitizer_placement_new.h"
>
>  using namespace __tsan;  // NOLINT
>
> +namespace __tsan {
> +
> +const uptr kHeapShadow = 0x300000000000ull;
> +const uptr kHeapAlignment = 8;
> +
> +struct BlockDesc {
> +  bool begin;
> +  Mutex mtx;
> +  SyncVar *head;
> +
> +  BlockDesc()
> +      : mtx(MutexTypeJava, StatMtxJava)
> +      , head() {
> +    CHECK_EQ(begin, false);
> +    begin = true;
> +  }
> +
> +  explicit BlockDesc(BlockDesc *b)
> +      : mtx(MutexTypeJava, StatMtxJava)
> +      , head(b->head) {
> +    CHECK_EQ(begin, false);
> +    begin = true;
> +    b->head = 0;
> +  }
> +
> +  ~BlockDesc() {
> +    CHECK_EQ(begin, true);
> +    begin = false;
> +    ThreadState *thr = cur_thread();
> +    SyncVar *s = head;
> +    while (s) {
> +      SyncVar *s1 = s->next;
> +      StatInc(thr, StatSyncDestroyed);
> +      s->mtx.Lock();
> +      s->mtx.Unlock();
> +      thr->mset.Remove(s->GetId());
> +      DestroyAndFree(s);
> +      s = s1;
> +    }
> +  }
> +};
> +
> +struct JavaContext {
> +  Mutex mtx;
> +  const uptr heap_begin;
> +  const uptr heap_size;
> +  BlockDesc *heap_shadow;
> +
> +  JavaContext(jptr heap_begin, jptr heap_size)
> +      : mtx(MutexTypeJava, StatMtxJava)
> +      , heap_begin(heap_begin)
> +      , heap_size(heap_size) {
> +    uptr size = heap_size / kHeapAlignment * sizeof(BlockDesc);
> +    heap_shadow = (BlockDesc*)MmapFixedNoReserve(kHeapShadow, size);
> +    if ((uptr)heap_shadow != kHeapShadow) {
> +      Printf("ThreadSanitizer: failed to mmap Java heap shadow\n");
> +      Die();
> +    }
> +  }
> +};
> +
> +class ScopedJavaFunc {
> + public:
> +  ScopedJavaFunc(ThreadState *thr, uptr pc)
> +      : thr_(thr) {
> +    Initialize(thr_);
> +    FuncEntry(thr, pc);
> +    CHECK_EQ(thr_->in_rtl, 0);
> +    thr_->in_rtl++;
> +  }
> +
> +  ~ScopedJavaFunc() {
> +    thr_->in_rtl--;
> +    CHECK_EQ(thr_->in_rtl, 0);
> +    FuncExit(thr_);
> +    // FIXME(dvyukov): process pending signals.
> +  }
> +
> + private:
> +  ThreadState *thr_;
> +};
> +
> +static u64 jctx_buf[sizeof(JavaContext) / sizeof(u64) + 1];
> +static JavaContext *jctx;
> +
> +static BlockDesc *getblock(uptr addr) {
> +  uptr i = (addr - jctx->heap_begin) / kHeapAlignment;
> +  return &jctx->heap_shadow[i];
> +}
> +
> +static BlockDesc *getblockbegin(uptr addr) {
> +  for (BlockDesc *b = getblock(addr);; b--) {
> +    CHECK_GE(b, jctx->heap_shadow);
> +    if (b->begin)
> +      return b;
> +  }
> +  return 0;
> +}
> +
> +SyncVar* GetJavaSync(ThreadState *thr, uptr pc, uptr addr,
> +                     bool write_lock, bool create) {
> +  if (jctx == 0 || addr < jctx->heap_begin
> +      || addr >= jctx->heap_begin + jctx->heap_size)
> +    return 0;
> +  BlockDesc *b = getblockbegin(addr);
> +  Lock l(&b->mtx);
> +  SyncVar *s = b->head;
> +  for (; s; s = s->next) {
> +    if (s->addr == addr)
> +      break;
> +  }
> +  if (s == 0 && create) {
> +    s = CTX()->synctab.Create(thr, pc, addr);
> +    s->next = b->head;
> +    b->head = s;
> +  }
> +  if (s) {
> +    if (write_lock)
> +      s->mtx.Lock();
> +    else
> +      s->mtx.ReadLock();
> +  }
> +  return s;
> +}
> +
> +SyncVar* GetAndRemoveJavaSync(ThreadState *thr, uptr pc, uptr addr) {
> +  // We do not destroy Java mutexes other than in __tsan_java_free().
> +  return 0;
> +}
> +
> +}  // namespace __tsan {
> +
> +#define SCOPED_JAVA_FUNC(func) \
> +  ThreadState *thr = cur_thread(); \
> +  const uptr caller_pc = GET_CALLER_PC(); \
> +  const uptr pc = (uptr)&func; \
> +  (void)pc; \
> +  ScopedJavaFunc scoped(thr, caller_pc); \
> +/**/
> +
>  void __tsan_java_init(jptr heap_begin, jptr heap_size) {
> +  SCOPED_JAVA_FUNC(__tsan_java_init);
> +  DPrintf("#%d: java_init(%p, %p)\n", thr->tid, heap_begin, heap_size);
> +  CHECK_EQ(jctx, 0);
> +  CHECK_GT(heap_begin, 0);
> +  CHECK_GT(heap_size, 0);
> +  CHECK_LT(heap_begin, heap_begin + heap_size);
> +  jctx = new(jctx_buf) JavaContext(heap_begin, heap_size);
>  }
>
>  int  __tsan_java_fini() {
> -  return 0;
> +  SCOPED_JAVA_FUNC(__tsan_java_fini);
> +  DPrintf("#%d: java_fini()\n", thr->tid);
> +  CHECK_NE(jctx, 0);
> +  // FIXME(dvyukov): this does not call atexit() callbacks.
> +  int status = Finalize(thr);
> +  DPrintf("#%d: java_fini() = %d\n", thr->tid, status);
> +  return status;
>  }
>
>  void __tsan_java_alloc(jptr ptr, jptr size) {
> +  SCOPED_JAVA_FUNC(__tsan_java_alloc);
> +  DPrintf("#%d: java_alloc(%p, %p)\n", thr->tid, ptr, size);
> +  CHECK_NE(jctx, 0);
> +  CHECK_NE(size, 0);
> +  CHECK_GE(ptr, jctx->heap_begin);
> +  CHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
> +
> +  BlockDesc *b = getblock(ptr);
> +  new(b) BlockDesc();
>  }
>
>  void __tsan_java_free(jptr ptr, jptr size) {
> +  SCOPED_JAVA_FUNC(__tsan_java_free);
> +  DPrintf("#%d: java_free(%p, %p)\n", thr->tid, ptr, size);
> +  CHECK_NE(jctx, 0);
> +  CHECK_NE(size, 0);
> +  CHECK_GE(ptr, jctx->heap_begin);
> +  CHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
> +
> +  BlockDesc *beg = getblock(ptr);
> +  BlockDesc *end = getblock(ptr + size);
> +  for (BlockDesc *b = beg; b != end; b++) {
> +    if (b->begin)
> +      b->~BlockDesc();
> +  }
>  }
>
>  void __tsan_java_move(jptr src, jptr dst, jptr size) {
> +  SCOPED_JAVA_FUNC(__tsan_java_move);
> +  DPrintf("#%d: java_move(%p, %p, %p)\n", thr->tid, src, dst, size);
> +  CHECK_NE(jctx, 0);
> +  CHECK_NE(size, 0);
> +  CHECK_GE(src, jctx->heap_begin);
> +  CHECK_LE(src + size, jctx->heap_begin + jctx->heap_size);
> +  CHECK_GE(dst, jctx->heap_begin);
> +  CHECK_LE(dst + size, jctx->heap_begin + jctx->heap_size);
> +  CHECK(dst >= src + size || src >= dst + size);
> +
> +  // Assuming it's not running concurrently with threads that do
> +  // memory accesses and mutex operations (stop-the-world phase).
> +  BlockDesc *srcbeg = getblock(src);
> +  BlockDesc *dstbeg = getblock(dst);
> +  BlockDesc *srcend = getblock(src + size);
> +  for (BlockDesc *s = srcbeg, *d = dstbeg; s != srcend; s++, d++) {
> +    if (s->begin) {
> +      new(d) BlockDesc(s);
> +      s->~BlockDesc();
> +    }
> +  }
>  }
>
>  void __tsan_java_mutex_lock(jptr addr) {
> +  SCOPED_JAVA_FUNC(__tsan_java_mutex_lock);
> +  DPrintf("#%d: java_mutex_lock(%p)\n", thr->tid, addr);
> +  CHECK_NE(jctx, 0);
> +  CHECK_GE(addr, jctx->heap_begin);
> +  CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
> +
> +  MutexLock(thr, pc, addr);
>  }
>
>  void __tsan_java_mutex_unlock(jptr addr) {
> +  SCOPED_JAVA_FUNC(__tsan_java_mutex_unlock);
> +  DPrintf("#%d: java_mutex_unlock(%p)\n", thr->tid, addr);
> +  CHECK_NE(jctx, 0);
> +  CHECK_GE(addr, jctx->heap_begin);
> +  CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
> +
> +  MutexUnlock(thr, pc, addr);
>  }
>
>  void __tsan_java_mutex_read_lock(jptr addr) {
> +  SCOPED_JAVA_FUNC(__tsan_java_mutex_read_lock);
> +  DPrintf("#%d: java_mutex_read_lock(%p)\n", thr->tid, addr);
> +  CHECK_NE(jctx, 0);
> +  CHECK_GE(addr, jctx->heap_begin);
> +  CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
> +
> +  MutexReadLock(thr, pc, addr);
>  }
>
>  void __tsan_java_mutex_read_unlock(jptr addr) {
> -}
> +  SCOPED_JAVA_FUNC(__tsan_java_mutex_read_unlock);
> +  DPrintf("#%d: java_mutex_read_unlock(%p)\n", thr->tid, addr);
> +  CHECK_NE(jctx, 0);
> +  CHECK_GE(addr, jctx->heap_begin);
> +  CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
>
> +  MutexReadUnlock(thr, pc, addr);
> +}
>
> Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_mutex.h
> URL:
> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_mutex.h?rev=170707&r1=170706&r2=170707&view=diff
>
> ==============================================================================
> --- compiler-rt/trunk/lib/tsan/rtl/tsan_mutex.h (original)
> +++ compiler-rt/trunk/lib/tsan/rtl/tsan_mutex.h Thu Dec 20 11:29:34 2012
> @@ -30,6 +30,7 @@
>    MutexTypeAnnotations,
>    MutexTypeAtExit,
>    MutexTypeMBlock,
> +  MutexTypeJava,
>
>    // This must be the last.
>    MutexTypeCount
>
> 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=170707&r1=170706&r2=170707&view=diff
>
> ==============================================================================
> --- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h (original)
> +++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h Thu Dec 20 11:29:34 2012
> @@ -515,6 +515,10 @@
>  void Initialize(ThreadState *thr);
>  int Finalize(ThreadState *thr);
>
> +SyncVar* GetJavaSync(ThreadState *thr, uptr pc, uptr addr,
> +                     bool write_lock, bool create);
> +SyncVar* GetAndRemoveJavaSync(ThreadState *thr, uptr pc, uptr addr);
> +
>  void MemoryAccess(ThreadState *thr, uptr pc, uptr addr,
>      int kAccessSizeLog, bool kAccessIsWrite);
>  void MemoryAccessImpl(ThreadState *thr, uptr addr,
>
> Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h
> URL:
> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h?rev=170707&r1=170706&r2=170707&view=diff
>
> ==============================================================================
> --- compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h (original)
> +++ compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h Thu Dec 20 11:29:34 2012
> @@ -281,6 +281,7 @@
>    StatMtxAnnotations,
>    StatMtxAtExit,
>    StatMtxMBlock,
> +  StatMtxJava,
>
>    // This must be the last.
>    StatCnt
>
> Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_sync.cc
> URL:
> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_sync.cc?rev=170707&r1=170706&r2=170707&view=diff
>
> ==============================================================================
> --- compiler-rt/trunk/lib/tsan/rtl/tsan_sync.cc (original)
> +++ compiler-rt/trunk/lib/tsan/rtl/tsan_sync.cc Thu Dec 20 11:29:34 2012
> @@ -57,9 +57,26 @@
>    return GetAndLock(0, 0, addr, write_lock, false);
>  }
>
> +SyncVar* SyncTab::Create(ThreadState *thr, uptr pc, uptr addr) {
> +  StatInc(thr, StatSyncCreated);
> +  void *mem = internal_alloc(MBlockSync, sizeof(SyncVar));
> +  const u64 uid = atomic_fetch_add(&uid_gen_, 1, memory_order_relaxed);
> +  SyncVar *res = new(mem) SyncVar(addr, uid);
> +#ifndef TSAN_GO
> +  res->creation_stack.ObtainCurrent(thr, pc);
> +#endif
> +  return res;
> +}
> +
>  SyncVar* SyncTab::GetAndLock(ThreadState *thr, uptr pc,
>                               uptr addr, bool write_lock, bool create) {
>  #ifndef TSAN_GO
> +  {  // NOLINT
> +    SyncVar *res = GetJavaSync(thr, pc, addr, write_lock, create);
> +    if (res)
> +      return res;
> +  }
> +
>    // Here we ask only PrimaryAllocator, because
>    // SecondaryAllocator::PointerIsMine() is slow and we have fallback on
>    // the hashmap anyway.
> @@ -74,11 +91,7 @@
>      if (res == 0) {
>        if (!create)
>          return 0;
> -      StatInc(thr, StatSyncCreated);
> -      void *mem = internal_alloc(MBlockSync, sizeof(SyncVar));
> -      const u64 uid = atomic_fetch_add(&uid_gen_, 1,
> memory_order_relaxed);
> -      res = new(mem) SyncVar(addr, uid);
> -      res->creation_stack.ObtainCurrent(thr, pc);
> +      res = Create(thr, pc, addr);
>        res->next = b->head;
>        b->head = res;
>      }
> @@ -113,13 +126,7 @@
>          break;
>      }
>      if (res == 0) {
> -      StatInc(thr, StatSyncCreated);
> -      void *mem = internal_alloc(MBlockSync, sizeof(SyncVar));
> -      const u64 uid = atomic_fetch_add(&uid_gen_, 1,
> memory_order_relaxed);
> -      res = new(mem) SyncVar(addr, uid);
> -#ifndef TSAN_GO
> -      res->creation_stack.ObtainCurrent(thr, pc);
> -#endif
> +      res = Create(thr, pc, addr);
>        res->next = p->val;
>        p->val = res;
>      }
> @@ -133,6 +140,11 @@
>
>  SyncVar* SyncTab::GetAndRemove(ThreadState *thr, uptr pc, uptr addr) {
>  #ifndef TSAN_GO
> +  {  // NOLINT
> +    SyncVar *res = GetAndRemoveJavaSync(thr, pc, addr);
> +    if (res)
> +      return res;
> +  }
>    if (PrimaryAllocator::PointerIsMine((void*)addr)) {
>      MBlock *b = user_mblock(thr, (void*)addr);
>      SyncVar *res = 0;
>
> Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_sync.h
> URL:
> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_sync.h?rev=170707&r1=170706&r2=170707&view=diff
>
> ==============================================================================
> --- compiler-rt/trunk/lib/tsan/rtl/tsan_sync.h (original)
> +++ compiler-rt/trunk/lib/tsan/rtl/tsan_sync.h Thu Dec 20 11:29:34 2012
> @@ -96,6 +96,8 @@
>    // If the SyncVar does not exist, returns 0.
>    SyncVar* GetAndRemove(ThreadState *thr, uptr pc, uptr addr);
>
> +  SyncVar* Create(ThreadState *thr, uptr pc, uptr addr);
> +
>    uptr GetMemoryConsumption(uptr *nsync);
>
>   private:
>
>
> _______________________________________________
> 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/20121221/0049d00f/attachment.html>


More information about the llvm-commits mailing list