Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/compiler-rt/lib/tsan/rtl/tsan_interface_java.cpp
35266 views
1
//===-- tsan_interface_java.cpp -------------------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This file is a part of ThreadSanitizer (TSan), a race detector.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "tsan_interface_java.h"
14
#include "tsan_rtl.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"
20
21
using namespace __tsan;
22
23
const jptr kHeapAlignment = 8;
24
25
namespace __tsan {
26
27
struct JavaContext {
28
const uptr heap_begin;
29
const uptr heap_size;
30
31
JavaContext(jptr heap_begin, jptr heap_size)
32
: heap_begin(heap_begin)
33
, heap_size(heap_size) {
34
}
35
};
36
37
static u64 jctx_buf[sizeof(JavaContext) / sizeof(u64) + 1];
38
static JavaContext *jctx;
39
40
MBlock *JavaHeapBlock(uptr addr, uptr *start) {
41
if (!jctx || addr < jctx->heap_begin ||
42
addr >= jctx->heap_begin + jctx->heap_size)
43
return nullptr;
44
for (uptr p = RoundDown(addr, kMetaShadowCell); p >= jctx->heap_begin;
45
p -= kMetaShadowCell) {
46
MBlock *b = ctx->metamap.GetBlock(p);
47
if (!b)
48
continue;
49
if (p + b->siz <= addr)
50
return nullptr;
51
*start = p;
52
return b;
53
}
54
return nullptr;
55
}
56
57
} // namespace __tsan
58
59
#define JAVA_FUNC_ENTER(func) \
60
ThreadState *thr = cur_thread(); \
61
(void)thr;
62
63
void __tsan_java_init(jptr heap_begin, jptr heap_size) {
64
JAVA_FUNC_ENTER(__tsan_java_init);
65
Initialize(thr);
66
DPrintf("#%d: java_init(0x%zx, 0x%zx)\n", thr->tid, heap_begin, heap_size);
67
DCHECK_EQ(jctx, 0);
68
DCHECK_GT(heap_begin, 0);
69
DCHECK_GT(heap_size, 0);
70
DCHECK_EQ(heap_begin % kHeapAlignment, 0);
71
DCHECK_EQ(heap_size % kHeapAlignment, 0);
72
DCHECK_LT(heap_begin, heap_begin + heap_size);
73
jctx = new(jctx_buf) JavaContext(heap_begin, heap_size);
74
}
75
76
int __tsan_java_fini() {
77
JAVA_FUNC_ENTER(__tsan_java_fini);
78
DPrintf("#%d: java_fini()\n", thr->tid);
79
DCHECK_NE(jctx, 0);
80
// FIXME(dvyukov): this does not call atexit() callbacks.
81
int status = Finalize(thr);
82
DPrintf("#%d: java_fini() = %d\n", thr->tid, status);
83
return status;
84
}
85
86
void __tsan_java_alloc(jptr ptr, jptr size) {
87
JAVA_FUNC_ENTER(__tsan_java_alloc);
88
DPrintf("#%d: java_alloc(0x%zx, 0x%zx)\n", thr->tid, ptr, size);
89
DCHECK_NE(jctx, 0);
90
DCHECK_NE(size, 0);
91
DCHECK_EQ(ptr % kHeapAlignment, 0);
92
DCHECK_EQ(size % kHeapAlignment, 0);
93
DCHECK_GE(ptr, jctx->heap_begin);
94
DCHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
95
96
OnUserAlloc(thr, 0, ptr, size, false);
97
}
98
99
void __tsan_java_free(jptr ptr, jptr size) {
100
JAVA_FUNC_ENTER(__tsan_java_free);
101
DPrintf("#%d: java_free(0x%zx, 0x%zx)\n", thr->tid, ptr, size);
102
DCHECK_NE(jctx, 0);
103
DCHECK_NE(size, 0);
104
DCHECK_EQ(ptr % kHeapAlignment, 0);
105
DCHECK_EQ(size % kHeapAlignment, 0);
106
DCHECK_GE(ptr, jctx->heap_begin);
107
DCHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
108
109
ctx->metamap.FreeRange(thr->proc(), ptr, size, false);
110
}
111
112
void __tsan_java_move(jptr src, jptr dst, jptr size) {
113
JAVA_FUNC_ENTER(__tsan_java_move);
114
DPrintf("#%d: java_move(0x%zx, 0x%zx, 0x%zx)\n", thr->tid, src, dst, size);
115
DCHECK_NE(jctx, 0);
116
DCHECK_NE(size, 0);
117
DCHECK_EQ(src % kHeapAlignment, 0);
118
DCHECK_EQ(dst % kHeapAlignment, 0);
119
DCHECK_EQ(size % kHeapAlignment, 0);
120
DCHECK_GE(src, jctx->heap_begin);
121
DCHECK_LE(src + size, jctx->heap_begin + jctx->heap_size);
122
DCHECK_GE(dst, jctx->heap_begin);
123
DCHECK_LE(dst + size, jctx->heap_begin + jctx->heap_size);
124
DCHECK_NE(dst, src);
125
DCHECK_NE(size, 0);
126
127
// Assuming it's not running concurrently with threads that do
128
// memory accesses and mutex operations (stop-the-world phase).
129
ctx->metamap.MoveMemory(src, dst, size);
130
131
// Clear the destination shadow range.
132
// We used to move shadow from src to dst, but the trace format does not
133
// support that anymore as it contains addresses of accesses.
134
RawShadow *d = MemToShadow(dst);
135
RawShadow *dend = MemToShadow(dst + size);
136
ShadowSet(d, dend, Shadow::kEmpty);
137
}
138
139
jptr __tsan_java_find(jptr *from_ptr, jptr to) {
140
JAVA_FUNC_ENTER(__tsan_java_find);
141
DPrintf("#%d: java_find(&0x%zx, 0x%zx)\n", thr->tid, *from_ptr, to);
142
DCHECK_EQ((*from_ptr) % kHeapAlignment, 0);
143
DCHECK_EQ(to % kHeapAlignment, 0);
144
DCHECK_GE(*from_ptr, jctx->heap_begin);
145
DCHECK_LE(to, jctx->heap_begin + jctx->heap_size);
146
for (uptr from = *from_ptr; from < to; from += kHeapAlignment) {
147
MBlock *b = ctx->metamap.GetBlock(from);
148
if (b) {
149
*from_ptr = from;
150
return b->siz;
151
}
152
}
153
return 0;
154
}
155
156
void __tsan_java_finalize() {
157
JAVA_FUNC_ENTER(__tsan_java_finalize);
158
DPrintf("#%d: java_finalize()\n", thr->tid);
159
AcquireGlobal(thr);
160
}
161
162
void __tsan_java_mutex_lock(jptr addr) {
163
JAVA_FUNC_ENTER(__tsan_java_mutex_lock);
164
DPrintf("#%d: java_mutex_lock(0x%zx)\n", thr->tid, addr);
165
DCHECK_NE(jctx, 0);
166
DCHECK_GE(addr, jctx->heap_begin);
167
DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
168
169
MutexPostLock(thr, 0, addr,
170
MutexFlagLinkerInit | MutexFlagWriteReentrant |
171
MutexFlagDoPreLockOnPostLock);
172
}
173
174
void __tsan_java_mutex_unlock(jptr addr) {
175
JAVA_FUNC_ENTER(__tsan_java_mutex_unlock);
176
DPrintf("#%d: java_mutex_unlock(0x%zx)\n", thr->tid, addr);
177
DCHECK_NE(jctx, 0);
178
DCHECK_GE(addr, jctx->heap_begin);
179
DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
180
181
MutexUnlock(thr, 0, addr);
182
}
183
184
void __tsan_java_mutex_read_lock(jptr addr) {
185
JAVA_FUNC_ENTER(__tsan_java_mutex_read_lock);
186
DPrintf("#%d: java_mutex_read_lock(0x%zx)\n", thr->tid, addr);
187
DCHECK_NE(jctx, 0);
188
DCHECK_GE(addr, jctx->heap_begin);
189
DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
190
191
MutexPostReadLock(thr, 0, addr,
192
MutexFlagLinkerInit | MutexFlagWriteReentrant |
193
MutexFlagDoPreLockOnPostLock);
194
}
195
196
void __tsan_java_mutex_read_unlock(jptr addr) {
197
JAVA_FUNC_ENTER(__tsan_java_mutex_read_unlock);
198
DPrintf("#%d: java_mutex_read_unlock(0x%zx)\n", thr->tid, addr);
199
DCHECK_NE(jctx, 0);
200
DCHECK_GE(addr, jctx->heap_begin);
201
DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
202
203
MutexReadUnlock(thr, 0, addr);
204
}
205
206
void __tsan_java_mutex_lock_rec(jptr addr, int rec) {
207
JAVA_FUNC_ENTER(__tsan_java_mutex_lock_rec);
208
DPrintf("#%d: java_mutex_lock_rec(0x%zx, %d)\n", thr->tid, addr, rec);
209
DCHECK_NE(jctx, 0);
210
DCHECK_GE(addr, jctx->heap_begin);
211
DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
212
DCHECK_GT(rec, 0);
213
214
MutexPostLock(thr, 0, addr,
215
MutexFlagLinkerInit | MutexFlagWriteReentrant |
216
MutexFlagDoPreLockOnPostLock | MutexFlagRecursiveLock,
217
rec);
218
}
219
220
int __tsan_java_mutex_unlock_rec(jptr addr) {
221
JAVA_FUNC_ENTER(__tsan_java_mutex_unlock_rec);
222
DPrintf("#%d: java_mutex_unlock_rec(0x%zx)\n", thr->tid, addr);
223
DCHECK_NE(jctx, 0);
224
DCHECK_GE(addr, jctx->heap_begin);
225
DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
226
227
return MutexUnlock(thr, 0, addr, MutexFlagRecursiveUnlock);
228
}
229
230
void __tsan_java_acquire(jptr addr) {
231
JAVA_FUNC_ENTER(__tsan_java_acquire);
232
DPrintf("#%d: java_acquire(0x%zx)\n", thr->tid, addr);
233
DCHECK_NE(jctx, 0);
234
DCHECK_GE(addr, jctx->heap_begin);
235
DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
236
237
Acquire(thr, 0, addr);
238
}
239
240
void __tsan_java_release(jptr addr) {
241
JAVA_FUNC_ENTER(__tsan_java_release);
242
DPrintf("#%d: java_release(0x%zx)\n", thr->tid, addr);
243
DCHECK_NE(jctx, 0);
244
DCHECK_GE(addr, jctx->heap_begin);
245
DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
246
247
Release(thr, 0, addr);
248
}
249
250
void __tsan_java_release_store(jptr addr) {
251
JAVA_FUNC_ENTER(__tsan_java_release);
252
DPrintf("#%d: java_release_store(0x%zx)\n", thr->tid, addr);
253
DCHECK_NE(jctx, 0);
254
DCHECK_GE(addr, jctx->heap_begin);
255
DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
256
257
ReleaseStore(thr, 0, addr);
258
}
259
260