<div style="font-family: arial, helvetica, sans-serif; font-size: 10pt"><div dir="ltr"><div class="gmail_default" style>tests and/or comments are welcome here! </div></div><div class="gmail_extra"><br><br><div class="gmail_quote">
On Thu, Dec 20, 2012 at 9:29 PM, Dmitry Vyukov <span dir="ltr"><<a href="mailto:dvyukov@google.com" target="_blank">dvyukov@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Author: dvyukov<br>
Date: Thu Dec 20 11:29:34 2012<br>
New Revision: 170707<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=170707&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=170707&view=rev</a><br>
Log:<br>
tsan: java interface implementation skeleton<br>
<br>
Modified:<br>
    compiler-rt/trunk/lib/tsan/rtl/tsan_interface_java.cc<br>
    compiler-rt/trunk/lib/tsan/rtl/tsan_mutex.h<br>
    compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h<br>
    compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h<br>
    compiler-rt/trunk/lib/tsan/rtl/tsan_sync.cc<br>
    compiler-rt/trunk/lib/tsan/rtl/tsan_sync.h<br>
<br>
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_interface_java.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_interface_java.cc?rev=170707&r1=170706&r2=170707&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_interface_java.cc?rev=170707&r1=170706&r2=170707&view=diff</a><br>

==============================================================================<br>
--- compiler-rt/trunk/lib/tsan/rtl/tsan_interface_java.cc (original)<br>
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_interface_java.cc Thu Dec 20 11:29:34 2012<br>
@@ -13,34 +13,261 @@<br>
<br>
 #include "tsan_interface_java.h"<br>
 #include "tsan_rtl.h"<br>
+#include "tsan_mutex.h"<br>
+#include "sanitizer_common/sanitizer_internal_defs.h"<br>
+#include "sanitizer_common/sanitizer_common.h"<br>
+#include "sanitizer_common/sanitizer_placement_new.h"<br>
<br>
 using namespace __tsan;  // NOLINT<br>
