1e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukov//===-- tsan_interface_java.cc --------------------------------------------===//
2e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukov//
3e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukov//                     The LLVM Compiler Infrastructure
4e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukov//
5e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukov// This file is distributed under the University of Illinois Open Source
6e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukov// License. See LICENSE.TXT for details.
7e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukov//
8e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukov//===----------------------------------------------------------------------===//
9e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukov//
10e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukov// This file is a part of ThreadSanitizer (TSan), a race detector.
11e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukov//
12e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukov//===----------------------------------------------------------------------===//
13e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukov
14e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukov#include "tsan_interface_java.h"
15e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukov#include "tsan_rtl.h"
1621cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov#include "tsan_mutex.h"
1721cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov#include "sanitizer_common/sanitizer_internal_defs.h"
1821cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov#include "sanitizer_common/sanitizer_common.h"
1921cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov#include "sanitizer_common/sanitizer_placement_new.h"
20e7718bcc1372d25fc21100e403cf41b166d42f9bDmitry Vyukov#include "sanitizer_common/sanitizer_stacktrace.h"
21d18865339cebcdaa9fc720a1e960cb452f330835Dmitry Vyukov#include "sanitizer_common/sanitizer_procmaps.h"
22e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukov
23e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukovusing namespace __tsan;  // NOLINT
24e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukov
256a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hinesconst jptr kHeapAlignment = 8;
2621cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov
276a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hinesnamespace __tsan {
2821cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov
2921cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukovstruct JavaContext {
3021cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  const uptr heap_begin;
3121cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  const uptr heap_size;
3221cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov
3321cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  JavaContext(jptr heap_begin, jptr heap_size)
34f4e4f9393ed1cf9cbefaafc6ea8fd9b89fea4bcfDmitry Vyukov      : heap_begin(heap_begin)
3521cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov      , heap_size(heap_size) {
3621cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  }
3721cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov};
3821cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov
3921cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukovclass ScopedJavaFunc {
4021cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov public:
4121cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  ScopedJavaFunc(ThreadState *thr, uptr pc)
4221cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov      : thr_(thr) {
4321cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov    Initialize(thr_);
4421cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov    FuncEntry(thr, pc);
4521cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  }
4621cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov
4721cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  ~ScopedJavaFunc() {
4821cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov    FuncExit(thr_);
4921cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov    // FIXME(dvyukov): process pending signals.
5021cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  }
5121cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov
5221cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov private:
5321cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  ThreadState *thr_;
5421cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov};
5521cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov
5621cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukovstatic u64 jctx_buf[sizeof(JavaContext) / sizeof(u64) + 1];
5721cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukovstatic JavaContext *jctx;
5821cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov
59ba5e99668e3030cc5bab357a04271a1bdbac209cAlexey Samsonov}  // namespace __tsan
6021cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov
6121cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov#define SCOPED_JAVA_FUNC(func) \
6221cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  ThreadState *thr = cur_thread(); \
6321cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  const uptr caller_pc = GET_CALLER_PC(); \
646d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  const uptr pc = StackTrace::GetCurrentPc(); \
6521cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  (void)pc; \
6621cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  ScopedJavaFunc scoped(thr, caller_pc); \
6721cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov/**/
6821cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov
69e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukovvoid __tsan_java_init(jptr heap_begin, jptr heap_size) {
7021cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  SCOPED_JAVA_FUNC(__tsan_java_init);
7121cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  DPrintf("#%d: java_init(%p, %p)\n", thr->tid, heap_begin, heap_size);
7221cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  CHECK_EQ(jctx, 0);
7321cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  CHECK_GT(heap_begin, 0);
7421cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  CHECK_GT(heap_size, 0);
75ef86724015d7882c2d3e614e0f72bffe10cb762bDmitry Vyukov  CHECK_EQ(heap_begin % kHeapAlignment, 0);
76ef86724015d7882c2d3e614e0f72bffe10cb762bDmitry Vyukov  CHECK_EQ(heap_size % kHeapAlignment, 0);
7721cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  CHECK_LT(heap_begin, heap_begin + heap_size);
7821cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  jctx = new(jctx_buf) JavaContext(heap_begin, heap_size);
79e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukov}
80e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukov
81e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukovint  __tsan_java_fini() {
8221cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  SCOPED_JAVA_FUNC(__tsan_java_fini);
8321cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  DPrintf("#%d: java_fini()\n", thr->tid);
8421cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  CHECK_NE(jctx, 0);
8521cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  // FIXME(dvyukov): this does not call atexit() callbacks.
8621cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  int status = Finalize(thr);
8721cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  DPrintf("#%d: java_fini() = %d\n", thr->tid, status);
8821cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  return status;
89e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukov}
90e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukov
91e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukovvoid __tsan_java_alloc(jptr ptr, jptr size) {
9221cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  SCOPED_JAVA_FUNC(__tsan_java_alloc);
9321cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  DPrintf("#%d: java_alloc(%p, %p)\n", thr->tid, ptr, size);
9421cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  CHECK_NE(jctx, 0);
9521cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  CHECK_NE(size, 0);
96ef86724015d7882c2d3e614e0f72bffe10cb762bDmitry Vyukov  CHECK_EQ(ptr % kHeapAlignment, 0);
97ef86724015d7882c2d3e614e0f72bffe10cb762bDmitry Vyukov  CHECK_EQ(size % kHeapAlignment, 0);
9821cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  CHECK_GE(ptr, jctx->heap_begin);
9921cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  CHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
10021cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov
1016a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  OnUserAlloc(thr, pc, ptr, size, false);
102e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukov}
103e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukov
104e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukovvoid __tsan_java_free(jptr ptr, jptr size) {
10521cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  SCOPED_JAVA_FUNC(__tsan_java_free);
10621cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  DPrintf("#%d: java_free(%p, %p)\n", thr->tid, ptr, size);
10721cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  CHECK_NE(jctx, 0);
10821cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  CHECK_NE(size, 0);
109ef86724015d7882c2d3e614e0f72bffe10cb762bDmitry Vyukov  CHECK_EQ(ptr % kHeapAlignment, 0);
110ef86724015d7882c2d3e614e0f72bffe10cb762bDmitry Vyukov  CHECK_EQ(size % kHeapAlignment, 0);
11121cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  CHECK_GE(ptr, jctx->heap_begin);
11221cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  CHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
11321cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov
114c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  ctx->metamap.FreeRange(thr->proc(), ptr, size);
115e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukov}
116e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukov
117e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukovvoid __tsan_java_move(jptr src, jptr dst, jptr size) {
11821cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  SCOPED_JAVA_FUNC(__tsan_java_move);
11921cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  DPrintf("#%d: java_move(%p, %p, %p)\n", thr->tid, src, dst, size);
12021cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  CHECK_NE(jctx, 0);
12121cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  CHECK_NE(size, 0);
122ef86724015d7882c2d3e614e0f72bffe10cb762bDmitry Vyukov  CHECK_EQ(src % kHeapAlignment, 0);
123ef86724015d7882c2d3e614e0f72bffe10cb762bDmitry Vyukov  CHECK_EQ(dst % kHeapAlignment, 0);
124ef86724015d7882c2d3e614e0f72bffe10cb762bDmitry Vyukov  CHECK_EQ(size % kHeapAlignment, 0);
12521cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  CHECK_GE(src, jctx->heap_begin);
12621cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  CHECK_LE(src + size, jctx->heap_begin + jctx->heap_size);
12721cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  CHECK_GE(dst, jctx->heap_begin);
12821cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  CHECK_LE(dst + size, jctx->heap_begin + jctx->heap_size);
1296a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  CHECK_NE(dst, src);
1306a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  CHECK_NE(size, 0);
13121cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov
13221cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  // Assuming it's not running concurrently with threads that do
13321cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  // memory accesses and mutex operations (stop-the-world phase).
1346a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  ctx->metamap.MoveMemory(src, dst, size);
1356a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines
1366a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  // Move shadow.
1376a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  u64 *s = (u64*)MemToShadow(src);
1386a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  u64 *d = (u64*)MemToShadow(dst);
1396a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  u64 *send = (u64*)MemToShadow(src + size);
1406a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  uptr inc = 1;
1416a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  if (dst > src) {
1426a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    s = (u64*)MemToShadow(src + size) - 1;
1436a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    d = (u64*)MemToShadow(dst + size) - 1;
1446a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    send = (u64*)MemToShadow(src) - 1;
1456a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    inc = -1;
146ef86724015d7882c2d3e614e0f72bffe10cb762bDmitry Vyukov  }
1476a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  for (; s != send; s += inc, d += inc) {
1486a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    *d = *s;
1496a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    *s = 0;
15021cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  }
151e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukov}
152e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukov
1536a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hinesvoid __tsan_java_finalize() {
1546a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  SCOPED_JAVA_FUNC(__tsan_java_finalize);
1556a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  DPrintf("#%d: java_mutex_finalize()\n", thr->tid);
1566a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  AcquireGlobal(thr, 0);
1576a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines}
1586a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines
159e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukovvoid __tsan_java_mutex_lock(jptr addr) {
16021cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  SCOPED_JAVA_FUNC(__tsan_java_mutex_lock);
16121cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  DPrintf("#%d: java_mutex_lock(%p)\n", thr->tid, addr);
16221cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  CHECK_NE(jctx, 0);
16321cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  CHECK_GE(addr, jctx->heap_begin);
16421cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
16521cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov
1668354faeec647dc5b420726fa61616189392d5045Dmitry Vyukov  MutexCreate(thr, pc, addr, true, true, true);
16721cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  MutexLock(thr, pc, addr);
168e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukov}
169e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukov
170e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukovvoid __tsan_java_mutex_unlock(jptr addr) {
17121cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  SCOPED_JAVA_FUNC(__tsan_java_mutex_unlock);
17221cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  DPrintf("#%d: java_mutex_unlock(%p)\n", thr->tid, addr);
17321cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  CHECK_NE(jctx, 0);
17421cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  CHECK_GE(addr, jctx->heap_begin);
17521cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
17621cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov
17721cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  MutexUnlock(thr, pc, addr);
178e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukov}
179e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukov
180e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukovvoid __tsan_java_mutex_read_lock(jptr addr) {
18121cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  SCOPED_JAVA_FUNC(__tsan_java_mutex_read_lock);
18221cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  DPrintf("#%d: java_mutex_read_lock(%p)\n", thr->tid, addr);
18321cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  CHECK_NE(jctx, 0);
18421cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  CHECK_GE(addr, jctx->heap_begin);
18521cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
18621cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov
1878354faeec647dc5b420726fa61616189392d5045Dmitry Vyukov  MutexCreate(thr, pc, addr, true, true, true);
18821cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  MutexReadLock(thr, pc, addr);
189e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukov}
190e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukov
191e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukovvoid __tsan_java_mutex_read_unlock(jptr addr) {
19221cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  SCOPED_JAVA_FUNC(__tsan_java_mutex_read_unlock);
19321cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  DPrintf("#%d: java_mutex_read_unlock(%p)\n", thr->tid, addr);
19421cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  CHECK_NE(jctx, 0);
19521cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  CHECK_GE(addr, jctx->heap_begin);
19621cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
197e78b620d10b4c59871480a130c10588a124d05f4Dmitry Vyukov
19821cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov  MutexReadUnlock(thr, pc, addr);
19921cc85db95b8fa85a9ff7a403c8a24e345d73bafDmitry Vyukov}
2008354faeec647dc5b420726fa61616189392d5045Dmitry Vyukov
2018354faeec647dc5b420726fa61616189392d5045Dmitry Vyukovvoid __tsan_java_mutex_lock_rec(jptr addr, int rec) {
2028354faeec647dc5b420726fa61616189392d5045Dmitry Vyukov  SCOPED_JAVA_FUNC(__tsan_java_mutex_lock_rec);
2038354faeec647dc5b420726fa61616189392d5045Dmitry Vyukov  DPrintf("#%d: java_mutex_lock_rec(%p, %d)\n", thr->tid, addr, rec);
2048354faeec647dc5b420726fa61616189392d5045Dmitry Vyukov  CHECK_NE(jctx, 0);
2058354faeec647dc5b420726fa61616189392d5045Dmitry Vyukov  CHECK_GE(addr, jctx->heap_begin);
2068354faeec647dc5b420726fa61616189392d5045Dmitry Vyukov  CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
2078354faeec647dc5b420726fa61616189392d5045Dmitry Vyukov  CHECK_GT(rec, 0);
2088354faeec647dc5b420726fa61616189392d5045Dmitry Vyukov
2098354faeec647dc5b420726fa61616189392d5045Dmitry Vyukov  MutexCreate(thr, pc, addr, true, true, true);
2108354faeec647dc5b420726fa61616189392d5045Dmitry Vyukov  MutexLock(thr, pc, addr, rec);
2118354faeec647dc5b420726fa61616189392d5045Dmitry Vyukov}
2128354faeec647dc5b420726fa61616189392d5045Dmitry Vyukov
2138354faeec647dc5b420726fa61616189392d5045Dmitry Vyukovint __tsan_java_mutex_unlock_rec(jptr addr) {
2148354faeec647dc5b420726fa61616189392d5045Dmitry Vyukov  SCOPED_JAVA_FUNC(__tsan_java_mutex_unlock_rec);
2158354faeec647dc5b420726fa61616189392d5045Dmitry Vyukov  DPrintf("#%d: java_mutex_unlock_rec(%p)\n", thr->tid, addr);
2168354faeec647dc5b420726fa61616189392d5045Dmitry Vyukov  CHECK_NE(jctx, 0);
2178354faeec647dc5b420726fa61616189392d5045Dmitry Vyukov  CHECK_GE(addr, jctx->heap_begin);
2188354faeec647dc5b420726fa61616189392d5045Dmitry Vyukov  CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
2198354faeec647dc5b420726fa61616189392d5045Dmitry Vyukov
2208354faeec647dc5b420726fa61616189392d5045Dmitry Vyukov  return MutexUnlock(thr, pc, addr, true);
2218354faeec647dc5b420726fa61616189392d5045Dmitry Vyukov}
22286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
22386277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid __tsan_java_acquire(jptr addr) {
22486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  SCOPED_JAVA_FUNC(__tsan_java_acquire);
22586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  DPrintf("#%d: java_acquire(%p)\n", thr->tid, addr);
22686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHECK_NE(jctx, 0);
22786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHECK_GE(addr, jctx->heap_begin);
22886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
22986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
23086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  Acquire(thr, caller_pc, addr);
23186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
23286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
23386277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid __tsan_java_release(jptr addr) {
23486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  SCOPED_JAVA_FUNC(__tsan_java_release);
23586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  DPrintf("#%d: java_release(%p)\n", thr->tid, addr);
23686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHECK_NE(jctx, 0);
23786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHECK_GE(addr, jctx->heap_begin);
23886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
23986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
24086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  Release(thr, caller_pc, addr);
24186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
24286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
24386277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid __tsan_java_release_store(jptr addr) {
24486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  SCOPED_JAVA_FUNC(__tsan_java_release);
24586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  DPrintf("#%d: java_release_store(%p)\n", thr->tid, addr);
24686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHECK_NE(jctx, 0);
24786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHECK_GE(addr, jctx->heap_begin);
24886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
24986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
25086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  ReleaseStore(thr, caller_pc, addr);
25186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
252