1 //===-- tsan_interface_java.cc --------------------------------------------===//
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
6 //===----------------------------------------------------------------------===//
8 // This file is a part of ThreadSanitizer (TSan), a race detector.
10 //===----------------------------------------------------------------------===//
12 #include "tsan_interface_java.h"
14 #include "tsan_mutex.h"
15 #include "sanitizer_common/sanitizer_internal_defs.h"
16 #include "sanitizer_common/sanitizer_common.h"
17 #include "sanitizer_common/sanitizer_placement_new.h"
18 #include "sanitizer_common/sanitizer_stacktrace.h"
19 #include "sanitizer_common/sanitizer_procmaps.h"
21 using namespace __tsan
; // NOLINT
23 const jptr kHeapAlignment
= 8;
28 const uptr heap_begin
;
31 JavaContext(jptr heap_begin
, jptr heap_size
)
32 : heap_begin(heap_begin
)
33 , heap_size(heap_size
) {
37 class ScopedJavaFunc
{
39 ScopedJavaFunc(ThreadState
*thr
, uptr pc
)
47 // FIXME(dvyukov): process pending signals.
54 static u64 jctx_buf
[sizeof(JavaContext
) / sizeof(u64
) + 1];
55 static JavaContext
*jctx
;
59 #define SCOPED_JAVA_FUNC(func) \
60 ThreadState *thr = cur_thread(); \
61 const uptr caller_pc = GET_CALLER_PC(); \
62 const uptr pc = StackTrace::GetCurrentPc(); \
64 ScopedJavaFunc scoped(thr, caller_pc); \
67 void __tsan_java_init(jptr heap_begin
, jptr heap_size
) {
68 SCOPED_JAVA_FUNC(__tsan_java_init
);
69 DPrintf("#%d: java_init(%p, %p)\n", thr
->tid
, heap_begin
, heap_size
);
71 CHECK_GT(heap_begin
, 0);
72 CHECK_GT(heap_size
, 0);
73 CHECK_EQ(heap_begin
% kHeapAlignment
, 0);
74 CHECK_EQ(heap_size
% kHeapAlignment
, 0);
75 CHECK_LT(heap_begin
, heap_begin
+ heap_size
);
76 jctx
= new(jctx_buf
) JavaContext(heap_begin
, heap_size
);
79 int __tsan_java_fini() {
80 SCOPED_JAVA_FUNC(__tsan_java_fini
);
81 DPrintf("#%d: java_fini()\n", thr
->tid
);
83 // FIXME(dvyukov): this does not call atexit() callbacks.
84 int status
= Finalize(thr
);
85 DPrintf("#%d: java_fini() = %d\n", thr
->tid
, status
);
89 void __tsan_java_alloc(jptr ptr
, jptr size
) {
90 SCOPED_JAVA_FUNC(__tsan_java_alloc
);
91 DPrintf("#%d: java_alloc(%p, %p)\n", thr
->tid
, ptr
, size
);
94 CHECK_EQ(ptr
% kHeapAlignment
, 0);
95 CHECK_EQ(size
% kHeapAlignment
, 0);
96 CHECK_GE(ptr
, jctx
->heap_begin
);
97 CHECK_LE(ptr
+ size
, jctx
->heap_begin
+ jctx
->heap_size
);
99 OnUserAlloc(thr
, pc
, ptr
, size
, false);
102 void __tsan_java_free(jptr ptr
, jptr size
) {
103 SCOPED_JAVA_FUNC(__tsan_java_free
);
104 DPrintf("#%d: java_free(%p, %p)\n", thr
->tid
, ptr
, size
);
107 CHECK_EQ(ptr
% kHeapAlignment
, 0);
108 CHECK_EQ(size
% kHeapAlignment
, 0);
109 CHECK_GE(ptr
, jctx
->heap_begin
);
110 CHECK_LE(ptr
+ size
, jctx
->heap_begin
+ jctx
->heap_size
);
112 ctx
->metamap
.FreeRange(thr
->proc(), ptr
, size
);
115 void __tsan_java_move(jptr src
, jptr dst
, jptr size
) {
116 SCOPED_JAVA_FUNC(__tsan_java_move
);
117 DPrintf("#%d: java_move(%p, %p, %p)\n", thr
->tid
, src
, dst
, size
);
120 CHECK_EQ(src
% kHeapAlignment
, 0);
121 CHECK_EQ(dst
% kHeapAlignment
, 0);
122 CHECK_EQ(size
% kHeapAlignment
, 0);
123 CHECK_GE(src
, jctx
->heap_begin
);
124 CHECK_LE(src
+ size
, jctx
->heap_begin
+ jctx
->heap_size
);
125 CHECK_GE(dst
, jctx
->heap_begin
);
126 CHECK_LE(dst
+ size
, jctx
->heap_begin
+ jctx
->heap_size
);
130 // Assuming it's not running concurrently with threads that do
131 // memory accesses and mutex operations (stop-the-world phase).
132 ctx
->metamap
.MoveMemory(src
, dst
, size
);
135 u64
*s
= (u64
*)MemToShadow(src
);
136 u64
*d
= (u64
*)MemToShadow(dst
);
137 u64
*send
= (u64
*)MemToShadow(src
+ size
);
140 s
= (u64
*)MemToShadow(src
+ size
) - 1;
141 d
= (u64
*)MemToShadow(dst
+ size
) - 1;
142 send
= (u64
*)MemToShadow(src
) - 1;
145 for (; s
!= send
; s
+= inc
, d
+= inc
) {
151 jptr
__tsan_java_find(jptr
*from_ptr
, jptr to
) {
152 SCOPED_JAVA_FUNC(__tsan_java_find
);
153 DPrintf("#%d: java_find(&%p, %p)\n", *from_ptr
, to
);
154 CHECK_EQ((*from_ptr
) % kHeapAlignment
, 0);
155 CHECK_EQ(to
% kHeapAlignment
, 0);
156 CHECK_GE(*from_ptr
, jctx
->heap_begin
);
157 CHECK_LE(to
, jctx
->heap_begin
+ jctx
->heap_size
);
158 for (uptr from
= *from_ptr
; from
< to
; from
+= kHeapAlignment
) {
159 MBlock
*b
= ctx
->metamap
.GetBlock(from
);
168 void __tsan_java_finalize() {
169 SCOPED_JAVA_FUNC(__tsan_java_finalize
);
170 DPrintf("#%d: java_mutex_finalize()\n", thr
->tid
);
171 AcquireGlobal(thr
, 0);
174 void __tsan_java_mutex_lock(jptr addr
) {
175 SCOPED_JAVA_FUNC(__tsan_java_mutex_lock
);
176 DPrintf("#%d: java_mutex_lock(%p)\n", thr
->tid
, addr
);
178 CHECK_GE(addr
, jctx
->heap_begin
);
179 CHECK_LT(addr
, jctx
->heap_begin
+ jctx
->heap_size
);
181 MutexPostLock(thr
, pc
, addr
, MutexFlagLinkerInit
| MutexFlagWriteReentrant
|
182 MutexFlagDoPreLockOnPostLock
);
185 void __tsan_java_mutex_unlock(jptr addr
) {
186 SCOPED_JAVA_FUNC(__tsan_java_mutex_unlock
);
187 DPrintf("#%d: java_mutex_unlock(%p)\n", thr
->tid
, addr
);
189 CHECK_GE(addr
, jctx
->heap_begin
);
190 CHECK_LT(addr
, jctx
->heap_begin
+ jctx
->heap_size
);
192 MutexUnlock(thr
, pc
, addr
);
195 void __tsan_java_mutex_read_lock(jptr addr
) {
196 SCOPED_JAVA_FUNC(__tsan_java_mutex_read_lock
);
197 DPrintf("#%d: java_mutex_read_lock(%p)\n", thr
->tid
, addr
);
199 CHECK_GE(addr
, jctx
->heap_begin
);
200 CHECK_LT(addr
, jctx
->heap_begin
+ jctx
->heap_size
);
202 MutexPostReadLock(thr
, pc
, addr
, MutexFlagLinkerInit
|
203 MutexFlagWriteReentrant
| MutexFlagDoPreLockOnPostLock
);
206 void __tsan_java_mutex_read_unlock(jptr addr
) {
207 SCOPED_JAVA_FUNC(__tsan_java_mutex_read_unlock
);
208 DPrintf("#%d: java_mutex_read_unlock(%p)\n", thr
->tid
, addr
);
210 CHECK_GE(addr
, jctx
->heap_begin
);
211 CHECK_LT(addr
, jctx
->heap_begin
+ jctx
->heap_size
);
213 MutexReadUnlock(thr
, pc
, addr
);
216 void __tsan_java_mutex_lock_rec(jptr addr
, int rec
) {
217 SCOPED_JAVA_FUNC(__tsan_java_mutex_lock_rec
);
218 DPrintf("#%d: java_mutex_lock_rec(%p, %d)\n", thr
->tid
, addr
, rec
);
220 CHECK_GE(addr
, jctx
->heap_begin
);
221 CHECK_LT(addr
, jctx
->heap_begin
+ jctx
->heap_size
);
224 MutexPostLock(thr
, pc
, addr
, MutexFlagLinkerInit
| MutexFlagWriteReentrant
|
225 MutexFlagDoPreLockOnPostLock
| MutexFlagRecursiveLock
, rec
);
228 int __tsan_java_mutex_unlock_rec(jptr addr
) {
229 SCOPED_JAVA_FUNC(__tsan_java_mutex_unlock_rec
);
230 DPrintf("#%d: java_mutex_unlock_rec(%p)\n", thr
->tid
, addr
);
232 CHECK_GE(addr
, jctx
->heap_begin
);
233 CHECK_LT(addr
, jctx
->heap_begin
+ jctx
->heap_size
);
235 return MutexUnlock(thr
, pc
, addr
, MutexFlagRecursiveUnlock
);
238 void __tsan_java_acquire(jptr addr
) {
239 SCOPED_JAVA_FUNC(__tsan_java_acquire
);
240 DPrintf("#%d: java_acquire(%p)\n", thr
->tid
, addr
);
242 CHECK_GE(addr
, jctx
->heap_begin
);
243 CHECK_LT(addr
, jctx
->heap_begin
+ jctx
->heap_size
);
245 Acquire(thr
, caller_pc
, addr
);
248 void __tsan_java_release(jptr addr
) {
249 SCOPED_JAVA_FUNC(__tsan_java_release
);
250 DPrintf("#%d: java_release(%p)\n", thr
->tid
, addr
);
252 CHECK_GE(addr
, jctx
->heap_begin
);
253 CHECK_LT(addr
, jctx
->heap_begin
+ jctx
->heap_size
);
255 Release(thr
, caller_pc
, addr
);
258 void __tsan_java_release_store(jptr addr
) {
259 SCOPED_JAVA_FUNC(__tsan_java_release
);
260 DPrintf("#%d: java_release_store(%p)\n", thr
->tid
, addr
);
262 CHECK_GE(addr
, jctx
->heap_begin
);
263 CHECK_LT(addr
, jctx
->heap_begin
+ jctx
->heap_size
);
265 ReleaseStore(thr
, caller_pc
, addr
);