<br>
+namespace __tsan {<br>
+<br>
+const uptr kHeapShadow = 0x300000000000ull;<br>
+const uptr kHeapAlignment = 8;<br>
+<br>
+struct BlockDesc {<br>
+  bool begin;<br>
+  Mutex mtx;<br>
+  SyncVar *head;<br>
+<br>
+  BlockDesc()<br>
+      : mtx(MutexTypeJava, StatMtxJava)<br>
+      , head() {<br>
+    CHECK_EQ(begin, false);<br>
+    begin = true;<br>
+  }<br>
+<br>
+  explicit BlockDesc(BlockDesc *b)<br>
+      : mtx(MutexTypeJava, StatMtxJava)<br>
+      , head(b->head) {<br>
+    CHECK_EQ(begin, false);<br>
+    begin = true;<br>
+    b->head = 0;<br>
+  }<br>
+<br>
+  ~BlockDesc() {<br>
+    CHECK_EQ(begin, true);<br>
+    begin = false;<br>
+    ThreadState *thr = cur_thread();<br>
+    SyncVar *s = head;<br>
+    while (s) {<br>
+      SyncVar *s1 = s->next;<br>
+      StatInc(thr, StatSyncDestroyed);<br>
+      s->mtx.Lock();<br>
+      s->mtx.Unlock();<br>
+      thr->mset.Remove(s->GetId());<br>
+      DestroyAndFree(s);<br>
+      s = s1;<br>
+    }<br>
+  }<br>
+};<br>
+<br>
+struct JavaContext {<br>
+  Mutex mtx;<br>
+  const uptr heap_begin;<br>
+  const uptr heap_size;<br>
+  BlockDesc *heap_shadow;<br>
+<br>
+  JavaContext(jptr heap_begin, jptr heap_size)<br>
+      : mtx(MutexTypeJava, StatMtxJava)<br>
+      , heap_begin(heap_begin)<br>
+      , heap_size(heap_size) {<br>
+    uptr size = heap_size / kHeapAlignment * sizeof(BlockDesc);<br>
+    heap_shadow = (BlockDesc*)MmapFixedNoReserve(kHeapShadow, size);<br>
+    if ((uptr)heap_shadow != kHeapShadow) {<br>
+      Printf("ThreadSanitizer: failed to mmap Java heap shadow\n");<br>
+      Die();<br>
+    }<br>
+  }<br>
+};<br>
+<br>
+class ScopedJavaFunc {<br>
+ public:<br>
+  ScopedJavaFunc(ThreadState *thr, uptr pc)<br>
+      : thr_(thr) {<br>
+    Initialize(thr_);<br>
+    FuncEntry(thr, pc);<br>
+    CHECK_EQ(thr_->in_rtl, 0);<br>
+    thr_->in_rtl++;<br>
+  }<br>
+<br>
+  ~ScopedJavaFunc() {<br>
+    thr_->in_rtl--;<br>
+    CHECK_EQ(thr_->in_rtl, 0);<br>
+    FuncExit(thr_);<br>
+    // FIXME(dvyukov): process pending signals.<br>
+  }<br>
+<br>
+ private:<br>
+  ThreadState *thr_;<br>
+};<br>
+<br>
+static u64 jctx_buf[sizeof(JavaContext) / sizeof(u64) + 1];<br>
+static JavaContext *jctx;<br>
+<br>
+static BlockDesc *getblock(uptr addr) {<br>
+  uptr i = (addr - jctx->heap_begin) / kHeapAlignment;<br>
+  return &jctx->heap_shadow[i];<br>
+}<br>
+<br>
+static BlockDesc *getblockbegin(uptr addr) {<br>
+  for (BlockDesc *b = getblock(addr);; b--) {<br>
+    CHECK_GE(b, jctx->heap_shadow);<br>
+    if (b->begin)<br>
+      return b;<br>
+  }<br>
+  return 0;<br>
+}<br>
+<br>
+SyncVar* GetJavaSync(ThreadState *thr, uptr pc, uptr addr,<br>
+                     bool write_lock, bool create) {<br>
+  if (jctx == 0 || addr < jctx->heap_begin<br>
+      || addr >= jctx->heap_begin + jctx->heap_size)<br>
+    return 0;<br>
+  BlockDesc *b = getblockbegin(addr);<br>
+  Lock l(&b->mtx);<br>
+  SyncVar *s = b->head;<br>
+  for (; s; s = s->next) {<br>
+    if (s->addr == addr)<br>
+      break;<br>
+  }<br>
+  if (s == 0 && create) {<br>
+    s = CTX()->synctab.Create(thr, pc, addr);<br>
+    s->next = b->head;<br>
+    b->head = s;<br>
+  }<br>
+  if (s) {<br>
+    if (write_lock)<br>
+      s->mtx.Lock();<br>
+    else<br>
+      s->mtx.ReadLock();<br>
+  }<br>
+  return s;<br>
+}<br>
+<br>
+SyncVar* GetAndRemoveJavaSync(ThreadState *thr, uptr pc, uptr addr) {<br>
+  // We do not destroy Java mutexes other than in __tsan_java_free().<br>
+  return 0;<br>
+}<br>
+<br>
+}  // namespace __tsan {<br>
+<br>
+#define SCOPED_JAVA_FUNC(func) \<br>
+  ThreadState *thr = cur_thread(); \<br>
+  const uptr caller_pc = GET_CALLER_PC(); \<br>
+  const uptr pc = (uptr)&func; \<br>
+  (void)pc; \<br>
+  ScopedJavaFunc scoped(thr, caller_pc); \<br>
+/**/<br>
+<br>
 void __tsan_java_init(jptr heap_begin, jptr heap_size) {<br>
+  SCOPED_JAVA_FUNC(__tsan_java_init);<br>
+  DPrintf("#%d: java_init(%p, %p)\n", thr->tid, heap_begin, heap_size);<br>
+  CHECK_EQ(jctx, 0);<br>
+  CHECK_GT(heap_begin, 0);<br>
+  CHECK_GT(heap_size, 0);<br>
+  CHECK_LT(heap_begin, heap_begin + heap_size);<br>
+  jctx = new(jctx_buf) JavaContext(heap_begin, heap_size);<br>
 }<br>
