xref: /netbsd-src/external/gpl3/gcc.old/dist/libsanitizer/tsan/tsan_interface_java.cc (revision 796c32c94f6e154afc9de0f63da35c91bb739b45)
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 //===----------------------------------------------------------------------===//
11 
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"
20 
21 using namespace __tsan;  // NOLINT
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 class ScopedJavaFunc {
38  public:
39   ScopedJavaFunc(ThreadState *thr, uptr pc)
40       : thr_(thr) {
41     Initialize(thr_);
42     FuncEntry(thr, pc);
43   }
44 
45   ~ScopedJavaFunc() {
46     FuncExit(thr_);
47     // FIXME(dvyukov): process pending signals.
48   }
49 
50  private:
51   ThreadState *thr_;
52 };
53 
54 static u64 jctx_buf[sizeof(JavaContext) / sizeof(u64) + 1];
55 static JavaContext *jctx;
56 
57 }  // namespace __tsan
58 
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 /**/
66 
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);
77 }
78 
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;
87 }
88 
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);
98 
99   OnUserAlloc(thr, pc, ptr, size, false);
100 }
101 
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);
111 
112   ctx->metamap.FreeRange(thr, pc, ptr, size);
113 }
114 
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);
129 
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);
133 
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;
144   }
145   for (; s != send; s += inc, d += inc) {
146     *d = *s;
147     *s = 0;
148   }
149 }
150 
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);
155 }
156 
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);
160   CHECK_NE(jctx, 0);
161   CHECK_GE(addr, jctx->heap_begin);
162   CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
163 
164   MutexCreate(thr, pc, addr, true, true, true);
165   MutexLock(thr, pc, addr);
166 }
167 
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);
171   CHECK_NE(jctx, 0);
172   CHECK_GE(addr, jctx->heap_begin);
173   CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
174 
175   MutexUnlock(thr, pc, addr);
176 }
177 
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);
181   CHECK_NE(jctx, 0);
182   CHECK_GE(addr, jctx->heap_begin);
183   CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
184 
185   MutexCreate(thr, pc, addr, true, true, true);
186   MutexReadLock(thr, pc, addr);
187 }
188 
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);
192   CHECK_NE(jctx, 0);
193   CHECK_GE(addr, jctx->heap_begin);
194   CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
195 
196   MutexReadUnlock(thr, pc, addr);
197 }
198 
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);
202   CHECK_NE(jctx, 0);
203   CHECK_GE(addr, jctx->heap_begin);
204   CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
205   CHECK_GT(rec, 0);
206 
207   MutexCreate(thr, pc, addr, true, true, true);
208   MutexLock(thr, pc, addr, rec);
209 }
210 
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);
214   CHECK_NE(jctx, 0);
215   CHECK_GE(addr, jctx->heap_begin);
216   CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
217 
218   return MutexUnlock(thr, pc, addr, true);
219 }
220