]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/compiler-rt/lib/tsan/rtl/tsan_interface_java.cc
Update to tcsh 6.20.00
[FreeBSD/FreeBSD.git] / contrib / compiler-rt / lib / tsan / rtl / tsan_interface_java.cc
1 //===-- tsan_interface_java.cc --------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file is a part of ThreadSanitizer (TSan), a race detector.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "tsan_interface_java.h"
15 #include "tsan_rtl.h"
16 #include "tsan_mutex.h"
17 #include "sanitizer_common/sanitizer_internal_defs.h"
18 #include "sanitizer_common/sanitizer_common.h"
19 #include "sanitizer_common/sanitizer_placement_new.h"
20 #include "sanitizer_common/sanitizer_stacktrace.h"
21 #include "sanitizer_common/sanitizer_procmaps.h"
22
23 using namespace __tsan;  // NOLINT
24
25 const jptr kHeapAlignment = 8;
26
27 namespace __tsan {
28
29 struct JavaContext {
30   const uptr heap_begin;
31   const uptr heap_size;
32
33   JavaContext(jptr heap_begin, jptr heap_size)
34       : heap_begin(heap_begin)
35       , heap_size(heap_size) {
36   }
37 };
38
39 class ScopedJavaFunc {
40  public:
41   ScopedJavaFunc(ThreadState *thr, uptr pc)
42       : thr_(thr) {
43     Initialize(thr_);
44     FuncEntry(thr, pc);
45   }
46
47   ~ScopedJavaFunc() {
48     FuncExit(thr_);
49     // FIXME(dvyukov): process pending signals.
50   }
51
52  private:
53   ThreadState *thr_;
54 };
55
56 static u64 jctx_buf[sizeof(JavaContext) / sizeof(u64) + 1];
57 static JavaContext *jctx;
58
59 }  // namespace __tsan
60
61 #define SCOPED_JAVA_FUNC(func) \
62   ThreadState *thr = cur_thread(); \
63   const uptr caller_pc = GET_CALLER_PC(); \
64   const uptr pc = StackTrace::GetCurrentPc(); \
65   (void)pc; \
66   ScopedJavaFunc scoped(thr, caller_pc); \
67 /**/
68
69 void __tsan_java_init(jptr heap_begin, jptr heap_size) {
70   SCOPED_JAVA_FUNC(__tsan_java_init);
71   DPrintf("#%d: java_init(%p, %p)\n", thr->tid, heap_begin, heap_size);
72   CHECK_EQ(jctx, 0);
73   CHECK_GT(heap_begin, 0);
74   CHECK_GT(heap_size, 0);
75   CHECK_EQ(heap_begin % kHeapAlignment, 0);
76   CHECK_EQ(heap_size % kHeapAlignment, 0);
77   CHECK_LT(heap_begin, heap_begin + heap_size);
78   jctx = new(jctx_buf) JavaContext(heap_begin, heap_size);
79 }
80
81 int  __tsan_java_fini() {
82   SCOPED_JAVA_FUNC(__tsan_java_fini);
83   DPrintf("#%d: java_fini()\n", thr->tid);
84   CHECK_NE(jctx, 0);
85   // FIXME(dvyukov): this does not call atexit() callbacks.
86   int status = Finalize(thr);
87   DPrintf("#%d: java_fini() = %d\n", thr->tid, status);
88   return status;
89 }
90
91 void __tsan_java_alloc(jptr ptr, jptr size) {
92   SCOPED_JAVA_FUNC(__tsan_java_alloc);
93   DPrintf("#%d: java_alloc(%p, %p)\n", thr->tid, ptr, size);
94   CHECK_NE(jctx, 0);
95   CHECK_NE(size, 0);
96   CHECK_EQ(ptr % kHeapAlignment, 0);
97   CHECK_EQ(size % kHeapAlignment, 0);
98   CHECK_GE(ptr, jctx->heap_begin);
99   CHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
100
101   OnUserAlloc(thr, pc, ptr, size, false);
102 }
103
104 void __tsan_java_free(jptr ptr, jptr size) {
105   SCOPED_JAVA_FUNC(__tsan_java_free);
106   DPrintf("#%d: java_free(%p, %p)\n", thr->tid, ptr, size);
107   CHECK_NE(jctx, 0);
108   CHECK_NE(size, 0);
109   CHECK_EQ(ptr % kHeapAlignment, 0);
110   CHECK_EQ(size % kHeapAlignment, 0);
111   CHECK_GE(ptr, jctx->heap_begin);
112   CHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
113
114   ctx->metamap.FreeRange(thr->proc(), ptr, size);
115 }
116
117 void __tsan_java_move(jptr src, jptr dst, jptr size) {
118   SCOPED_JAVA_FUNC(__tsan_java_move);
119   DPrintf("#%d: java_move(%p, %p, %p)\n", thr->tid, src, dst, size);
120   CHECK_NE(jctx, 0);
121   CHECK_NE(size, 0);
122   CHECK_EQ(src % kHeapAlignment, 0);
123   CHECK_EQ(dst % kHeapAlignment, 0);
124   CHECK_EQ(size % kHeapAlignment, 0);
125   CHECK_GE(src, jctx->heap_begin);
126   CHECK_LE(src + size, jctx->heap_begin + jctx->heap_size);
127   CHECK_GE(dst, jctx->heap_begin);
128   CHECK_LE(dst + size, jctx->heap_begin + jctx->heap_size);
129   CHECK_NE(dst, src);
130   CHECK_NE(size, 0);
131
132   // Assuming it's not running concurrently with threads that do
133   // memory accesses and mutex operations (stop-the-world phase).
134   ctx->metamap.MoveMemory(src, dst, size);
135
136   // Move shadow.
137   u64 *s = (u64*)MemToShadow(src);
138   u64 *d = (u64*)MemToShadow(dst);
139   u64 *send = (u64*)MemToShadow(src + size);
140   uptr inc = 1;
141   if (dst > src) {
142     s = (u64*)MemToShadow(src + size) - 1;
143     d = (u64*)MemToShadow(dst + size) - 1;
144     send = (u64*)MemToShadow(src) - 1;
145     inc = -1;
146   }
147   for (; s != send; s += inc, d += inc) {
148     *d = *s;
149     *s = 0;
150   }
151 }
152
153 jptr __tsan_java_find(jptr *from_ptr, jptr to) {
154   SCOPED_JAVA_FUNC(__tsan_java_find);
155   DPrintf("#%d: java_find(&%p, %p)\n", *from_ptr, to);
156   CHECK_EQ((*from_ptr) % kHeapAlignment, 0);
157   CHECK_EQ(to % kHeapAlignment, 0);
158   CHECK_GE(*from_ptr, jctx->heap_begin);
159   CHECK_LE(to, jctx->heap_begin + jctx->heap_size);
160   for (uptr from = *from_ptr; from < to; from += kHeapAlignment) {
161     MBlock *b = ctx->metamap.GetBlock(from);
162     if (b) {
163       *from_ptr = from;
164       return b->siz;
165     }
166   }
167   return 0;
168 }
169
170 void __tsan_java_finalize() {
171   SCOPED_JAVA_FUNC(__tsan_java_finalize);
172   DPrintf("#%d: java_mutex_finalize()\n", thr->tid);
173   AcquireGlobal(thr, 0);
174 }
175
176 void __tsan_java_mutex_lock(jptr addr) {
177   SCOPED_JAVA_FUNC(__tsan_java_mutex_lock);
178   DPrintf("#%d: java_mutex_lock(%p)\n", thr->tid, addr);
179   CHECK_NE(jctx, 0);
180   CHECK_GE(addr, jctx->heap_begin);
181   CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
182
183   MutexCreate(thr, pc, addr, true, true, true);
184   MutexLock(thr, pc, addr);
185 }
186
187 void __tsan_java_mutex_unlock(jptr addr) {
188   SCOPED_JAVA_FUNC(__tsan_java_mutex_unlock);
189   DPrintf("#%d: java_mutex_unlock(%p)\n", thr->tid, addr);
190   CHECK_NE(jctx, 0);
191   CHECK_GE(addr, jctx->heap_begin);
192   CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
193
194   MutexUnlock(thr, pc, addr);
195 }
196
197 void __tsan_java_mutex_read_lock(jptr addr) {
198   SCOPED_JAVA_FUNC(__tsan_java_mutex_read_lock);
199   DPrintf("#%d: java_mutex_read_lock(%p)\n", thr->tid, addr);
200   CHECK_NE(jctx, 0);
201   CHECK_GE(addr, jctx->heap_begin);
202   CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
203
204   MutexCreate(thr, pc, addr, true, true, true);
205   MutexReadLock(thr, pc, addr);
206 }
207
208 void __tsan_java_mutex_read_unlock(jptr addr) {
209   SCOPED_JAVA_FUNC(__tsan_java_mutex_read_unlock);
210   DPrintf("#%d: java_mutex_read_unlock(%p)\n", thr->tid, addr);
211   CHECK_NE(jctx, 0);
212   CHECK_GE(addr, jctx->heap_begin);
213   CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
214
215   MutexReadUnlock(thr, pc, addr);
216 }
217
218 void __tsan_java_mutex_lock_rec(jptr addr, int rec) {
219   SCOPED_JAVA_FUNC(__tsan_java_mutex_lock_rec);
220   DPrintf("#%d: java_mutex_lock_rec(%p, %d)\n", thr->tid, addr, rec);
221   CHECK_NE(jctx, 0);
222   CHECK_GE(addr, jctx->heap_begin);
223   CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
224   CHECK_GT(rec, 0);
225
226   MutexCreate(thr, pc, addr, true, true, true);
227   MutexLock(thr, pc, addr, rec);
228 }
229
230 int __tsan_java_mutex_unlock_rec(jptr addr) {
231   SCOPED_JAVA_FUNC(__tsan_java_mutex_unlock_rec);
232   DPrintf("#%d: java_mutex_unlock_rec(%p)\n", thr->tid, addr);
233   CHECK_NE(jctx, 0);
234   CHECK_GE(addr, jctx->heap_begin);
235   CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
236
237   return MutexUnlock(thr, pc, addr, true);
238 }
239
240 void __tsan_java_acquire(jptr addr) {
241   SCOPED_JAVA_FUNC(__tsan_java_acquire);
242   DPrintf("#%d: java_acquire(%p)\n", thr->tid, addr);
243   CHECK_NE(jctx, 0);
244   CHECK_GE(addr, jctx->heap_begin);
245   CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
246
247   Acquire(thr, caller_pc, addr);
248 }
249
250 void __tsan_java_release(jptr addr) {
251   SCOPED_JAVA_FUNC(__tsan_java_release);
252   DPrintf("#%d: java_release(%p)\n", thr->tid, addr);
253   CHECK_NE(jctx, 0);
254   CHECK_GE(addr, jctx->heap_begin);
255   CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
256
257   Release(thr, caller_pc, addr);
258 }
259
260 void __tsan_java_release_store(jptr addr) {
261   SCOPED_JAVA_FUNC(__tsan_java_release);
262   DPrintf("#%d: java_release_store(%p)\n", thr->tid, addr);
263   CHECK_NE(jctx, 0);
264   CHECK_GE(addr, jctx->heap_begin);
265   CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
266
267   ReleaseStore(thr, caller_pc, addr);
268 }