<br>
 int  __tsan_java_fini() {<br>
-  return 0;<br>
+  SCOPED_JAVA_FUNC(__tsan_java_fini);<br>
+  DPrintf("#%d: java_fini()\n", thr->tid);<br>
+  CHECK_NE(jctx, 0);<br>
+  // FIXME(dvyukov): this does not call atexit() callbacks.<br>
+  int status = Finalize(thr);<br>
+  DPrintf("#%d: java_fini() = %d\n", thr->tid, status);<br>
+  return status;<br>
 }<br>
<br>
 void __tsan_java_alloc(jptr ptr, jptr size) {<br>
+  SCOPED_JAVA_FUNC(__tsan_java_alloc);<br>
+  DPrintf("#%d: java_alloc(%p, %p)\n", thr->tid, ptr, size);<br>
+  CHECK_NE(jctx, 0);<br>
+  CHECK_NE(size, 0);<br>
+  CHECK_GE(ptr, jctx->heap_begin);<br>
+  CHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);<br>
+<br>
+  BlockDesc *b = getblock(ptr);<br>
+  new(b) BlockDesc();<br>
 }<br>
<br>
 void __tsan_java_free(jptr ptr, jptr size) {<br>
+  SCOPED_JAVA_FUNC(__tsan_java_free);<br>
+  DPrintf("#%d: java_free(%p, %p)\n", thr->tid, ptr, size);<br>
+  CHECK_NE(jctx, 0);<br>
+  CHECK_NE(size, 0);<br>
+  CHECK_GE(ptr, jctx->heap_begin);<br>
+  CHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);<br>
+<br>
+  BlockDesc *beg = getblock(ptr);<br>
+  BlockDesc *end = getblock(ptr + size);<br>
+  for (BlockDesc *b = beg; b != end; b++) {<br>
+    if (b->begin)<br>
+      b->~BlockDesc();<br>
+  }<br>
 }<br>
<br>
 void __tsan_java_move(jptr src, jptr dst, jptr size) {<br>
+  SCOPED_JAVA_FUNC(__tsan_java_move);<br>
+  DPrintf("#%d: java_move(%p, %p, %p)\n", thr->tid, src, dst, size);<br>
+  CHECK_NE(jctx, 0);<br>
+  CHECK_NE(size, 0);<br>
+  CHECK_GE(src, jctx->heap_begin);<br>
+  CHECK_LE(src + size, jctx->heap_begin + jctx->heap_size);<br>
+  CHECK_GE(dst, jctx->heap_begin);<br>
+  CHECK_LE(dst + size, jctx->heap_begin + jctx->heap_size);<br>
+  CHECK(dst >= src + size || src >= dst + size);<br>
+<br>
+  // Assuming it's not running concurrently with threads that do<br>
+  // memory accesses and mutex operations (stop-the-world phase).<br>
+  BlockDesc *srcbeg = getblock(src);<br>
+  BlockDesc *dstbeg = getblock(dst);<br>
+  BlockDesc *srcend = getblock(src + size);<br>
+  for (BlockDesc *s = srcbeg, *d = dstbeg; s != srcend; s++, d++) {<br>
+    if (s->begin) {<br>
+      new(d) BlockDesc(s);<br>
+      s->~BlockDesc();<br>
+    }<br>
+  }<br>
 }<br>
<br>
 void __tsan_java_mutex_lock(jptr addr) {<br>
+  SCOPED_JAVA_FUNC(__tsan_java_mutex_lock);<br>
+  DPrintf("#%d: java_mutex_lock(%p)\n", thr->tid, addr);<br>
+  CHECK_NE(jctx, 0);<br>
+  CHECK_GE(addr, jctx->heap_begin);<br>
+  CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);<br>
+<br>
+  MutexLock(thr, pc, addr);<br>
 }<br>
