<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>