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 void __tsan_java_finalize() {
152 SCOPED_JAVA_FUNC(__tsan_java_finalize
);
153 DPrintf("#%d: java_mutex_finalize()\n", thr
->tid
);
154 AcquireGlobal(thr
, 0);
157 void __tsan_java_mutex_lock(jptr addr
) {
158 SCOPED_JAVA_FUNC(__tsan_java_mutex_lock
);
159 DPrintf("#%d: java_mutex_lock(%p)\n", thr
->tid
, addr
);
161 CHECK_GE(addr
, jctx
->heap_begin
);
162 CHECK_LT(addr
, jctx
->heap_begin
+ jctx
->heap_size
);
164 MutexCreate(thr
, pc
, addr
, true, true, true);
165 MutexLock(thr
, pc
, addr
);
168 void __tsan_java_mutex_unlock(jptr addr
) {
169 SCOPED_JAVA_FUNC(__tsan_java_mutex_unlock
);
170 DPrintf("#%d: java_mutex_unlock(%p)\n", thr
->tid
, addr
);
172 CHECK_GE(addr
, jctx
->heap_begin
);
173 CHECK_LT(addr
, jctx
->heap_begin
+ jctx
->heap_size
);
175 MutexUnlock(thr
, pc
, addr
);
178 void __tsan_java_mutex_read_lock(jptr addr
) {
179 SCOPED_JAVA_FUNC(__tsan_java_mutex_read_lock
);
180 DPrintf("#%d: java_mutex_read_lock(%p)\n", thr
->tid
, addr
);
182 CHECK_GE(addr
, jctx
->heap_begin
);
183 CHECK_LT(addr
, jctx
->heap_begin
+ jctx
->heap_size
);
185 MutexCreate(thr
, pc
, addr
, true, true, true);
186 MutexReadLock(thr
, pc
, addr
);
189 void __tsan_java_mutex_read_unlock(jptr addr
) {
190 SCOPED_JAVA_FUNC(__tsan_java_mutex_read_unlock
);
191 DPrintf("#%d: java_mutex_read_unlock(%p)\n", thr
->tid
, addr
);
193 CHECK_GE(addr
, jctx
->heap_begin
);
194 CHECK_LT(addr
, jctx
->heap_begin
+ jctx
->heap_size
);
196 MutexReadUnlock(thr
, pc
, addr
);
199 void __tsan_java_mutex_lock_rec(jptr addr
, int rec
) {
200 SCOPED_JAVA_FUNC(__tsan_java_mutex_lock_rec
);
201 DPrintf("#%d: java_mutex_lock_rec(%p, %d)\n", thr
->tid
, addr
, rec
);
203 CHECK_GE(addr
, jctx
->heap_begin
);
204 CHECK_LT(addr
, jctx
->heap_begin
+ jctx
->heap_size
);
207 MutexCreate(thr
, pc
, addr
, true, true, true);
208 MutexLock(thr
, pc
, addr
, rec
);
211 int __tsan_java_mutex_unlock_rec(jptr addr
) {
212 SCOPED_JAVA_FUNC(__tsan_java_mutex_unlock_rec
);
213 DPrintf("#%d: java_mutex_unlock_rec(%p)\n", thr
->tid
, addr
);
215 CHECK_GE(addr
, jctx
->heap_begin
);
216 CHECK_LT(addr
, jctx
->heap_begin
+ jctx
->heap_size
);
218 return MutexUnlock(thr
, pc
, addr
, true);
221 void __tsan_java_acquire(jptr addr
) {
222 SCOPED_JAVA_FUNC(__tsan_java_acquire
);
223 DPrintf("#%d: java_acquire(%p)\n", thr
->tid
, addr
);
225 CHECK_GE(addr
, jctx
->heap_begin
);
226 CHECK_LT(addr
, jctx
->heap_begin
+ jctx
->heap_size
);
228 Acquire(thr
, caller_pc
, addr
);
231 void __tsan_java_release(jptr addr
) {
232 SCOPED_JAVA_FUNC(__tsan_java_release
);
233 DPrintf("#%d: java_release(%p)\n", thr
->tid
, addr
);
235 CHECK_GE(addr
, jctx
->heap_begin
);
236 CHECK_LT(addr
, jctx
->heap_begin
+ jctx
->heap_size
);
238 Release(thr
, caller_pc
, addr
);
241 void __tsan_java_release_store(jptr addr
) {
242 SCOPED_JAVA_FUNC(__tsan_java_release
);
243 DPrintf("#%d: java_release_store(%p)\n", thr
->tid
, addr
);
245 CHECK_GE(addr
, jctx
->heap_begin
);
246 CHECK_LT(addr
, jctx
->heap_begin
+ jctx
->heap_size
);
248 ReleaseStore(thr
, caller_pc
, addr
);