blob: e63b93f4139c179a46516ab960afbac7a592cebe [file] [log] [blame]
Dmitry Vyukovd088b3b2012-12-20 10:21:30 +00001//===-- 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"
Dmitry Vyukov2547ac62012-12-20 17:29:34 +000016#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"
Dmitry Vyukov5cf581a2013-06-17 19:57:03 +000020#include "sanitizer_common/sanitizer_stacktrace.h"
Dmitry Vyukov150406b2013-09-21 23:06:00 +000021#include "sanitizer_common/sanitizer_procmaps.h"
Dmitry Vyukovd088b3b2012-12-20 10:21:30 +000022
23using namespace __tsan; // NOLINT
24
Dmitry Vyukovbde4c9c2014-05-29 13:50:54 +000025const jptr kHeapAlignment = 8;
26
Dmitry Vyukov2547ac62012-12-20 17:29:34 +000027namespace __tsan {
28
Dmitry Vyukov2547ac62012-12-20 17:29:34 +000029struct JavaContext {
Dmitry Vyukov2547ac62012-12-20 17:29:34 +000030 const uptr heap_begin;
31 const uptr heap_size;
Dmitry Vyukov2547ac62012-12-20 17:29:34 +000032
33 JavaContext(jptr heap_begin, jptr heap_size)
Dmitry Vyukov22be55e2012-12-21 11:30:14 +000034 : heap_begin(heap_begin)
Dmitry Vyukov2547ac62012-12-20 17:29:34 +000035 , heap_size(heap_size) {
Dmitry Vyukov2547ac62012-12-20 17:29:34 +000036 }
37};
38
39class ScopedJavaFunc {
40 public:
41 ScopedJavaFunc(ThreadState *thr, uptr pc)
42 : thr_(thr) {
43 Initialize(thr_);
44 FuncEntry(thr, pc);
Dmitry Vyukov2547ac62012-12-20 17:29:34 +000045 }
46
47 ~ScopedJavaFunc() {
Dmitry Vyukov2547ac62012-12-20 17:29:34 +000048 FuncExit(thr_);
49 // FIXME(dvyukov): process pending signals.
50 }
51
52 private:
53 ThreadState *thr_;
54};
55
56static u64 jctx_buf[sizeof(JavaContext) / sizeof(u64) + 1];
57static JavaContext *jctx;
58
Alexey Samsonov49a32c12013-01-30 07:45:58 +000059} // namespace __tsan
Dmitry Vyukov2547ac62012-12-20 17:29:34 +000060
61#define SCOPED_JAVA_FUNC(func) \
62 ThreadState *thr = cur_thread(); \
63 const uptr caller_pc = GET_CALLER_PC(); \
Dmitry Vyukov5cf581a2013-06-17 19:57:03 +000064 const uptr pc = __sanitizer::StackTrace::GetCurrentPc(); \
Dmitry Vyukov2547ac62012-12-20 17:29:34 +000065 (void)pc; \
66 ScopedJavaFunc scoped(thr, caller_pc); \
67/**/
68
69void __tsan_java_init(jptr heap_begin, jptr heap_size) {
70 SCOPED_JAVA_FUNC(__tsan_java_init);
71 DPrintf("#%d: java_init(%p, %p)\n", thr->tid, heap_begin, heap_size);
72 CHECK_EQ(jctx, 0);
73 CHECK_GT(heap_begin, 0);
74 CHECK_GT(heap_size, 0);
Dmitry Vyukova5b57102012-12-21 11:16:40 +000075 CHECK_EQ(heap_begin % kHeapAlignment, 0);
76 CHECK_EQ(heap_size % kHeapAlignment, 0);
Dmitry Vyukov2547ac62012-12-20 17:29:34 +000077 CHECK_LT(heap_begin, heap_begin + heap_size);
78 jctx = new(jctx_buf) JavaContext(heap_begin, heap_size);
79}
80
81int __tsan_java_fini() {
82 SCOPED_JAVA_FUNC(__tsan_java_fini);
83 DPrintf("#%d: java_fini()\n", thr->tid);
84 CHECK_NE(jctx, 0);
85 // FIXME(dvyukov): this does not call atexit() callbacks.
86 int status = Finalize(thr);
87 DPrintf("#%d: java_fini() = %d\n", thr->tid, status);
88 return status;
89}
90
Dmitry Vyukovd088b3b2012-12-20 10:21:30 +000091void __tsan_java_alloc(jptr ptr, jptr size) {
Dmitry Vyukov2547ac62012-12-20 17:29:34 +000092 SCOPED_JAVA_FUNC(__tsan_java_alloc);
93 DPrintf("#%d: java_alloc(%p, %p)\n", thr->tid, ptr, size);
94 CHECK_NE(jctx, 0);
95 CHECK_NE(size, 0);
Dmitry Vyukova5b57102012-12-21 11:16:40 +000096 CHECK_EQ(ptr % kHeapAlignment, 0);
97 CHECK_EQ(size % kHeapAlignment, 0);
Dmitry Vyukov2547ac62012-12-20 17:29:34 +000098 CHECK_GE(ptr, jctx->heap_begin);
99 CHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
100
Dmitry Vyukovbde4c9c2014-05-29 13:50:54 +0000101 OnUserAlloc(thr, pc, ptr, size, false);
Dmitry Vyukovd088b3b2012-12-20 10:21:30 +0000102}
103
104void __tsan_java_free(jptr ptr, jptr size) {
Dmitry Vyukov2547ac62012-12-20 17:29:34 +0000105 SCOPED_JAVA_FUNC(__tsan_java_free);
106 DPrintf("#%d: java_free(%p, %p)\n", thr->tid, ptr, size);
107 CHECK_NE(jctx, 0);
108 CHECK_NE(size, 0);
Dmitry Vyukova5b57102012-12-21 11:16:40 +0000109 CHECK_EQ(ptr % kHeapAlignment, 0);
110 CHECK_EQ(size % kHeapAlignment, 0);
Dmitry Vyukov2547ac62012-12-20 17:29:34 +0000111 CHECK_GE(ptr, jctx->heap_begin);
112 CHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
113
Dmitry Vyukovbde4c9c2014-05-29 13:50:54 +0000114 ctx->metamap.FreeRange(thr, pc, ptr, size);
Dmitry Vyukovd088b3b2012-12-20 10:21:30 +0000115}
116
117void __tsan_java_move(jptr src, jptr dst, jptr size) {
Dmitry Vyukov2547ac62012-12-20 17:29:34 +0000118 SCOPED_JAVA_FUNC(__tsan_java_move);
119 DPrintf("#%d: java_move(%p, %p, %p)\n", thr->tid, src, dst, size);
120 CHECK_NE(jctx, 0);
121 CHECK_NE(size, 0);
Dmitry Vyukova5b57102012-12-21 11:16:40 +0000122 CHECK_EQ(src % kHeapAlignment, 0);
123 CHECK_EQ(dst % kHeapAlignment, 0);
124 CHECK_EQ(size % kHeapAlignment, 0);
Dmitry Vyukov2547ac62012-12-20 17:29:34 +0000125 CHECK_GE(src, jctx->heap_begin);
126 CHECK_LE(src + size, jctx->heap_begin + jctx->heap_size);
127 CHECK_GE(dst, jctx->heap_begin);
128 CHECK_LE(dst + size, jctx->heap_begin + jctx->heap_size);
129 CHECK(dst >= src + size || src >= dst + size);
130
131 // Assuming it's not running concurrently with threads that do
132 // memory accesses and mutex operations (stop-the-world phase).
Dmitry Vyukovbde4c9c2014-05-29 13:50:54 +0000133 ctx->metamap.MoveMemory(src, dst, size);
Dmitry Vyukova5b57102012-12-21 11:16:40 +0000134
Dmitry Vyukovbde4c9c2014-05-29 13:50:54 +0000135 // Move shadow.
136 u64 *s = (u64*)MemToShadow(src);
137 u64 *d = (u64*)MemToShadow(dst);
138 u64 *send = (u64*)MemToShadow(src + size);
139 for (; s != send; s++, d++) {
140 *d = *s;
141 *s = 0;
Dmitry Vyukov2547ac62012-12-20 17:29:34 +0000142 }
Dmitry Vyukovd088b3b2012-12-20 10:21:30 +0000143}
144
Dmitry Vyukovfb251f52014-06-27 00:47:38 +0000145void __tsan_java_finalize() {
146 SCOPED_JAVA_FUNC(__tsan_java_finalize);
147 DPrintf("#%d: java_mutex_finalize()\n", thr->tid);
148 AcquireGlobal(thr, 0);
149}
150
Dmitry Vyukovd088b3b2012-12-20 10:21:30 +0000151void __tsan_java_mutex_lock(jptr addr) {
Dmitry Vyukov2547ac62012-12-20 17:29:34 +0000152 SCOPED_JAVA_FUNC(__tsan_java_mutex_lock);
153 DPrintf("#%d: java_mutex_lock(%p)\n", thr->tid, addr);
154 CHECK_NE(jctx, 0);
155 CHECK_GE(addr, jctx->heap_begin);
156 CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
157
Dmitry Vyukovc9af8182013-05-17 12:03:46 +0000158 MutexCreate(thr, pc, addr, true, true, true);
Dmitry Vyukov2547ac62012-12-20 17:29:34 +0000159 MutexLock(thr, pc, addr);
Dmitry Vyukovd088b3b2012-12-20 10:21:30 +0000160}
161
162void __tsan_java_mutex_unlock(jptr addr) {
Dmitry Vyukov2547ac62012-12-20 17:29:34 +0000163 SCOPED_JAVA_FUNC(__tsan_java_mutex_unlock);
164 DPrintf("#%d: java_mutex_unlock(%p)\n", thr->tid, addr);
165 CHECK_NE(jctx, 0);
166 CHECK_GE(addr, jctx->heap_begin);
167 CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
168
169 MutexUnlock(thr, pc, addr);
Dmitry Vyukovd088b3b2012-12-20 10:21:30 +0000170}
171
172void __tsan_java_mutex_read_lock(jptr addr) {
Dmitry Vyukov2547ac62012-12-20 17:29:34 +0000173 SCOPED_JAVA_FUNC(__tsan_java_mutex_read_lock);
174 DPrintf("#%d: java_mutex_read_lock(%p)\n", thr->tid, addr);
175 CHECK_NE(jctx, 0);
176 CHECK_GE(addr, jctx->heap_begin);
177 CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
178
Dmitry Vyukovc9af8182013-05-17 12:03:46 +0000179 MutexCreate(thr, pc, addr, true, true, true);
Dmitry Vyukov2547ac62012-12-20 17:29:34 +0000180 MutexReadLock(thr, pc, addr);
Dmitry Vyukovd088b3b2012-12-20 10:21:30 +0000181}
182
183void __tsan_java_mutex_read_unlock(jptr addr) {
Dmitry Vyukov2547ac62012-12-20 17:29:34 +0000184 SCOPED_JAVA_FUNC(__tsan_java_mutex_read_unlock);
185 DPrintf("#%d: java_mutex_read_unlock(%p)\n", thr->tid, addr);
186 CHECK_NE(jctx, 0);
187 CHECK_GE(addr, jctx->heap_begin);
188 CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
Dmitry Vyukovd088b3b2012-12-20 10:21:30 +0000189
Dmitry Vyukov2547ac62012-12-20 17:29:34 +0000190 MutexReadUnlock(thr, pc, addr);
191}
Dmitry Vyukovc9af8182013-05-17 12:03:46 +0000192
193void __tsan_java_mutex_lock_rec(jptr addr, int rec) {
194 SCOPED_JAVA_FUNC(__tsan_java_mutex_lock_rec);
195 DPrintf("#%d: java_mutex_lock_rec(%p, %d)\n", thr->tid, addr, rec);
196 CHECK_NE(jctx, 0);
197 CHECK_GE(addr, jctx->heap_begin);
198 CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
199 CHECK_GT(rec, 0);
200
201 MutexCreate(thr, pc, addr, true, true, true);
202 MutexLock(thr, pc, addr, rec);
203}
204
205int __tsan_java_mutex_unlock_rec(jptr addr) {
206 SCOPED_JAVA_FUNC(__tsan_java_mutex_unlock_rec);
207 DPrintf("#%d: java_mutex_unlock_rec(%p)\n", thr->tid, addr);
208 CHECK_NE(jctx, 0);
209 CHECK_GE(addr, jctx->heap_begin);
210 CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
211
212 return MutexUnlock(thr, pc, addr, true);
213}