Home | History | Annotate | Line # | Download | only in rtl
      1 //===-- tsan_defs.h ---------------------------------------------*- C++ -*-===//
      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 #ifndef TSAN_DEFS_H
     15 #define TSAN_DEFS_H
     16 
     17 #include "sanitizer_common/sanitizer_internal_defs.h"
     18 #include "sanitizer_common/sanitizer_libc.h"
     19 #include "tsan_stat.h"
     20 #include "ubsan/ubsan_platform.h"
     21 
     22 // Setup defaults for compile definitions.
     23 #ifndef TSAN_NO_HISTORY
     24 # define TSAN_NO_HISTORY 0
     25 #endif
     26 
     27 #ifndef TSAN_COLLECT_STATS
     28 # define TSAN_COLLECT_STATS 0
     29 #endif
     30 
     31 #ifndef TSAN_CONTAINS_UBSAN
     32 # if CAN_SANITIZE_UB && !SANITIZER_GO
     33 #  define TSAN_CONTAINS_UBSAN 1
     34 # else
     35 #  define TSAN_CONTAINS_UBSAN 0
     36 # endif
     37 #endif
     38 
     39 namespace __tsan {
     40 
     41 const int kClkBits = 42;
     42 const unsigned kMaxTidReuse = (1 << (64 - kClkBits)) - 1;
     43 
     44 struct ClockElem {
     45   u64 epoch  : kClkBits;
     46   u64 reused : 64 - kClkBits;  // tid reuse count
     47 };
     48 
     49 struct ClockBlock {
     50   static const uptr kSize = 512;
     51   static const uptr kTableSize = kSize / sizeof(u32);
     52   static const uptr kClockCount = kSize / sizeof(ClockElem);
     53   static const uptr kRefIdx = kTableSize - 1;
     54   static const uptr kBlockIdx = kTableSize - 2;
     55 
     56   union {
     57     u32       table[kTableSize];
     58     ClockElem clock[kClockCount];
     59   };
     60 
     61   ClockBlock() {
     62   }
     63 };
     64 
     65 const int kTidBits = 13;
     66 // Reduce kMaxTid by kClockCount because one slot in ClockBlock table is
     67 // occupied by reference counter, so total number of elements we can store
     68 // in SyncClock is kClockCount * (kTableSize - 1).
     69 const unsigned kMaxTid = (1 << kTidBits) - ClockBlock::kClockCount;
     70 #if !SANITIZER_GO
     71 const unsigned kMaxTidInClock = kMaxTid * 2;  // This includes msb 'freed' bit.
     72 #else
     73 const unsigned kMaxTidInClock = kMaxTid;  // Go does not track freed memory.
     74 #endif
     75 const uptr kShadowStackSize = 64 * 1024;
     76 
     77 // Count of shadow values in a shadow cell.
     78 const uptr kShadowCnt = 4;
     79 
     80 // That many user bytes are mapped onto a single shadow cell.
     81 const uptr kShadowCell = 8;
     82 
     83 // Size of a single shadow value (u64).
     84 const uptr kShadowSize = 8;
     85 
     86 // Shadow memory is kShadowMultiplier times larger than user memory.
     87 const uptr kShadowMultiplier = kShadowSize * kShadowCnt / kShadowCell;
     88 
     89 // That many user bytes are mapped onto a single meta shadow cell.
     90 // Must be less or equal to minimal memory allocator alignment.
     91 const uptr kMetaShadowCell = 8;
     92 
     93 // Size of a single meta shadow value (u32).
     94 const uptr kMetaShadowSize = 4;
     95 
     96 #if TSAN_NO_HISTORY
     97 const bool kCollectHistory = false;
     98 #else
     99 const bool kCollectHistory = true;
    100 #endif
    101 
    102 const u16 kInvalidTid = kMaxTid + 1;
    103 
    104 // The following "build consistency" machinery ensures that all source files
    105 // are built in the same configuration. Inconsistent builds lead to
    106 // hard to debug crashes.
    107 #if SANITIZER_DEBUG
    108 void build_consistency_debug();
    109 #else
    110 void build_consistency_release();
    111 #endif
    112 
    113 #if TSAN_COLLECT_STATS
    114 void build_consistency_stats();
    115 #else
    116 void build_consistency_nostats();
    117 #endif
    118 
    119 static inline void USED build_consistency() {
    120 #if SANITIZER_DEBUG
    121   build_consistency_debug();
    122 #else
    123   build_consistency_release();
    124 #endif
    125 #if TSAN_COLLECT_STATS
    126   build_consistency_stats();
    127 #else
    128   build_consistency_nostats();
    129 #endif
    130 }
    131 
    132 template<typename T>
    133 T min(T a, T b) {
    134   return a < b ? a : b;
    135 }
    136 
    137 template<typename T>
    138 T max(T a, T b) {
    139   return a > b ? a : b;
    140 }
    141 
    142 template<typename T>
    143 T RoundUp(T p, u64 align) {
    144   DCHECK_EQ(align & (align - 1), 0);
    145   return (T)(((u64)p + align - 1) & ~(align - 1));
    146 }
    147 
    148 template<typename T>
    149 T RoundDown(T p, u64 align) {
    150   DCHECK_EQ(align & (align - 1), 0);
    151   return (T)((u64)p & ~(align - 1));
    152 }
    153 
    154 // Zeroizes high part, returns 'bits' lsb bits.
    155 template<typename T>
    156 T GetLsb(T v, int bits) {
    157   return (T)((u64)v & ((1ull << bits) - 1));
    158 }
    159 
    160 struct MD5Hash {
    161   u64 hash[2];
    162   bool operator==(const MD5Hash &other) const;
    163 };
    164 
    165 MD5Hash md5_hash(const void *data, uptr size);
    166 
    167 struct Processor;
    168 struct ThreadState;
    169 class ThreadContext;
    170 struct Context;
    171 struct ReportStack;
    172 class ReportDesc;
    173 class RegionAlloc;
    174 
    175 // Descriptor of user's memory block.
    176 struct MBlock {
    177   u64  siz : 48;
    178   u64  tag : 16;
    179   u32  stk;
    180   u16  tid;
    181 };
    182 
    183 COMPILER_CHECK(sizeof(MBlock) == 16);
    184 
    185 enum ExternalTag : uptr {
    186   kExternalTagNone = 0,
    187   kExternalTagSwiftModifyingAccess = 1,
    188   kExternalTagFirstUserAvailable = 2,
    189   kExternalTagMax = 1024,
    190   // Don't set kExternalTagMax over 65,536, since MBlock only stores tags
    191   // as 16-bit values, see tsan_defs.h.
    192 };
    193 
    194 }  // namespace __tsan
    195 
    196 #endif  // TSAN_DEFS_H
    197