xref: /freebsd-src/contrib/llvm-project/compiler-rt/lib/tsan/rtl/tsan_interface_java.cpp (revision 0eae32dcef82f6f06de6419a0d623d7def0cc8f6)
168d75effSDimitry Andric //===-- tsan_interface_java.cpp -------------------------------------------===//
268d75effSDimitry Andric //
368d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
468d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
568d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
668d75effSDimitry Andric //
768d75effSDimitry Andric //===----------------------------------------------------------------------===//
868d75effSDimitry Andric //
968d75effSDimitry Andric // This file is a part of ThreadSanitizer (TSan), a race detector.
1068d75effSDimitry Andric //
1168d75effSDimitry Andric //===----------------------------------------------------------------------===//
1268d75effSDimitry Andric 
1368d75effSDimitry Andric #include "tsan_interface_java.h"
1468d75effSDimitry Andric #include "tsan_rtl.h"
1568d75effSDimitry Andric #include "sanitizer_common/sanitizer_internal_defs.h"
1668d75effSDimitry Andric #include "sanitizer_common/sanitizer_common.h"
1768d75effSDimitry Andric #include "sanitizer_common/sanitizer_placement_new.h"
1868d75effSDimitry Andric #include "sanitizer_common/sanitizer_stacktrace.h"
1968d75effSDimitry Andric #include "sanitizer_common/sanitizer_procmaps.h"
2068d75effSDimitry Andric 
2168d75effSDimitry Andric using namespace __tsan;
2268d75effSDimitry Andric 
2368d75effSDimitry Andric const jptr kHeapAlignment = 8;
2468d75effSDimitry Andric 
2568d75effSDimitry Andric namespace __tsan {
2668d75effSDimitry Andric 
2768d75effSDimitry Andric struct JavaContext {
2868d75effSDimitry Andric   const uptr heap_begin;
2968d75effSDimitry Andric   const uptr heap_size;
3068d75effSDimitry Andric 
JavaContext__tsan::JavaContext3168d75effSDimitry Andric   JavaContext(jptr heap_begin, jptr heap_size)
3268d75effSDimitry Andric       : heap_begin(heap_begin)
3368d75effSDimitry Andric       , heap_size(heap_size) {
3468d75effSDimitry Andric   }
3568d75effSDimitry Andric };
3668d75effSDimitry Andric 
3768d75effSDimitry Andric static u64 jctx_buf[sizeof(JavaContext) / sizeof(u64) + 1];
3868d75effSDimitry Andric static JavaContext *jctx;
3968d75effSDimitry Andric 
JavaHeapBlock(uptr addr,uptr * start)40349cc55cSDimitry Andric MBlock *JavaHeapBlock(uptr addr, uptr *start) {
41349cc55cSDimitry Andric   if (!jctx || addr < jctx->heap_begin ||
42349cc55cSDimitry Andric       addr >= jctx->heap_begin + jctx->heap_size)
43349cc55cSDimitry Andric     return nullptr;
44349cc55cSDimitry Andric   for (uptr p = RoundDown(addr, kMetaShadowCell); p >= jctx->heap_begin;
45349cc55cSDimitry Andric        p -= kMetaShadowCell) {
46349cc55cSDimitry Andric     MBlock *b = ctx->metamap.GetBlock(p);
47349cc55cSDimitry Andric     if (!b)
48349cc55cSDimitry Andric       continue;
49349cc55cSDimitry Andric     if (p + b->siz <= addr)
50349cc55cSDimitry Andric       return nullptr;
51349cc55cSDimitry Andric     *start = p;
52349cc55cSDimitry Andric     return b;
53349cc55cSDimitry Andric   }
54349cc55cSDimitry Andric   return nullptr;
55349cc55cSDimitry Andric }
56349cc55cSDimitry Andric 
5768d75effSDimitry Andric }  // namespace __tsan
5868d75effSDimitry Andric 
59349cc55cSDimitry Andric #define JAVA_FUNC_ENTER(func)      \
6068d75effSDimitry Andric   ThreadState *thr = cur_thread(); \
61349cc55cSDimitry Andric   (void)thr;
6268d75effSDimitry Andric 
__tsan_java_init(jptr heap_begin,jptr heap_size)6368d75effSDimitry Andric void __tsan_java_init(jptr heap_begin, jptr heap_size) {
64349cc55cSDimitry Andric   JAVA_FUNC_ENTER(__tsan_java_init);
65349cc55cSDimitry Andric   Initialize(thr);
66349cc55cSDimitry Andric   DPrintf("#%d: java_init(0x%zx, 0x%zx)\n", thr->tid, heap_begin, heap_size);
67349cc55cSDimitry Andric   DCHECK_EQ(jctx, 0);
68349cc55cSDimitry Andric   DCHECK_GT(heap_begin, 0);
69349cc55cSDimitry Andric   DCHECK_GT(heap_size, 0);
70349cc55cSDimitry Andric   DCHECK_EQ(heap_begin % kHeapAlignment, 0);
71349cc55cSDimitry Andric   DCHECK_EQ(heap_size % kHeapAlignment, 0);
72349cc55cSDimitry Andric   DCHECK_LT(heap_begin, heap_begin + heap_size);
7368d75effSDimitry Andric   jctx = new(jctx_buf) JavaContext(heap_begin, heap_size);
7468d75effSDimitry Andric }
7568d75effSDimitry Andric 
__tsan_java_fini()7668d75effSDimitry Andric int  __tsan_java_fini() {
77349cc55cSDimitry Andric   JAVA_FUNC_ENTER(__tsan_java_fini);
7868d75effSDimitry Andric   DPrintf("#%d: java_fini()\n", thr->tid);
79349cc55cSDimitry Andric   DCHECK_NE(jctx, 0);
8068d75effSDimitry Andric   // FIXME(dvyukov): this does not call atexit() callbacks.
8168d75effSDimitry Andric   int status = Finalize(thr);
8268d75effSDimitry Andric   DPrintf("#%d: java_fini() = %d\n", thr->tid, status);
8368d75effSDimitry Andric   return status;
8468d75effSDimitry Andric }
8568d75effSDimitry Andric 
__tsan_java_alloc(jptr ptr,jptr size)8668d75effSDimitry Andric void __tsan_java_alloc(jptr ptr, jptr size) {
87349cc55cSDimitry Andric   JAVA_FUNC_ENTER(__tsan_java_alloc);
88349cc55cSDimitry Andric   DPrintf("#%d: java_alloc(0x%zx, 0x%zx)\n", thr->tid, ptr, size);
89349cc55cSDimitry Andric   DCHECK_NE(jctx, 0);
90349cc55cSDimitry Andric   DCHECK_NE(size, 0);
91349cc55cSDimitry Andric   DCHECK_EQ(ptr % kHeapAlignment, 0);
92349cc55cSDimitry Andric   DCHECK_EQ(size % kHeapAlignment, 0);
93349cc55cSDimitry Andric   DCHECK_GE(ptr, jctx->heap_begin);
94349cc55cSDimitry Andric   DCHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
9568d75effSDimitry Andric 
96349cc55cSDimitry Andric   OnUserAlloc(thr, 0, ptr, size, false);
9768d75effSDimitry Andric }
9868d75effSDimitry Andric 
__tsan_java_free(jptr ptr,jptr size)9968d75effSDimitry Andric void __tsan_java_free(jptr ptr, jptr size) {
100349cc55cSDimitry Andric   JAVA_FUNC_ENTER(__tsan_java_free);
101349cc55cSDimitry Andric   DPrintf("#%d: java_free(0x%zx, 0x%zx)\n", thr->tid, ptr, size);
102349cc55cSDimitry Andric   DCHECK_NE(jctx, 0);
103349cc55cSDimitry Andric   DCHECK_NE(size, 0);
104349cc55cSDimitry Andric   DCHECK_EQ(ptr % kHeapAlignment, 0);
105349cc55cSDimitry Andric   DCHECK_EQ(size % kHeapAlignment, 0);
106349cc55cSDimitry Andric   DCHECK_GE(ptr, jctx->heap_begin);
107349cc55cSDimitry Andric   DCHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
10868d75effSDimitry Andric 
109*0eae32dcSDimitry Andric   ctx->metamap.FreeRange(thr->proc(), ptr, size, false);
11068d75effSDimitry Andric }
11168d75effSDimitry Andric 
__tsan_java_move(jptr src,jptr dst,jptr size)11268d75effSDimitry Andric void __tsan_java_move(jptr src, jptr dst, jptr size) {
113349cc55cSDimitry Andric   JAVA_FUNC_ENTER(__tsan_java_move);
114349cc55cSDimitry Andric   DPrintf("#%d: java_move(0x%zx, 0x%zx, 0x%zx)\n", thr->tid, src, dst, size);
115349cc55cSDimitry Andric   DCHECK_NE(jctx, 0);
116349cc55cSDimitry Andric   DCHECK_NE(size, 0);
117349cc55cSDimitry Andric   DCHECK_EQ(src % kHeapAlignment, 0);
118349cc55cSDimitry Andric   DCHECK_EQ(dst % kHeapAlignment, 0);
119349cc55cSDimitry Andric   DCHECK_EQ(size % kHeapAlignment, 0);
120349cc55cSDimitry Andric   DCHECK_GE(src, jctx->heap_begin);
121349cc55cSDimitry Andric   DCHECK_LE(src + size, jctx->heap_begin + jctx->heap_size);
122349cc55cSDimitry Andric   DCHECK_GE(dst, jctx->heap_begin);
123349cc55cSDimitry Andric   DCHECK_LE(dst + size, jctx->heap_begin + jctx->heap_size);
124349cc55cSDimitry Andric   DCHECK_NE(dst, src);
125349cc55cSDimitry Andric   DCHECK_NE(size, 0);
12668d75effSDimitry Andric 
12768d75effSDimitry Andric   // Assuming it's not running concurrently with threads that do
12868d75effSDimitry Andric   // memory accesses and mutex operations (stop-the-world phase).
12968d75effSDimitry Andric   ctx->metamap.MoveMemory(src, dst, size);
13068d75effSDimitry Andric 
131349cc55cSDimitry Andric   // Clear the destination shadow range.
132349cc55cSDimitry Andric   // We used to move shadow from src to dst, but the trace format does not
133349cc55cSDimitry Andric   // support that anymore as it contains addresses of accesses.
134349cc55cSDimitry Andric   RawShadow *d = MemToShadow(dst);
135349cc55cSDimitry Andric   RawShadow *dend = MemToShadow(dst + size);
136*0eae32dcSDimitry Andric   ShadowSet(d, dend, Shadow::kEmpty);
13768d75effSDimitry Andric }
13868d75effSDimitry Andric 
__tsan_java_find(jptr * from_ptr,jptr to)13968d75effSDimitry Andric jptr __tsan_java_find(jptr *from_ptr, jptr to) {
140349cc55cSDimitry Andric   JAVA_FUNC_ENTER(__tsan_java_find);
141349cc55cSDimitry Andric   DPrintf("#%d: java_find(&0x%zx, 0x%zx)\n", thr->tid, *from_ptr, to);
142349cc55cSDimitry Andric   DCHECK_EQ((*from_ptr) % kHeapAlignment, 0);
143349cc55cSDimitry Andric   DCHECK_EQ(to % kHeapAlignment, 0);
144349cc55cSDimitry Andric   DCHECK_GE(*from_ptr, jctx->heap_begin);
145349cc55cSDimitry Andric   DCHECK_LE(to, jctx->heap_begin + jctx->heap_size);
14668d75effSDimitry Andric   for (uptr from = *from_ptr; from < to; from += kHeapAlignment) {
14768d75effSDimitry Andric     MBlock *b = ctx->metamap.GetBlock(from);
14868d75effSDimitry Andric     if (b) {
14968d75effSDimitry Andric       *from_ptr = from;
15068d75effSDimitry Andric       return b->siz;
15168d75effSDimitry Andric     }
15268d75effSDimitry Andric   }
15368d75effSDimitry Andric   return 0;
15468d75effSDimitry Andric }
15568d75effSDimitry Andric 
__tsan_java_finalize()15668d75effSDimitry Andric void __tsan_java_finalize() {
157349cc55cSDimitry Andric   JAVA_FUNC_ENTER(__tsan_java_finalize);
158349cc55cSDimitry Andric   DPrintf("#%d: java_finalize()\n", thr->tid);
159349cc55cSDimitry Andric   AcquireGlobal(thr);
16068d75effSDimitry Andric }
16168d75effSDimitry Andric 
__tsan_java_mutex_lock(jptr addr)16268d75effSDimitry Andric void __tsan_java_mutex_lock(jptr addr) {
163349cc55cSDimitry Andric   JAVA_FUNC_ENTER(__tsan_java_mutex_lock);
164349cc55cSDimitry Andric   DPrintf("#%d: java_mutex_lock(0x%zx)\n", thr->tid, addr);
165349cc55cSDimitry Andric   DCHECK_NE(jctx, 0);
166349cc55cSDimitry Andric   DCHECK_GE(addr, jctx->heap_begin);
167349cc55cSDimitry Andric   DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
16868d75effSDimitry Andric 
169349cc55cSDimitry Andric   MutexPostLock(thr, 0, addr,
170349cc55cSDimitry Andric                 MutexFlagLinkerInit | MutexFlagWriteReentrant |
17168d75effSDimitry Andric                     MutexFlagDoPreLockOnPostLock);
17268d75effSDimitry Andric }
17368d75effSDimitry Andric 
__tsan_java_mutex_unlock(jptr addr)17468d75effSDimitry Andric void __tsan_java_mutex_unlock(jptr addr) {
175349cc55cSDimitry Andric   JAVA_FUNC_ENTER(__tsan_java_mutex_unlock);
176349cc55cSDimitry Andric   DPrintf("#%d: java_mutex_unlock(0x%zx)\n", thr->tid, addr);
177349cc55cSDimitry Andric   DCHECK_NE(jctx, 0);
178349cc55cSDimitry Andric   DCHECK_GE(addr, jctx->heap_begin);
179349cc55cSDimitry Andric   DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
18068d75effSDimitry Andric 
181349cc55cSDimitry Andric   MutexUnlock(thr, 0, addr);
18268d75effSDimitry Andric }
18368d75effSDimitry Andric 
__tsan_java_mutex_read_lock(jptr addr)18468d75effSDimitry Andric void __tsan_java_mutex_read_lock(jptr addr) {
185349cc55cSDimitry Andric   JAVA_FUNC_ENTER(__tsan_java_mutex_read_lock);
186349cc55cSDimitry Andric   DPrintf("#%d: java_mutex_read_lock(0x%zx)\n", thr->tid, addr);
187349cc55cSDimitry Andric   DCHECK_NE(jctx, 0);
188349cc55cSDimitry Andric   DCHECK_GE(addr, jctx->heap_begin);
189349cc55cSDimitry Andric   DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
19068d75effSDimitry Andric 
191349cc55cSDimitry Andric   MutexPostReadLock(thr, 0, addr,
192349cc55cSDimitry Andric                     MutexFlagLinkerInit | MutexFlagWriteReentrant |
193349cc55cSDimitry Andric                         MutexFlagDoPreLockOnPostLock);
19468d75effSDimitry Andric }
19568d75effSDimitry Andric 
__tsan_java_mutex_read_unlock(jptr addr)19668d75effSDimitry Andric void __tsan_java_mutex_read_unlock(jptr addr) {
197349cc55cSDimitry Andric   JAVA_FUNC_ENTER(__tsan_java_mutex_read_unlock);
198349cc55cSDimitry Andric   DPrintf("#%d: java_mutex_read_unlock(0x%zx)\n", thr->tid, addr);
199349cc55cSDimitry Andric   DCHECK_NE(jctx, 0);
200349cc55cSDimitry Andric   DCHECK_GE(addr, jctx->heap_begin);
201349cc55cSDimitry Andric   DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
20268d75effSDimitry Andric 
203349cc55cSDimitry Andric   MutexReadUnlock(thr, 0, addr);
20468d75effSDimitry Andric }
20568d75effSDimitry Andric 
__tsan_java_mutex_lock_rec(jptr addr,int rec)20668d75effSDimitry Andric void __tsan_java_mutex_lock_rec(jptr addr, int rec) {
207349cc55cSDimitry Andric   JAVA_FUNC_ENTER(__tsan_java_mutex_lock_rec);
208349cc55cSDimitry Andric   DPrintf("#%d: java_mutex_lock_rec(0x%zx, %d)\n", thr->tid, addr, rec);
209349cc55cSDimitry Andric   DCHECK_NE(jctx, 0);
210349cc55cSDimitry Andric   DCHECK_GE(addr, jctx->heap_begin);
211349cc55cSDimitry Andric   DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
212349cc55cSDimitry Andric   DCHECK_GT(rec, 0);
21368d75effSDimitry Andric 
214349cc55cSDimitry Andric   MutexPostLock(thr, 0, addr,
215349cc55cSDimitry Andric                 MutexFlagLinkerInit | MutexFlagWriteReentrant |
216349cc55cSDimitry Andric                     MutexFlagDoPreLockOnPostLock | MutexFlagRecursiveLock,
217349cc55cSDimitry Andric                 rec);
21868d75effSDimitry Andric }
21968d75effSDimitry Andric 
__tsan_java_mutex_unlock_rec(jptr addr)22068d75effSDimitry Andric int __tsan_java_mutex_unlock_rec(jptr addr) {
221349cc55cSDimitry Andric   JAVA_FUNC_ENTER(__tsan_java_mutex_unlock_rec);
222349cc55cSDimitry Andric   DPrintf("#%d: java_mutex_unlock_rec(0x%zx)\n", thr->tid, addr);
223349cc55cSDimitry Andric   DCHECK_NE(jctx, 0);
224349cc55cSDimitry Andric   DCHECK_GE(addr, jctx->heap_begin);
225349cc55cSDimitry Andric   DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
22668d75effSDimitry Andric 
227349cc55cSDimitry Andric   return MutexUnlock(thr, 0, addr, MutexFlagRecursiveUnlock);
22868d75effSDimitry Andric }
22968d75effSDimitry Andric 
__tsan_java_acquire(jptr addr)23068d75effSDimitry Andric void __tsan_java_acquire(jptr addr) {
231349cc55cSDimitry Andric   JAVA_FUNC_ENTER(__tsan_java_acquire);
232349cc55cSDimitry Andric   DPrintf("#%d: java_acquire(0x%zx)\n", thr->tid, addr);
233349cc55cSDimitry Andric   DCHECK_NE(jctx, 0);
234349cc55cSDimitry Andric   DCHECK_GE(addr, jctx->heap_begin);
235349cc55cSDimitry Andric   DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
23668d75effSDimitry Andric 
237349cc55cSDimitry Andric   Acquire(thr, 0, addr);
23868d75effSDimitry Andric }
23968d75effSDimitry Andric 
__tsan_java_release(jptr addr)24068d75effSDimitry Andric void __tsan_java_release(jptr addr) {
241349cc55cSDimitry Andric   JAVA_FUNC_ENTER(__tsan_java_release);
242349cc55cSDimitry Andric   DPrintf("#%d: java_release(0x%zx)\n", thr->tid, addr);
243349cc55cSDimitry Andric   DCHECK_NE(jctx, 0);
244349cc55cSDimitry Andric   DCHECK_GE(addr, jctx->heap_begin);
245349cc55cSDimitry Andric   DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
24668d75effSDimitry Andric 
247349cc55cSDimitry Andric   Release(thr, 0, addr);
24868d75effSDimitry Andric }
24968d75effSDimitry Andric 
__tsan_java_release_store(jptr addr)25068d75effSDimitry Andric void __tsan_java_release_store(jptr addr) {
251349cc55cSDimitry Andric   JAVA_FUNC_ENTER(__tsan_java_release);
252349cc55cSDimitry Andric   DPrintf("#%d: java_release_store(0x%zx)\n", thr->tid, addr);
253349cc55cSDimitry Andric   DCHECK_NE(jctx, 0);
254349cc55cSDimitry Andric   DCHECK_GE(addr, jctx->heap_begin);
255349cc55cSDimitry Andric   DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
25668d75effSDimitry Andric 
257349cc55cSDimitry Andric   ReleaseStore(thr, 0, addr);
25868d75effSDimitry Andric }
259