Mercurial > hg > CbC > CbC_gcc
comparison libsanitizer/tsan/tsan_rtl.h @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | 04ced10e8804 |
children |
comparison
equal
deleted
inserted
replaced
131:84e7813d76e9 | 145:1830386684a0 |
---|---|
1 //===-- tsan_rtl.h ----------------------------------------------*- C++ -*-===// | 1 //===-- tsan_rtl.h ----------------------------------------------*- C++ -*-===// |
2 // | 2 // |
3 // This file is distributed under the University of Illinois Open Source | 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 // License. See LICENSE.TXT for details. | 4 // See https://llvm.org/LICENSE.txt for license information. |
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
5 // | 6 // |
6 //===----------------------------------------------------------------------===// | 7 //===----------------------------------------------------------------------===// |
7 // | 8 // |
8 // This file is a part of ThreadSanitizer (TSan), a race detector. | 9 // This file is a part of ThreadSanitizer (TSan), a race detector. |
9 // | 10 // |
30 #include "sanitizer_common/sanitizer_common.h" | 31 #include "sanitizer_common/sanitizer_common.h" |
31 #include "sanitizer_common/sanitizer_deadlock_detector_interface.h" | 32 #include "sanitizer_common/sanitizer_deadlock_detector_interface.h" |
32 #include "sanitizer_common/sanitizer_libignore.h" | 33 #include "sanitizer_common/sanitizer_libignore.h" |
33 #include "sanitizer_common/sanitizer_suppressions.h" | 34 #include "sanitizer_common/sanitizer_suppressions.h" |
34 #include "sanitizer_common/sanitizer_thread_registry.h" | 35 #include "sanitizer_common/sanitizer_thread_registry.h" |
36 #include "sanitizer_common/sanitizer_vector.h" | |
35 #include "tsan_clock.h" | 37 #include "tsan_clock.h" |
36 #include "tsan_defs.h" | 38 #include "tsan_defs.h" |
37 #include "tsan_flags.h" | 39 #include "tsan_flags.h" |
40 #include "tsan_mman.h" | |
38 #include "tsan_sync.h" | 41 #include "tsan_sync.h" |
39 #include "tsan_trace.h" | 42 #include "tsan_trace.h" |
40 #include "tsan_vector.h" | |
41 #include "tsan_report.h" | 43 #include "tsan_report.h" |
42 #include "tsan_platform.h" | 44 #include "tsan_platform.h" |
43 #include "tsan_mutexset.h" | 45 #include "tsan_mutexset.h" |
44 #include "tsan_ignoreset.h" | 46 #include "tsan_ignoreset.h" |
45 #include "tsan_stack_trace.h" | 47 #include "tsan_stack_trace.h" |
51 namespace __tsan { | 53 namespace __tsan { |
52 | 54 |
53 #if !SANITIZER_GO | 55 #if !SANITIZER_GO |
54 struct MapUnmapCallback; | 56 struct MapUnmapCallback; |
55 #if defined(__mips64) || defined(__aarch64__) || defined(__powerpc__) | 57 #if defined(__mips64) || defined(__aarch64__) || defined(__powerpc__) |
56 static const uptr kAllocatorRegionSizeLog = 20; | 58 |
57 static const uptr kAllocatorNumRegions = | |
58 SANITIZER_MMAP_RANGE_SIZE >> kAllocatorRegionSizeLog; | |
59 typedef TwoLevelByteMap<(kAllocatorNumRegions >> 12), 1 << 12, | |
60 MapUnmapCallback> ByteMap; | |
61 struct AP32 { | 59 struct AP32 { |
62 static const uptr kSpaceBeg = 0; | 60 static const uptr kSpaceBeg = 0; |
63 static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE; | 61 static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE; |
64 static const uptr kMetadataSize = 0; | 62 static const uptr kMetadataSize = 0; |
65 typedef __sanitizer::CompactSizeClassMap SizeClassMap; | 63 typedef __sanitizer::CompactSizeClassMap SizeClassMap; |
66 static const uptr kRegionSizeLog = kAllocatorRegionSizeLog; | 64 static const uptr kRegionSizeLog = 20; |
67 typedef __tsan::ByteMap ByteMap; | 65 using AddressSpaceView = LocalAddressSpaceView; |
68 typedef __tsan::MapUnmapCallback MapUnmapCallback; | 66 typedef __tsan::MapUnmapCallback MapUnmapCallback; |
69 static const uptr kFlags = 0; | 67 static const uptr kFlags = 0; |
70 }; | 68 }; |
71 typedef SizeClassAllocator32<AP32> PrimaryAllocator; | 69 typedef SizeClassAllocator32<AP32> PrimaryAllocator; |
72 #else | 70 #else |
75 static const uptr kSpaceSize = Mapping::kHeapMemEnd - Mapping::kHeapMemBeg; | 73 static const uptr kSpaceSize = Mapping::kHeapMemEnd - Mapping::kHeapMemBeg; |
76 static const uptr kMetadataSize = 0; | 74 static const uptr kMetadataSize = 0; |
77 typedef DefaultSizeClassMap SizeClassMap; | 75 typedef DefaultSizeClassMap SizeClassMap; |
78 typedef __tsan::MapUnmapCallback MapUnmapCallback; | 76 typedef __tsan::MapUnmapCallback MapUnmapCallback; |
79 static const uptr kFlags = 0; | 77 static const uptr kFlags = 0; |
78 using AddressSpaceView = LocalAddressSpaceView; | |
80 }; | 79 }; |
81 typedef SizeClassAllocator64<AP64> PrimaryAllocator; | 80 typedef SizeClassAllocator64<AP64> PrimaryAllocator; |
82 #endif | 81 #endif |
83 typedef SizeClassAllocatorLocalCache<PrimaryAllocator> AllocatorCache; | 82 typedef CombinedAllocator<PrimaryAllocator> Allocator; |
84 typedef LargeMmapAllocator<MapUnmapCallback> SecondaryAllocator; | 83 typedef Allocator::AllocatorCache AllocatorCache; |
85 typedef CombinedAllocator<PrimaryAllocator, AllocatorCache, | |
86 SecondaryAllocator> Allocator; | |
87 Allocator *allocator(); | 84 Allocator *allocator(); |
88 #endif | 85 #endif |
89 | 86 |
90 void TsanCheckFailed(const char *file, int line, const char *cond, | 87 void TsanCheckFailed(const char *file, int line, const char *cond, |
91 u64 v1, u64 v2); | 88 u64 v1, u64 v2); |
239 | 236 |
240 static ALWAYS_INLINE bool TwoRangesIntersect(Shadow s1, Shadow s2, | 237 static ALWAYS_INLINE bool TwoRangesIntersect(Shadow s1, Shadow s2, |
241 unsigned kS2AccessSize) { | 238 unsigned kS2AccessSize) { |
242 bool res = false; | 239 bool res = false; |
243 u64 diff = s1.addr0() - s2.addr0(); | 240 u64 diff = s1.addr0() - s2.addr0(); |
244 if ((s64)diff < 0) { // s1.addr0 < s2.addr0 // NOLINT | 241 if ((s64)diff < 0) { // s1.addr0 < s2.addr0 |
245 // if (s1.addr0() + size1) > s2.addr0()) return true; | 242 // if (s1.addr0() + size1) > s2.addr0()) return true; |
246 if (s1.size() > -diff) | 243 if (s1.size() > -diff) |
247 res = true; | 244 res = true; |
248 } else { | 245 } else { |
249 // if (s2.addr0() + kS2AccessSize > s1.addr0()) return true; | 246 // if (s2.addr0() + kS2AccessSize > s1.addr0()) return true; |
326 | 323 |
327 struct ThreadSignalContext; | 324 struct ThreadSignalContext; |
328 | 325 |
329 struct JmpBuf { | 326 struct JmpBuf { |
330 uptr sp; | 327 uptr sp; |
331 uptr mangled_sp; | |
332 int int_signal_send; | 328 int int_signal_send; |
333 bool in_blocking_func; | 329 bool in_blocking_func; |
334 uptr in_signal_handler; | 330 uptr in_signal_handler; |
335 uptr *shadow_stack_pos; | 331 uptr *shadow_stack_pos; |
336 }; | 332 }; |
378 // QUESTION: can we can squeeze this into ThreadState::Fast? | 374 // QUESTION: can we can squeeze this into ThreadState::Fast? |
379 // E.g. ThreadState::Fast is a 44-bit, 32 are taken by synch_epoch and 12 are | 375 // E.g. ThreadState::Fast is a 44-bit, 32 are taken by synch_epoch and 12 are |
380 // taken by epoch between synchs. | 376 // taken by epoch between synchs. |
381 // This way we can save one load from tls. | 377 // This way we can save one load from tls. |
382 u64 fast_synch_epoch; | 378 u64 fast_synch_epoch; |
379 // Technically `current` should be a separate THREADLOCAL variable; | |
380 // but it is placed here in order to share cache line with previous fields. | |
381 ThreadState* current; | |
383 // This is a slow path flag. On fast path, fast_state.GetIgnoreBit() is read. | 382 // This is a slow path flag. On fast path, fast_state.GetIgnoreBit() is read. |
384 // We do not distinguish beteween ignoring reads and writes | 383 // We do not distinguish beteween ignoring reads and writes |
385 // for better performance. | 384 // for better performance. |
386 int ignore_reads_and_writes; | 385 int ignore_reads_and_writes; |
387 int ignore_sync; | 386 int ignore_sync; |
455 }; | 454 }; |
456 | 455 |
457 #if !SANITIZER_GO | 456 #if !SANITIZER_GO |
458 #if SANITIZER_MAC || SANITIZER_ANDROID | 457 #if SANITIZER_MAC || SANITIZER_ANDROID |
459 ThreadState *cur_thread(); | 458 ThreadState *cur_thread(); |
459 void set_cur_thread(ThreadState *thr); | |
460 void cur_thread_finalize(); | 460 void cur_thread_finalize(); |
461 INLINE void cur_thread_init() { } | |
461 #else | 462 #else |
462 __attribute__((tls_model("initial-exec"))) | 463 __attribute__((tls_model("initial-exec"))) |
463 extern THREADLOCAL char cur_thread_placeholder[]; | 464 extern THREADLOCAL char cur_thread_placeholder[]; |
464 INLINE ThreadState *cur_thread() { | 465 INLINE ThreadState *cur_thread() { |
465 return reinterpret_cast<ThreadState *>(&cur_thread_placeholder); | 466 return reinterpret_cast<ThreadState *>(cur_thread_placeholder)->current; |
467 } | |
468 INLINE void cur_thread_init() { | |
469 ThreadState *thr = reinterpret_cast<ThreadState *>(cur_thread_placeholder); | |
470 if (UNLIKELY(!thr->current)) | |
471 thr->current = thr; | |
472 } | |
473 INLINE void set_cur_thread(ThreadState *thr) { | |
474 reinterpret_cast<ThreadState *>(cur_thread_placeholder)->current = thr; | |
466 } | 475 } |
467 INLINE void cur_thread_finalize() { } | 476 INLINE void cur_thread_finalize() { } |
468 #endif // SANITIZER_MAC || SANITIZER_ANDROID | 477 #endif // SANITIZER_MAC || SANITIZER_ANDROID |
469 #endif // SANITIZER_GO | 478 #endif // SANITIZER_GO |
470 | 479 |
515 | 524 |
516 struct Context { | 525 struct Context { |
517 Context(); | 526 Context(); |
518 | 527 |
519 bool initialized; | 528 bool initialized; |
529 #if !SANITIZER_GO | |
520 bool after_multithreaded_fork; | 530 bool after_multithreaded_fork; |
531 #endif | |
521 | 532 |
522 MetaMap metamap; | 533 MetaMap metamap; |
523 | 534 |
524 Mutex report_mtx; | 535 Mutex report_mtx; |
525 int nreported; | 536 int nreported; |
570 | 581 |
571 const char *GetObjectTypeFromTag(uptr tag); | 582 const char *GetObjectTypeFromTag(uptr tag); |
572 const char *GetReportHeaderFromTag(uptr tag); | 583 const char *GetReportHeaderFromTag(uptr tag); |
573 uptr TagFromShadowStackFrame(uptr pc); | 584 uptr TagFromShadowStackFrame(uptr pc); |
574 | 585 |
575 class ScopedReport { | 586 class ScopedReportBase { |
576 public: | 587 public: |
577 explicit ScopedReport(ReportType typ, uptr tag = kExternalTagNone); | |
578 ~ScopedReport(); | |
579 | |
580 void AddMemoryAccess(uptr addr, uptr external_tag, Shadow s, StackTrace stack, | 588 void AddMemoryAccess(uptr addr, uptr external_tag, Shadow s, StackTrace stack, |
581 const MutexSet *mset); | 589 const MutexSet *mset); |
582 void AddStack(StackTrace stack, bool suppressable = false); | 590 void AddStack(StackTrace stack, bool suppressable = false); |
583 void AddThread(const ThreadContext *tctx, bool suppressable = false); | 591 void AddThread(const ThreadContext *tctx, bool suppressable = false); |
584 void AddThread(int unique_tid, bool suppressable = false); | 592 void AddThread(int unique_tid, bool suppressable = false); |
589 void AddSleep(u32 stack_id); | 597 void AddSleep(u32 stack_id); |
590 void SetCount(int count); | 598 void SetCount(int count); |
591 | 599 |
592 const ReportDesc *GetReport() const; | 600 const ReportDesc *GetReport() const; |
593 | 601 |
602 protected: | |
603 ScopedReportBase(ReportType typ, uptr tag); | |
604 ~ScopedReportBase(); | |
605 | |
594 private: | 606 private: |
595 ReportDesc *rep_; | 607 ReportDesc *rep_; |
596 // Symbolizer makes lots of intercepted calls. If we try to process them, | 608 // Symbolizer makes lots of intercepted calls. If we try to process them, |
597 // at best it will cause deadlocks on internal mutexes. | 609 // at best it will cause deadlocks on internal mutexes. |
598 ScopedIgnoreInterceptors ignore_interceptors_; | 610 ScopedIgnoreInterceptors ignore_interceptors_; |
599 | 611 |
600 void AddDeadMutex(u64 id); | 612 void AddDeadMutex(u64 id); |
601 | 613 |
602 ScopedReport(const ScopedReport&); | 614 ScopedReportBase(const ScopedReportBase &) = delete; |
603 void operator = (const ScopedReport&); | 615 void operator=(const ScopedReportBase &) = delete; |
616 }; | |
617 | |
618 class ScopedReport : public ScopedReportBase { | |
619 public: | |
620 explicit ScopedReport(ReportType typ, uptr tag = kExternalTagNone); | |
621 ~ScopedReport(); | |
622 | |
623 private: | |
624 ScopedErrorReportLock lock_; | |
604 }; | 625 }; |
605 | 626 |
606 ThreadContext *IsThreadStackOrTls(uptr addr, bool *is_stack); | 627 ThreadContext *IsThreadStackOrTls(uptr addr, bool *is_stack); |
607 void RestoreStack(int tid, const u64 epoch, VarSizeStackTrace *stk, | 628 void RestoreStack(int tid, const u64 epoch, VarSizeStackTrace *stk, |
608 MutexSet *mset, uptr *tag = nullptr); | 629 MutexSet *mset, uptr *tag = nullptr); |
633 } | 654 } |
634 stack->Init(&thr->shadow_stack[start], size, toppc); | 655 stack->Init(&thr->shadow_stack[start], size, toppc); |
635 ExtractTagFromStack(stack, tag); | 656 ExtractTagFromStack(stack, tag); |
636 } | 657 } |
637 | 658 |
659 #define GET_STACK_TRACE_FATAL(thr, pc) \ | |
660 VarSizeStackTrace stack; \ | |
661 ObtainCurrentStack(thr, pc, &stack); \ | |
662 stack.ReverseOrder(); | |
638 | 663 |
639 #if TSAN_COLLECT_STATS | 664 #if TSAN_COLLECT_STATS |
640 void StatAggregate(u64 *dst, u64 *src); | 665 void StatAggregate(u64 *dst, u64 *src); |
641 void StatOutput(u64 *stat); | 666 void StatOutput(u64 *stat); |
642 #endif | 667 #endif |
653 } | 678 } |
654 | 679 |
655 void MapShadow(uptr addr, uptr size); | 680 void MapShadow(uptr addr, uptr size); |
656 void MapThreadTrace(uptr addr, uptr size, const char *name); | 681 void MapThreadTrace(uptr addr, uptr size, const char *name); |
657 void DontNeedShadowFor(uptr addr, uptr size); | 682 void DontNeedShadowFor(uptr addr, uptr size); |
683 void UnmapShadow(ThreadState *thr, uptr addr, uptr size); | |
658 void InitializeShadowMemory(); | 684 void InitializeShadowMemory(); |
659 void InitializeInterceptors(); | 685 void InitializeInterceptors(); |
660 void InitializeLibIgnore(); | 686 void InitializeLibIgnore(); |
661 void InitializeDynamicAnnotations(); | 687 void InitializeDynamicAnnotations(); |
662 | 688 |
686 ReportStack *SymbolizeStackId(u32 stack_id); | 712 ReportStack *SymbolizeStackId(u32 stack_id); |
687 void PrintCurrentStack(ThreadState *thr, uptr pc); | 713 void PrintCurrentStack(ThreadState *thr, uptr pc); |
688 void PrintCurrentStackSlow(uptr pc); // uses libunwind | 714 void PrintCurrentStackSlow(uptr pc); // uses libunwind |
689 | 715 |
690 void Initialize(ThreadState *thr); | 716 void Initialize(ThreadState *thr); |
717 void MaybeSpawnBackgroundThread(); | |
691 int Finalize(ThreadState *thr); | 718 int Finalize(ThreadState *thr); |
692 | 719 |
693 void OnUserAlloc(ThreadState *thr, uptr pc, uptr p, uptr sz, bool write); | 720 void OnUserAlloc(ThreadState *thr, uptr pc, uptr p, uptr sz, bool write); |
694 void OnUserFree(ThreadState *thr, uptr pc, uptr p, bool write); | 721 void OnUserFree(ThreadState *thr, uptr pc, uptr p, bool write); |
695 | 722 |
731 } | 758 } |
732 | 759 |
733 void MemoryResetRange(ThreadState *thr, uptr pc, uptr addr, uptr size); | 760 void MemoryResetRange(ThreadState *thr, uptr pc, uptr addr, uptr size); |
734 void MemoryRangeFreed(ThreadState *thr, uptr pc, uptr addr, uptr size); | 761 void MemoryRangeFreed(ThreadState *thr, uptr pc, uptr addr, uptr size); |
735 void MemoryRangeImitateWrite(ThreadState *thr, uptr pc, uptr addr, uptr size); | 762 void MemoryRangeImitateWrite(ThreadState *thr, uptr pc, uptr addr, uptr size); |
763 void MemoryRangeImitateWriteOrResetRange(ThreadState *thr, uptr pc, uptr addr, | |
764 uptr size); | |
736 | 765 |
737 void ThreadIgnoreBegin(ThreadState *thr, uptr pc, bool save_stack = true); | 766 void ThreadIgnoreBegin(ThreadState *thr, uptr pc, bool save_stack = true); |
738 void ThreadIgnoreEnd(ThreadState *thr, uptr pc); | 767 void ThreadIgnoreEnd(ThreadState *thr, uptr pc); |
739 void ThreadIgnoreSyncBegin(ThreadState *thr, uptr pc, bool save_stack = true); | 768 void ThreadIgnoreSyncBegin(ThreadState *thr, uptr pc, bool save_stack = true); |
740 void ThreadIgnoreSyncEnd(ThreadState *thr, uptr pc); | 769 void ThreadIgnoreSyncEnd(ThreadState *thr, uptr pc); |
741 | 770 |
742 void FuncEntry(ThreadState *thr, uptr pc); | 771 void FuncEntry(ThreadState *thr, uptr pc); |
743 void FuncExit(ThreadState *thr); | 772 void FuncExit(ThreadState *thr); |
744 | 773 |
745 int ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached); | 774 int ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached); |
746 void ThreadStart(ThreadState *thr, int tid, tid_t os_id, bool workerthread); | 775 void ThreadStart(ThreadState *thr, int tid, tid_t os_id, |
776 ThreadType thread_type); | |
747 void ThreadFinish(ThreadState *thr); | 777 void ThreadFinish(ThreadState *thr); |
748 int ThreadTid(ThreadState *thr, uptr pc, uptr uid); | 778 int ThreadTid(ThreadState *thr, uptr pc, uptr uid); |
749 void ThreadJoin(ThreadState *thr, uptr pc, int tid); | 779 void ThreadJoin(ThreadState *thr, uptr pc, int tid); |
750 void ThreadDetach(ThreadState *thr, uptr pc, int tid); | 780 void ThreadDetach(ThreadState *thr, uptr pc, int tid); |
751 void ThreadFinalize(ThreadState *thr); | 781 void ThreadFinalize(ThreadState *thr); |
752 void ThreadSetName(ThreadState *thr, const char *name); | 782 void ThreadSetName(ThreadState *thr, const char *name); |
753 int ThreadCount(ThreadState *thr); | 783 int ThreadCount(ThreadState *thr); |
754 void ProcessPendingSignals(ThreadState *thr); | 784 void ProcessPendingSignals(ThreadState *thr); |
785 void ThreadNotJoined(ThreadState *thr, uptr pc, int tid, uptr uid); | |
755 | 786 |
756 Processor *ProcCreate(); | 787 Processor *ProcCreate(); |
757 void ProcDestroy(Processor *proc); | 788 void ProcDestroy(Processor *proc); |
758 void ProcWire(Processor *proc, ThreadState *thr); | 789 void ProcWire(Processor *proc, ThreadState *thr); |
759 void ProcUnwire(Processor *proc, ThreadState *thr); | 790 void ProcUnwire(Processor *proc, ThreadState *thr); |
843 uptr ALWAYS_INLINE HeapEnd() { | 874 uptr ALWAYS_INLINE HeapEnd() { |
844 return HeapMemEnd() + PrimaryAllocator::AdditionalSize(); | 875 return HeapMemEnd() + PrimaryAllocator::AdditionalSize(); |
845 } | 876 } |
846 #endif | 877 #endif |
847 | 878 |
879 ThreadState *FiberCreate(ThreadState *thr, uptr pc, unsigned flags); | |
880 void FiberDestroy(ThreadState *thr, uptr pc, ThreadState *fiber); | |
881 void FiberSwitch(ThreadState *thr, uptr pc, ThreadState *fiber, unsigned flags); | |
882 | |
883 // These need to match __tsan_switch_to_fiber_* flags defined in | |
884 // tsan_interface.h. See documentation there as well. | |
885 enum FiberSwitchFlags { | |
886 FiberSwitchFlagNoSync = 1 << 0, // __tsan_switch_to_fiber_no_sync | |
887 }; | |
888 | |
848 } // namespace __tsan | 889 } // namespace __tsan |
849 | 890 |
850 #endif // TSAN_RTL_H | 891 #endif // TSAN_RTL_H |