tsan_interface_java.cc 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  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. #include "tsan_interface_java.h"
  12. #include "tsan_rtl.h"
  13. #include "tsan_mutex.h"
  14. #include "sanitizer_common/sanitizer_internal_defs.h"
  15. #include "sanitizer_common/sanitizer_common.h"
  16. #include "sanitizer_common/sanitizer_placement_new.h"
  17. #include "sanitizer_common/sanitizer_stacktrace.h"
  18. #include "sanitizer_common/sanitizer_procmaps.h"
  19. using namespace __tsan; // NOLINT
  20. const jptr kHeapAlignment = 8;
  21. namespace __tsan {
  22. struct JavaContext {
  23. const uptr heap_begin;
  24. const uptr heap_size;
  25. JavaContext(jptr heap_begin, jptr heap_size)
  26. : heap_begin(heap_begin)
  27. , heap_size(heap_size) {
  28. }
  29. };
  30. class ScopedJavaFunc {
  31. public:
  32. ScopedJavaFunc(ThreadState *thr, uptr pc)
  33. : thr_(thr) {
  34. Initialize(thr_);
  35. FuncEntry(thr, pc);
  36. }
  37. ~ScopedJavaFunc() {
  38. FuncExit(thr_);
  39. // FIXME(dvyukov): process pending signals.
  40. }
  41. private:
  42. ThreadState *thr_;
  43. };
  44. static u64 jctx_buf[sizeof(JavaContext) / sizeof(u64) + 1];
  45. static JavaContext *jctx;
  46. } // namespace __tsan
  47. #define SCOPED_JAVA_FUNC(func) \
  48. ThreadState *thr = cur_thread(); \
  49. const uptr caller_pc = GET_CALLER_PC(); \
  50. const uptr pc = StackTrace::GetCurrentPc(); \
  51. (void)pc; \
  52. ScopedJavaFunc scoped(thr, caller_pc); \
  53. /**/
  54. void __tsan_java_init(jptr heap_begin, jptr heap_size) {
  55. SCOPED_JAVA_FUNC(__tsan_java_init);
  56. DPrintf("#%d: java_init(%p, %p)\n", thr->tid, heap_begin, heap_size);
  57. CHECK_EQ(jctx, 0);
  58. CHECK_GT(heap_begin, 0);
  59. CHECK_GT(heap_size, 0);
  60. CHECK_EQ(heap_begin % kHeapAlignment, 0);
  61. CHECK_EQ(heap_size % kHeapAlignment, 0);
  62. CHECK_LT(heap_begin, heap_begin + heap_size);
  63. jctx = new(jctx_buf) JavaContext(heap_begin, heap_size);
  64. }
  65. int __tsan_java_fini() {
  66. SCOPED_JAVA_FUNC(__tsan_java_fini);
  67. DPrintf("#%d: java_fini()\n", thr->tid);
  68. CHECK_NE(jctx, 0);
  69. // FIXME(dvyukov): this does not call atexit() callbacks.
  70. int status = Finalize(thr);
  71. DPrintf("#%d: java_fini() = %d\n", thr->tid, status);
  72. return status;
  73. }
  74. void __tsan_java_alloc(jptr ptr, jptr size) {
  75. SCOPED_JAVA_FUNC(__tsan_java_alloc);
  76. DPrintf("#%d: java_alloc(%p, %p)\n", thr->tid, ptr, size);
  77. CHECK_NE(jctx, 0);
  78. CHECK_NE(size, 0);
  79. CHECK_EQ(ptr % kHeapAlignment, 0);
  80. CHECK_EQ(size % kHeapAlignment, 0);
  81. CHECK_GE(ptr, jctx->heap_begin);
  82. CHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
  83. OnUserAlloc(thr, pc, ptr, size, false);
  84. }
  85. void __tsan_java_free(jptr ptr, jptr size) {
  86. SCOPED_JAVA_FUNC(__tsan_java_free);
  87. DPrintf("#%d: java_free(%p, %p)\n", thr->tid, ptr, size);
  88. CHECK_NE(jctx, 0);
  89. CHECK_NE(size, 0);
  90. CHECK_EQ(ptr % kHeapAlignment, 0);
  91. CHECK_EQ(size % kHeapAlignment, 0);
  92. CHECK_GE(ptr, jctx->heap_begin);
  93. CHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
  94. ctx->metamap.FreeRange(thr, pc, ptr, size);
  95. }
  96. void __tsan_java_move(jptr src, jptr dst, jptr size) {
  97. SCOPED_JAVA_FUNC(__tsan_java_move);
  98. DPrintf("#%d: java_move(%p, %p, %p)\n", thr->tid, src, dst, size);
  99. CHECK_NE(jctx, 0);
  100. CHECK_NE(size, 0);
  101. CHECK_EQ(src % kHeapAlignment, 0);
  102. CHECK_EQ(dst % kHeapAlignment, 0);
  103. CHECK_EQ(size % kHeapAlignment, 0);
  104. CHECK_GE(src, jctx->heap_begin);
  105. CHECK_LE(src + size, jctx->heap_begin + jctx->heap_size);
  106. CHECK_GE(dst, jctx->heap_begin);
  107. CHECK_LE(dst + size, jctx->heap_begin + jctx->heap_size);
  108. CHECK_NE(dst, src);
  109. CHECK_NE(size, 0);
  110. // Assuming it's not running concurrently with threads that do
  111. // memory accesses and mutex operations (stop-the-world phase).
  112. ctx->metamap.MoveMemory(src, dst, size);
  113. // Move shadow.
  114. u64 *s = (u64*)MemToShadow(src);
  115. u64 *d = (u64*)MemToShadow(dst);
  116. u64 *send = (u64*)MemToShadow(src + size);
  117. uptr inc = 1;
  118. if (dst > src) {
  119. s = (u64*)MemToShadow(src + size) - 1;
  120. d = (u64*)MemToShadow(dst + size) - 1;
  121. send = (u64*)MemToShadow(src) - 1;
  122. inc = -1;
  123. }
  124. for (; s != send; s += inc, d += inc) {
  125. *d = *s;
  126. *s = 0;
  127. }
  128. }
  129. void __tsan_java_finalize() {
  130. SCOPED_JAVA_FUNC(__tsan_java_finalize);
  131. DPrintf("#%d: java_mutex_finalize()\n", thr->tid);
  132. AcquireGlobal(thr, 0);
  133. }
  134. void __tsan_java_mutex_lock(jptr addr) {
  135. SCOPED_JAVA_FUNC(__tsan_java_mutex_lock);
  136. DPrintf("#%d: java_mutex_lock(%p)\n", thr->tid, addr);
  137. CHECK_NE(jctx, 0);
  138. CHECK_GE(addr, jctx->heap_begin);
  139. CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
  140. MutexCreate(thr, pc, addr, true, true, true);
  141. MutexLock(thr, pc, addr);
  142. }
  143. void __tsan_java_mutex_unlock(jptr addr) {
  144. SCOPED_JAVA_FUNC(__tsan_java_mutex_unlock);
  145. DPrintf("#%d: java_mutex_unlock(%p)\n", thr->tid, addr);
  146. CHECK_NE(jctx, 0);
  147. CHECK_GE(addr, jctx->heap_begin);
  148. CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
  149. MutexUnlock(thr, pc, addr);
  150. }
  151. void __tsan_java_mutex_read_lock(jptr addr) {
  152. SCOPED_JAVA_FUNC(__tsan_java_mutex_read_lock);
  153. DPrintf("#%d: java_mutex_read_lock(%p)\n", thr->tid, addr);
  154. CHECK_NE(jctx, 0);
  155. CHECK_GE(addr, jctx->heap_begin);
  156. CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
  157. MutexCreate(thr, pc, addr, true, true, true);
  158. MutexReadLock(thr, pc, addr);
  159. }
  160. void __tsan_java_mutex_read_unlock(jptr addr) {
  161. SCOPED_JAVA_FUNC(__tsan_java_mutex_read_unlock);
  162. DPrintf("#%d: java_mutex_read_unlock(%p)\n", thr->tid, addr);
  163. CHECK_NE(jctx, 0);
  164. CHECK_GE(addr, jctx->heap_begin);
  165. CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
  166. MutexReadUnlock(thr, pc, addr);
  167. }
  168. void __tsan_java_mutex_lock_rec(jptr addr, int rec) {
  169. SCOPED_JAVA_FUNC(__tsan_java_mutex_lock_rec);
  170. DPrintf("#%d: java_mutex_lock_rec(%p, %d)\n", thr->tid, addr, rec);
  171. CHECK_NE(jctx, 0);
  172. CHECK_GE(addr, jctx->heap_begin);
  173. CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
  174. CHECK_GT(rec, 0);
  175. MutexCreate(thr, pc, addr, true, true, true);
  176. MutexLock(thr, pc, addr, rec);
  177. }
  178. int __tsan_java_mutex_unlock_rec(jptr addr) {
  179. SCOPED_JAVA_FUNC(__tsan_java_mutex_unlock_rec);
  180. DPrintf("#%d: java_mutex_unlock_rec(%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. return MutexUnlock(thr, pc, addr, true);
  185. }