1 //===-- tsan_interface_java.cc --------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file is a part of ThreadSanitizer (TSan), a race detector.
12 //===----------------------------------------------------------------------===//
14 #include "tsan_interface_java.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"
23 using namespace __tsan; // NOLINT
25 const jptr kHeapAlignment = 8;
30 const uptr heap_begin;
33 JavaContext(jptr heap_begin, jptr heap_size)
34 : heap_begin(heap_begin)
35 , heap_size(heap_size) {
39 class ScopedJavaFunc {
41 ScopedJavaFunc(ThreadState *thr, uptr pc)
49 // FIXME(dvyukov): process pending signals.
56 static u64 jctx_buf[sizeof(JavaContext) / sizeof(u64) + 1];
57 static JavaContext *jctx;
61 #define SCOPED_JAVA_FUNC(func) \
62 ThreadState *thr = cur_thread(); \
63 const uptr caller_pc = GET_CALLER_PC(); \
64 const uptr pc = StackTrace::GetCurrentPc(); \
66 ScopedJavaFunc scoped(thr, caller_pc); \
69 void __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);
73 CHECK_GT(heap_begin, 0);
74 CHECK_GT(heap_size, 0);
75 CHECK_EQ(heap_begin % kHeapAlignment, 0);
76 CHECK_EQ(heap_size % kHeapAlignment, 0);
77 CHECK_LT(heap_begin, heap_begin + heap_size);
78 jctx = new(jctx_buf) JavaContext(heap_begin, heap_size);
81 int __tsan_java_fini() {
82 SCOPED_JAVA_FUNC(__tsan_java_fini);
83 DPrintf("#%d: java_fini()\n", thr->tid);
85 // FIXME(dvyukov): this does not call atexit() callbacks.
86 int status = Finalize(thr);
87 DPrintf("#%d: java_fini() = %d\n", thr->tid, status);
91 void __tsan_java_alloc(jptr ptr, jptr size) {
92 SCOPED_JAVA_FUNC(__tsan_java_alloc);
93 DPrintf("#%d: java_alloc(%p, %p)\n", thr->tid, ptr, size);
96 CHECK_EQ(ptr % kHeapAlignment, 0);
97 CHECK_EQ(size % kHeapAlignment, 0);
98 CHECK_GE(ptr, jctx->heap_begin);
99 CHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
101 OnUserAlloc(thr, pc, ptr, size, false);
104 void __tsan_java_free(jptr ptr, jptr size) {
105 SCOPED_JAVA_FUNC(__tsan_java_free);
106 DPrintf("#%d: java_free(%p, %p)\n", thr->tid, ptr, size);
109 CHECK_EQ(ptr % kHeapAlignment, 0);
110 CHECK_EQ(size % kHeapAlignment, 0);
111 CHECK_GE(ptr, jctx->heap_begin);
112 CHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
114 ctx->metamap.FreeRange(thr->proc(), ptr, size);
117 void __tsan_java_move(jptr src, jptr dst, jptr size) {
118 SCOPED_JAVA_FUNC(__tsan_java_move);
119 DPrintf("#%d: java_move(%p, %p, %p)\n", thr->tid, src, dst, size);
122 CHECK_EQ(src % kHeapAlignment, 0);
123 CHECK_EQ(dst % kHeapAlignment, 0);
124 CHECK_EQ(size % kHeapAlignment, 0);
125 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);
132 // Assuming it's not running concurrently with threads that do
133 // memory accesses and mutex operations (stop-the-world phase).
134 ctx->metamap.MoveMemory(src, dst, size);
137 u64 *s = (u64*)MemToShadow(src);
138 u64 *d = (u64*)MemToShadow(dst);
139 u64 *send = (u64*)MemToShadow(src + size);
142 s = (u64*)MemToShadow(src + size) - 1;
143 d = (u64*)MemToShadow(dst + size) - 1;
144 send = (u64*)MemToShadow(src) - 1;
147 for (; s != send; s += inc, d += inc) {
153 jptr __tsan_java_find(jptr *from_ptr, jptr to) {
154 SCOPED_JAVA_FUNC(__tsan_java_find);
155 DPrintf("#%d: java_find(&%p, %p)\n", *from_ptr, to);
156 CHECK_EQ((*from_ptr) % kHeapAlignment, 0);
157 CHECK_EQ(to % kHeapAlignment, 0);
158 CHECK_GE(*from_ptr, jctx->heap_begin);
159 CHECK_LE(to, jctx->heap_begin + jctx->heap_size);
160 for (uptr from = *from_ptr; from < to; from += kHeapAlignment) {
161 MBlock *b = ctx->metamap.GetBlock(from);
170 void __tsan_java_finalize() {
171 SCOPED_JAVA_FUNC(__tsan_java_finalize);
172 DPrintf("#%d: java_mutex_finalize()\n", thr->tid);
173 AcquireGlobal(thr, 0);
176 void __tsan_java_mutex_lock(jptr addr) {
177 SCOPED_JAVA_FUNC(__tsan_java_mutex_lock);
178 DPrintf("#%d: java_mutex_lock(%p)\n", thr->tid, addr);
180 CHECK_GE(addr, jctx->heap_begin);
181 CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
183 MutexCreate(thr, pc, addr, true, true, true);
184 MutexLock(thr, pc, addr);
187 void __tsan_java_mutex_unlock(jptr addr) {
188 SCOPED_JAVA_FUNC(__tsan_java_mutex_unlock);
189 DPrintf("#%d: java_mutex_unlock(%p)\n", thr->tid, addr);
191 CHECK_GE(addr, jctx->heap_begin);
192 CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
194 MutexUnlock(thr, pc, addr);
197 void __tsan_java_mutex_read_lock(jptr addr) {
198 SCOPED_JAVA_FUNC(__tsan_java_mutex_read_lock);
199 DPrintf("#%d: java_mutex_read_lock(%p)\n", thr->tid, addr);
201 CHECK_GE(addr, jctx->heap_begin);
202 CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
204 MutexCreate(thr, pc, addr, true, true, true);
205 MutexReadLock(thr, pc, addr);
208 void __tsan_java_mutex_read_unlock(jptr addr) {
209 SCOPED_JAVA_FUNC(__tsan_java_mutex_read_unlock);
210 DPrintf("#%d: java_mutex_read_unlock(%p)\n", thr->tid, addr);
212 CHECK_GE(addr, jctx->heap_begin);
213 CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
215 MutexReadUnlock(thr, pc, addr);
218 void __tsan_java_mutex_lock_rec(jptr addr, int rec) {
219 SCOPED_JAVA_FUNC(__tsan_java_mutex_lock_rec);
220 DPrintf("#%d: java_mutex_lock_rec(%p, %d)\n", thr->tid, addr, rec);
222 CHECK_GE(addr, jctx->heap_begin);
223 CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
226 MutexCreate(thr, pc, addr, true, true, true);
227 MutexLock(thr, pc, addr, rec);
230 int __tsan_java_mutex_unlock_rec(jptr addr) {
231 SCOPED_JAVA_FUNC(__tsan_java_mutex_unlock_rec);
232 DPrintf("#%d: java_mutex_unlock_rec(%p)\n", thr->tid, addr);
234 CHECK_GE(addr, jctx->heap_begin);
235 CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
237 return MutexUnlock(thr, pc, addr, true);
240 void __tsan_java_acquire(jptr addr) {
241 SCOPED_JAVA_FUNC(__tsan_java_acquire);
242 DPrintf("#%d: java_acquire(%p)\n", thr->tid, addr);
244 CHECK_GE(addr, jctx->heap_begin);
245 CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
247 Acquire(thr, caller_pc, addr);
250 void __tsan_java_release(jptr addr) {
251 SCOPED_JAVA_FUNC(__tsan_java_release);
252 DPrintf("#%d: java_release(%p)\n", thr->tid, addr);
254 CHECK_GE(addr, jctx->heap_begin);
255 CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
257 Release(thr, caller_pc, addr);
260 void __tsan_java_release_store(jptr addr) {
261 SCOPED_JAVA_FUNC(__tsan_java_release);
262 DPrintf("#%d: java_release_store(%p)\n", thr->tid, addr);
264 CHECK_GE(addr, jctx->heap_begin);
265 CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
267 ReleaseStore(thr, caller_pc, addr);