<br>
 void __tsan_java_mutex_unlock(jptr addr) {<br>
+  SCOPED_JAVA_FUNC(__tsan_java_mutex_unlock);<br>
+  DPrintf("#%d: java_mutex_unlock(%p)\n", thr->tid, addr);<br>
+  CHECK_NE(jctx, 0);<br>
+  CHECK_GE(addr, jctx->heap_begin);<br>
+  CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);<br>
+<br>
+  MutexUnlock(thr, pc, addr);<br>
 }<br>
<br>
 void __tsan_java_mutex_read_lock(jptr addr) {<br>
+  SCOPED_JAVA_FUNC(__tsan_java_mutex_read_lock);<br>
+  DPrintf("#%d: java_mutex_read_lock(%p)\n", thr->tid, addr);<br>
+  CHECK_NE(jctx, 0);<br>
+  CHECK_GE(addr, jctx->heap_begin);<br>
+  CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);<br>
+<br>
+  MutexReadLock(thr, pc, addr);<br>
 }<br>
<br>
 void __tsan_java_mutex_read_unlock(jptr addr) {<br>
-}<br>
+  SCOPED_JAVA_FUNC(__tsan_java_mutex_read_unlock);<br>
+  DPrintf("#%d: java_mutex_read_unlock(%p)\n", thr->tid, addr);<br>
+  CHECK_NE(jctx, 0);<br>
+  CHECK_GE(addr, jctx->heap_begin);<br>
+  CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);<br>
<br>
+  MutexReadUnlock(thr, pc, addr);<br>
+}<br>
<br>
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_mutex.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_mutex.h?rev=170707&r1=170706&r2=170707&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_mutex.h?rev=170707&r1=170706&r2=170707&view=diff</a><br>

==============================================================================<br>
--- compiler-rt/trunk/lib/tsan/rtl/tsan_mutex.h (original)<br>
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_mutex.h Thu Dec 20 11:29:34 2012<br>
@@ -30,6 +30,7 @@<br>
   MutexTypeAnnotations,<br>
   MutexTypeAtExit,<br>
   MutexTypeMBlock,<br>
+  MutexTypeJava,<br>
<br>
   // This must be the last.<br>
   MutexTypeCount<br>
<br>
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h?rev=170707&r1=170706&r2=170707&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h?rev=170707&r1=170706&r2=170707&view=diff</a><br>

==============================================================================<br>
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h (original)<br>
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h Thu Dec 20 11:29:34 2012<br>
@@ -515,6 +515,10 @@<br>
 void Initialize(ThreadState *thr);<br>
 int Finalize(ThreadState *thr);<br>
<br>
+SyncVar* GetJavaSync(ThreadState *thr, uptr pc, uptr addr,<br>
+                     bool write_lock, bool create);<br>
+SyncVar* GetAndRemoveJavaSync(ThreadState *thr, uptr pc, uptr addr);<br>
+<br>
 void MemoryAccess(ThreadState *thr, uptr pc, uptr addr,<br>
     int kAccessSizeLog, bool kAccessIsWrite);<br>
 void MemoryAccessImpl(ThreadState *thr, uptr addr,<br>
<br>
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h?rev=170707&r1=170706&r2=170707&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h?rev=170707&r1=170706&r2=170707&view=diff</a><br>

==============================================================================<br>
--- compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h (original)<br>
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h Thu Dec 20 11:29:34 2012<br>
@@ -281,6 +281,7 @@<br>
   StatMtxAnnotations,<br>
   StatMtxAtExit,<br>
   StatMtxMBlock,<br>
+  StatMtxJava,<br>
<br>
   // This must be the last.<br>
   StatCnt<br>
<br>
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_sync.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_sync.cc?rev=170707&r1=170706&r2=170707&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_sync.cc?rev=170707&r1=170706&r2=170707&view=diff</a><br>

==============================================================================<br>
--- compiler-rt/trunk/lib/tsan/rtl/tsan_sync.cc (original)<br>
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_sync.cc Thu Dec 20 11:29:34 2012<br>
@@ -57,9 +57,26 @@<br>
   return GetAndLock(0, 0, addr, write_lock, false);<br>
 }<br>
