2018-01-30 Thomas Koenig <tkoenig@gcc.gnu.org>
[official-gcc.git] / libsanitizer / tsan / tsan_interface_java.cc
blobd3f35a9bc82306342bdd4f46da628fc1aa1bbf3d
1 //===-- tsan_interface_java.cc --------------------------------------------===//
2 //
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // This file is a part of ThreadSanitizer (TSan), a race detector.
9 //
10 //===----------------------------------------------------------------------===//
12 #include "tsan_interface_java.h"
13 #include "tsan_rtl.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;
25 namespace __tsan {
27 struct JavaContext {
28 const uptr heap_begin;
29 const uptr heap_size;
31 JavaContext(jptr heap_begin, jptr heap_size)
32 : heap_begin(heap_begin)
33 , heap_size(heap_size) {
37 class ScopedJavaFunc {
38 public:
39 ScopedJavaFunc(ThreadState *thr, uptr pc)
40 : thr_(thr) {
41 Initialize(thr_);
42 FuncEntry(thr, pc);
45 ~ScopedJavaFunc() {
46 FuncExit(thr_);
47 // FIXME(dvyukov): process pending signals.
50 private:
51 ThreadState *thr_;
54 static u64 jctx_buf[sizeof(JavaContext) / sizeof(u64) + 1];
55 static JavaContext *jctx;
57 } // namespace __tsan
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(); \
63 (void)pc; \
64 ScopedJavaFunc scoped(thr, caller_pc); \
65 /**/
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);
70 CHECK_EQ(jctx, 0);
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);
82 CHECK_NE(jctx, 0);
83 // FIXME(dvyukov): this does not call atexit() callbacks.
84 int status = Finalize(thr);
85 DPrintf("#%d: java_fini() = %d\n", thr->tid, status);
86 return 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);
92 CHECK_NE(jctx, 0);
93 CHECK_NE(size, 0);
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);
105 CHECK_NE(jctx, 0);
106 CHECK_NE(size, 0);
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);
118 CHECK_NE(jctx, 0);
119 CHECK_NE(size, 0);
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);
127 CHECK_NE(dst, src);
128 CHECK_NE(size, 0);
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);
134 // Move shadow.
135 u64 *s = (u64*)MemToShadow(src);
136 u64 *d = (u64*)MemToShadow(dst);
137 u64 *send = (u64*)MemToShadow(src + size);
138 uptr inc = 1;
139 if (dst > src) {
140 s = (u64*)MemToShadow(src + size) - 1;
141 d = (u64*)MemToShadow(dst + size) - 1;
142 send = (u64*)MemToShadow(src) - 1;
143 inc = -1;
145 for (; s != send; s += inc, d += inc) {
146 *d = *s;
147 *s = 0;
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);
160 if (b) {
161 *from_ptr = from;
162 return b->siz;
165 return 0;
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);
177 CHECK_NE(jctx, 0);
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);
188 CHECK_NE(jctx, 0);
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);
198 CHECK_NE(jctx, 0);
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);
209 CHECK_NE(jctx, 0);
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);
219 CHECK_NE(jctx, 0);
220 CHECK_GE(addr, jctx->heap_begin);
221 CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
222 CHECK_GT(rec, 0);
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);
231 CHECK_NE(jctx, 0);
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);
241 CHECK_NE(jctx, 0);
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);
251 CHECK_NE(jctx, 0);
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);
261 CHECK_NE(jctx, 0);
262 CHECK_GE(addr, jctx->heap_begin);
263 CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
265 ReleaseStore(thr, caller_pc, addr);