tsan_interface_java.cc revision 2d1fdb26e458c4ddc04155c1d421bced3ba90cd0
1//===-- tsan_interface_java.cc --------------------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file is a part of ThreadSanitizer (TSan), a race detector.
11//
12//===----------------------------------------------------------------------===//
13
14#include "tsan_interface_java.h"
15#include "tsan_rtl.h"
16#include "tsan_mutex.h"
17#include "sanitizer_common/sanitizer_internal_defs.h"
18#include "sanitizer_common/sanitizer_common.h"
19#include "sanitizer_common/sanitizer_placement_new.h"
20#include "sanitizer_common/sanitizer_stacktrace.h"
21#include "sanitizer_common/sanitizer_procmaps.h"
22
23using namespace __tsan;  // NOLINT
24
25namespace __tsan {
26
27const uptr kHeapShadow = 0x300000000000ull;
28const uptr kHeapAlignment = 8;
29
30struct BlockDesc {
31  bool begin;
32  Mutex mtx;
33  SyncVar *head;
34
35  BlockDesc()
36      : mtx(MutexTypeJavaMBlock, StatMtxJavaMBlock)
37      , head() {
38    CHECK_EQ(begin, false);
39    begin = true;
40  }
41
42  ~BlockDesc() {
43    CHECK_EQ(begin, true);
44    begin = false;
45    ThreadState *thr = cur_thread();
46    SyncVar *s = head;
47    while (s) {
48      SyncVar *s1 = s->next;
49      StatInc(thr, StatSyncDestroyed);
50      s->mtx.Lock();
51      s->mtx.Unlock();
52      thr->mset.Remove(s->GetId());
53      DestroyAndFree(s);
54      s = s1;
55    }
56  }
57};
58
59struct JavaContext {
60  const uptr heap_begin;
61  const uptr heap_size;
62  BlockDesc *heap_shadow;
63
64  JavaContext(jptr heap_begin, jptr heap_size)
65      : heap_begin(heap_begin)
66      , heap_size(heap_size) {
67    uptr size = heap_size / kHeapAlignment * sizeof(BlockDesc);
68    heap_shadow = (BlockDesc*)MmapFixedNoReserve(kHeapShadow, size);
69    if ((uptr)heap_shadow != kHeapShadow) {
70      Printf("ThreadSanitizer: failed to mmap Java heap shadow\n");
71      Die();
72    }
73  }
74};
75
76class ScopedJavaFunc {
77 public:
78  ScopedJavaFunc(ThreadState *thr, uptr pc)
79      : thr_(thr) {
80    Initialize(thr_);
81    FuncEntry(thr, pc);
82  }
83
84  ~ScopedJavaFunc() {
85    FuncExit(thr_);
86    // FIXME(dvyukov): process pending signals.
87  }
88
89 private:
90  ThreadState *thr_;
91};
92
93static u64 jctx_buf[sizeof(JavaContext) / sizeof(u64) + 1];
94static JavaContext *jctx;
95
96static BlockDesc *getblock(uptr addr) {
97  uptr i = (addr - jctx->heap_begin) / kHeapAlignment;
98  return &jctx->heap_shadow[i];
99}
100
101static uptr USED getmem(BlockDesc *b) {
102  uptr i = b - jctx->heap_shadow;
103  uptr p = jctx->heap_begin + i * kHeapAlignment;
104  CHECK_GE(p, jctx->heap_begin);
105  CHECK_LT(p, jctx->heap_begin + jctx->heap_size);
106  return p;
107}
108
109static BlockDesc *getblockbegin(uptr addr) {
110  for (BlockDesc *b = getblock(addr);; b--) {
111    CHECK_GE(b, jctx->heap_shadow);
112    if (b->begin)
113      return b;
114  }
115  return 0;
116}
117
118SyncVar* GetJavaSync(ThreadState *thr, uptr pc, uptr addr,
119                     bool write_lock, bool create) {
120  if (jctx == 0 || addr < jctx->heap_begin
121      || addr >= jctx->heap_begin + jctx->heap_size)
122    return 0;
123  BlockDesc *b = getblockbegin(addr);
124  DPrintf("#%d: GetJavaSync %p->%p\n", thr->tid, addr, b);
125  Lock l(&b->mtx);
126  SyncVar *s = b->head;
127  for (; s; s = s->next) {
128    if (s->addr == addr) {
129      DPrintf("#%d: found existing sync for %p\n", thr->tid, addr);
130      break;
131    }
132  }
133  if (s == 0 && create) {
134    DPrintf("#%d: creating new sync for %p\n", thr->tid, addr);
135    s = ctx->synctab.Create(thr, pc, addr);
136    s->next = b->head;
137    b->head = s;
138  }
139  if (s) {
140    if (write_lock)
141      s->mtx.Lock();
142    else
143      s->mtx.ReadLock();
144  }
145  return s;
146}
147
148SyncVar* GetAndRemoveJavaSync(ThreadState *thr, uptr pc, uptr addr) {
149  // We do not destroy Java mutexes other than in __tsan_java_free().
150  return 0;
151}
152
153}  // namespace __tsan
154
155#define SCOPED_JAVA_FUNC(func) \
156  ThreadState *thr = cur_thread(); \
157  const uptr caller_pc = GET_CALLER_PC(); \
158  const uptr pc = __sanitizer::StackTrace::GetCurrentPc(); \
159  (void)pc; \
160  ScopedJavaFunc scoped(thr, caller_pc); \
161/**/
162
163void __tsan_java_init(jptr heap_begin, jptr heap_size) {
164  SCOPED_JAVA_FUNC(__tsan_java_init);
165  DPrintf("#%d: java_init(%p, %p)\n", thr->tid, heap_begin, heap_size);
166  CHECK_EQ(jctx, 0);
167  CHECK_GT(heap_begin, 0);
168  CHECK_GT(heap_size, 0);
169  CHECK_EQ(heap_begin % kHeapAlignment, 0);
170  CHECK_EQ(heap_size % kHeapAlignment, 0);
171  CHECK_LT(heap_begin, heap_begin + heap_size);
172  jctx = new(jctx_buf) JavaContext(heap_begin, heap_size);
173}
174
175int  __tsan_java_fini() {
176  SCOPED_JAVA_FUNC(__tsan_java_fini);
177  DPrintf("#%d: java_fini()\n", thr->tid);
178  CHECK_NE(jctx, 0);
179  // FIXME(dvyukov): this does not call atexit() callbacks.
180  int status = Finalize(thr);
181  DPrintf("#%d: java_fini() = %d\n", thr->tid, status);
182  return status;
183}
184
185void __tsan_java_alloc(jptr ptr, jptr size) {
186  SCOPED_JAVA_FUNC(__tsan_java_alloc);
187  DPrintf("#%d: java_alloc(%p, %p)\n", thr->tid, ptr, size);
188  CHECK_NE(jctx, 0);
189  CHECK_NE(size, 0);
190  CHECK_EQ(ptr % kHeapAlignment, 0);
191  CHECK_EQ(size % kHeapAlignment, 0);
192  CHECK_GE(ptr, jctx->heap_begin);
193  CHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
194
195  BlockDesc *b = getblock(ptr);
196  new(b) BlockDesc();
197}
198
199void __tsan_java_free(jptr ptr, jptr size) {
200  SCOPED_JAVA_FUNC(__tsan_java_free);
201  DPrintf("#%d: java_free(%p, %p)\n", thr->tid, ptr, size);
202  CHECK_NE(jctx, 0);
203  CHECK_NE(size, 0);
204  CHECK_EQ(ptr % kHeapAlignment, 0);
205  CHECK_EQ(size % kHeapAlignment, 0);
206  CHECK_GE(ptr, jctx->heap_begin);
207  CHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
208
209  BlockDesc *beg = getblock(ptr);
210  BlockDesc *end = getblock(ptr + size);
211  for (BlockDesc *b = beg; b != end; b++) {
212    if (b->begin)
213      b->~BlockDesc();
214  }
215}
216
217void __tsan_java_move(jptr src, jptr dst, jptr size) {
218  SCOPED_JAVA_FUNC(__tsan_java_move);
219  DPrintf("#%d: java_move(%p, %p, %p)\n", thr->tid, src, dst, size);
220  CHECK_NE(jctx, 0);
221  CHECK_NE(size, 0);
222  CHECK_EQ(src % kHeapAlignment, 0);
223  CHECK_EQ(dst % kHeapAlignment, 0);
224  CHECK_EQ(size % kHeapAlignment, 0);
225  CHECK_GE(src, jctx->heap_begin);
226  CHECK_LE(src + size, jctx->heap_begin + jctx->heap_size);
227  CHECK_GE(dst, jctx->heap_begin);
228  CHECK_LE(dst + size, jctx->heap_begin + jctx->heap_size);
229  CHECK(dst >= src + size || src >= dst + size);
230
231  // Assuming it's not running concurrently with threads that do
232  // memory accesses and mutex operations (stop-the-world phase).
233  {  // NOLINT
234    BlockDesc *s = getblock(src);
235    BlockDesc *d = getblock(dst);
236    BlockDesc *send = getblock(src + size);
237    for (; s != send; s++, d++) {
238      CHECK_EQ(d->begin, false);
239      if (s->begin) {
240        DPrintf("#%d: moving block %p->%p\n", thr->tid, getmem(s), getmem(d));
241        new(d) BlockDesc;
242        d->head = s->head;
243        for (SyncVar *sync = d->head; sync; sync = sync->next) {
244          uptr newaddr = sync->addr - src + dst;
245          DPrintf("#%d: moving sync %p->%p\n", thr->tid, sync->addr, newaddr);
246          sync->addr = newaddr;
247        }
248        s->head = 0;
249        s->~BlockDesc();
250      }
251    }
252  }
253
254  {  // NOLINT
255    u64 *s = (u64*)MemToShadow(src);
256    u64 *d = (u64*)MemToShadow(dst);
257    u64 *send = (u64*)MemToShadow(src + size);
258    for (; s != send; s++, d++) {
259      *d = *s;
260      *s = 0;
261    }
262  }
263}
264
265void __tsan_java_mutex_lock(jptr addr) {
266  SCOPED_JAVA_FUNC(__tsan_java_mutex_lock);
267  DPrintf("#%d: java_mutex_lock(%p)\n", thr->tid, addr);
268  CHECK_NE(jctx, 0);
269  CHECK_GE(addr, jctx->heap_begin);
270  CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
271
272  MutexCreate(thr, pc, addr, true, true, true);
273  MutexLock(thr, pc, addr);
274}
275
276void __tsan_java_mutex_unlock(jptr addr) {
277  SCOPED_JAVA_FUNC(__tsan_java_mutex_unlock);
278  DPrintf("#%d: java_mutex_unlock(%p)\n", thr->tid, addr);
279  CHECK_NE(jctx, 0);
280  CHECK_GE(addr, jctx->heap_begin);
281  CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
282
283  MutexUnlock(thr, pc, addr);
284}
285
286void __tsan_java_mutex_read_lock(jptr addr) {
287  SCOPED_JAVA_FUNC(__tsan_java_mutex_read_lock);
288  DPrintf("#%d: java_mutex_read_lock(%p)\n", thr->tid, addr);
289  CHECK_NE(jctx, 0);
290  CHECK_GE(addr, jctx->heap_begin);
291  CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
292
293  MutexCreate(thr, pc, addr, true, true, true);
294  MutexReadLock(thr, pc, addr);
295}
296
297void __tsan_java_mutex_read_unlock(jptr addr) {
298  SCOPED_JAVA_FUNC(__tsan_java_mutex_read_unlock);
299  DPrintf("#%d: java_mutex_read_unlock(%p)\n", thr->tid, addr);
300  CHECK_NE(jctx, 0);
301  CHECK_GE(addr, jctx->heap_begin);
302  CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
303
304  MutexReadUnlock(thr, pc, addr);
305}
306
307void __tsan_java_mutex_lock_rec(jptr addr, int rec) {
308  SCOPED_JAVA_FUNC(__tsan_java_mutex_lock_rec);
309  DPrintf("#%d: java_mutex_lock_rec(%p, %d)\n", thr->tid, addr, rec);
310  CHECK_NE(jctx, 0);
311  CHECK_GE(addr, jctx->heap_begin);
312  CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
313  CHECK_GT(rec, 0);
314
315  MutexCreate(thr, pc, addr, true, true, true);
316  MutexLock(thr, pc, addr, rec);
317}
318
319int __tsan_java_mutex_unlock_rec(jptr addr) {
320  SCOPED_JAVA_FUNC(__tsan_java_mutex_unlock_rec);
321  DPrintf("#%d: java_mutex_unlock_rec(%p)\n", thr->tid, addr);
322  CHECK_NE(jctx, 0);
323  CHECK_GE(addr, jctx->heap_begin);
324  CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
325
326  return MutexUnlock(thr, pc, addr, true);
327}
328