<br>
+SyncVar* SyncTab::Create(ThreadState *thr, uptr pc, uptr addr) {<br>
+  StatInc(thr, StatSyncCreated);<br>
+  void *mem = internal_alloc(MBlockSync, sizeof(SyncVar));<br>
+  const u64 uid = atomic_fetch_add(&uid_gen_, 1, memory_order_relaxed);<br>
+  SyncVar *res = new(mem) SyncVar(addr, uid);<br>
+#ifndef TSAN_GO<br>
+  res->creation_stack.ObtainCurrent(thr, pc);<br>
+#endif<br>
+  return res;<br>
+}<br>
+<br>
 SyncVar* SyncTab::GetAndLock(ThreadState *thr, uptr pc,<br>
                              uptr addr, bool write_lock, bool create) {<br>
 #ifndef TSAN_GO<br>
+  {  // NOLINT<br>
+    SyncVar *res = GetJavaSync(thr, pc, addr, write_lock, create);<br>
+    if (res)<br>
+      return res;<br>
+  }<br>
+<br>
   // Here we ask only PrimaryAllocator, because<br>
   // SecondaryAllocator::PointerIsMine() is slow and we have fallback on<br>
   // the hashmap anyway.<br>
@@ -74,11 +91,7 @@<br>
     if (res == 0) {<br>
       if (!create)<br>
         return 0;<br>
-      StatInc(thr, StatSyncCreated);<br>
-      void *mem = internal_alloc(MBlockSync, sizeof(SyncVar));<br>
-      const u64 uid = atomic_fetch_add(&uid_gen_, 1, memory_order_relaxed);<br>
-      res = new(mem) SyncVar(addr, uid);<br>
-      res->creation_stack.ObtainCurrent(thr, pc);<br>
+      res = Create(thr, pc, addr);<br>
       res->next = b->head;<br>
       b->head = res;<br>
     }<br>
@@ -113,13 +126,7 @@<br>
         break;<br>
     }<br>
     if (res == 0) {<br>
-      StatInc(thr, StatSyncCreated);<br>
-      void *mem = internal_alloc(MBlockSync, sizeof(SyncVar));<br>
-      const u64 uid = atomic_fetch_add(&uid_gen_, 1, memory_order_relaxed);<br>
-      res = new(mem) SyncVar(addr, uid);<br>
-#ifndef TSAN_GO<br>
-      res->creation_stack.ObtainCurrent(thr, pc);<br>
-#endif<br>
+      res = Create(thr, pc, addr);<br>
       res->next = p->val;<br>
       p->val = res;<br>
     }<br>
@@ -133,6 +140,11 @@<br>
<br>
 SyncVar* SyncTab::GetAndRemove(ThreadState *thr, uptr pc, uptr addr) {<br>
 #ifndef TSAN_GO<br>
+  {  // NOLINT<br>
+    SyncVar *res = GetAndRemoveJavaSync(thr, pc, addr);<br>
+    if (res)<br>
+      return res;<br>
+  }<br>
   if (PrimaryAllocator::PointerIsMine((void*)addr)) {<br>
     MBlock *b = user_mblock(thr, (void*)addr);<br>
     SyncVar *res = 0;<br>
<br>
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_sync.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_sync.h?rev=170707&r1=170706&r2=170707&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_sync.h?rev=170707&r1=170706&r2=170707&view=diff</a><br>

==============================================================================<br>
--- compiler-rt/trunk/lib/tsan/rtl/tsan_sync.h (original)<br>
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_sync.h Thu Dec 20 11:29:34 2012<br>
@@ -96,6 +96,8 @@<br>
   // If the SyncVar does not exist, returns 0.<br>
   SyncVar* GetAndRemove(ThreadState *thr, uptr pc, uptr addr);<br>
<br>
+  SyncVar* Create(ThreadState *thr, uptr pc, uptr addr);<br>
+<br>
   uptr GetMemoryConsumption(uptr *nsync);<br>
<br>
  private:<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div></div>