Home | History | Annotate | Line # | Download | only in tsan
      1  1.1  mrg //===-- tsan_shadow.h -------------------------------------------*- C++ -*-===//
      2  1.1  mrg //
      3  1.1  mrg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4  1.1  mrg // See https://llvm.org/LICENSE.txt for license information.
      5  1.1  mrg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6  1.1  mrg //
      7  1.1  mrg //===----------------------------------------------------------------------===//
      8  1.1  mrg 
      9  1.1  mrg #ifndef TSAN_SHADOW_H
     10  1.1  mrg #define TSAN_SHADOW_H
     11  1.1  mrg 
     12  1.1  mrg #include "tsan_defs.h"
     13  1.1  mrg #include "tsan_trace.h"
     14  1.1  mrg 
     15  1.1  mrg namespace __tsan {
     16  1.1  mrg 
     17  1.1  mrg // FastState (from most significant bit):
     18  1.1  mrg //   ignore          : 1
     19  1.1  mrg //   tid             : kTidBits
     20  1.1  mrg //   unused          : -
     21  1.1  mrg //   history_size    : 3
     22  1.1  mrg //   epoch           : kClkBits
     23  1.1  mrg class FastState {
     24  1.1  mrg  public:
     25  1.1  mrg   FastState(u64 tid, u64 epoch) {
     26  1.1  mrg     x_ = tid << kTidShift;
     27  1.1  mrg     x_ |= epoch;
     28  1.1  mrg     DCHECK_EQ(tid, this->tid());
     29  1.1  mrg     DCHECK_EQ(epoch, this->epoch());
     30  1.1  mrg     DCHECK_EQ(GetIgnoreBit(), false);
     31  1.1  mrg   }
     32  1.1  mrg 
     33  1.1  mrg   explicit FastState(u64 x) : x_(x) {}
     34  1.1  mrg 
     35  1.1  mrg   u64 raw() const { return x_; }
     36  1.1  mrg 
     37  1.1  mrg   u64 tid() const {
     38  1.1  mrg     u64 res = (x_ & ~kIgnoreBit) >> kTidShift;
     39  1.1  mrg     return res;
     40  1.1  mrg   }
     41  1.1  mrg 
     42  1.1  mrg   u64 TidWithIgnore() const {
     43  1.1  mrg     u64 res = x_ >> kTidShift;
     44  1.1  mrg     return res;
     45  1.1  mrg   }
     46  1.1  mrg 
     47  1.1  mrg   u64 epoch() const {
     48  1.1  mrg     u64 res = x_ & ((1ull << kClkBits) - 1);
     49  1.1  mrg     return res;
     50  1.1  mrg   }
     51  1.1  mrg 
     52  1.1  mrg   void IncrementEpoch() {
     53  1.1  mrg     u64 old_epoch = epoch();
     54  1.1  mrg     x_ += 1;
     55  1.1  mrg     DCHECK_EQ(old_epoch + 1, epoch());
     56  1.1  mrg     (void)old_epoch;
     57  1.1  mrg   }
     58  1.1  mrg 
     59  1.1  mrg   void SetIgnoreBit() { x_ |= kIgnoreBit; }
     60  1.1  mrg   void ClearIgnoreBit() { x_ &= ~kIgnoreBit; }
     61  1.1  mrg   bool GetIgnoreBit() const { return (s64)x_ < 0; }
     62  1.1  mrg 
     63  1.1  mrg   void SetHistorySize(int hs) {
     64  1.1  mrg     CHECK_GE(hs, 0);
     65  1.1  mrg     CHECK_LE(hs, 7);
     66  1.1  mrg     x_ = (x_ & ~(kHistoryMask << kHistoryShift)) | (u64(hs) << kHistoryShift);
     67  1.1  mrg   }
     68  1.1  mrg 
     69  1.1  mrg   ALWAYS_INLINE
     70  1.1  mrg   int GetHistorySize() const {
     71  1.1  mrg     return (int)((x_ >> kHistoryShift) & kHistoryMask);
     72  1.1  mrg   }
     73  1.1  mrg 
     74  1.1  mrg   void ClearHistorySize() { SetHistorySize(0); }
     75  1.1  mrg 
     76  1.1  mrg   ALWAYS_INLINE
     77  1.1  mrg   u64 GetTracePos() const {
     78  1.1  mrg     const int hs = GetHistorySize();
     79  1.1  mrg     // When hs == 0, the trace consists of 2 parts.
     80  1.1  mrg     const u64 mask = (1ull << (kTracePartSizeBits + hs + 1)) - 1;
     81  1.1  mrg     return epoch() & mask;
     82  1.1  mrg   }
     83  1.1  mrg 
     84  1.1  mrg  private:
     85  1.1  mrg   friend class Shadow;
     86  1.1  mrg   static const int kTidShift = 64 - kTidBits - 1;
     87  1.1  mrg   static const u64 kIgnoreBit = 1ull << 63;
     88  1.1  mrg   static const u64 kFreedBit = 1ull << 63;
     89  1.1  mrg   static const u64 kHistoryShift = kClkBits;
     90  1.1  mrg   static const u64 kHistoryMask = 7;
     91  1.1  mrg   u64 x_;
     92  1.1  mrg };
     93  1.1  mrg 
     94  1.1  mrg // Shadow (from most significant bit):
     95  1.1  mrg //   freed           : 1
     96  1.1  mrg //   tid             : kTidBits
     97  1.1  mrg //   is_atomic       : 1
     98  1.1  mrg //   is_read         : 1
     99  1.1  mrg //   size_log        : 2
    100  1.1  mrg //   addr0           : 3
    101  1.1  mrg //   epoch           : kClkBits
    102  1.1  mrg class Shadow : public FastState {
    103  1.1  mrg  public:
    104  1.1  mrg   explicit Shadow(u64 x) : FastState(x) {}
    105  1.1  mrg 
    106  1.1  mrg   explicit Shadow(const FastState &s) : FastState(s.x_) { ClearHistorySize(); }
    107  1.1  mrg 
    108  1.1  mrg   void SetAddr0AndSizeLog(u64 addr0, unsigned kAccessSizeLog) {
    109  1.1  mrg     DCHECK_EQ((x_ >> kClkBits) & 31, 0);
    110  1.1  mrg     DCHECK_LE(addr0, 7);
    111  1.1  mrg     DCHECK_LE(kAccessSizeLog, 3);
    112  1.1  mrg     x_ |= ((kAccessSizeLog << 3) | addr0) << kClkBits;
    113  1.1  mrg     DCHECK_EQ(kAccessSizeLog, size_log());
    114  1.1  mrg     DCHECK_EQ(addr0, this->addr0());
    115  1.1  mrg   }
    116  1.1  mrg 
    117  1.1  mrg   void SetWrite(unsigned kAccessIsWrite) {
    118  1.1  mrg     DCHECK_EQ(x_ & kReadBit, 0);
    119  1.1  mrg     if (!kAccessIsWrite)
    120  1.1  mrg       x_ |= kReadBit;
    121  1.1  mrg     DCHECK_EQ(kAccessIsWrite, IsWrite());
    122  1.1  mrg   }
    123  1.1  mrg 
    124  1.1  mrg   void SetAtomic(bool kIsAtomic) {
    125  1.1  mrg     DCHECK(!IsAtomic());
    126  1.1  mrg     if (kIsAtomic)
    127  1.1  mrg       x_ |= kAtomicBit;
    128  1.1  mrg     DCHECK_EQ(IsAtomic(), kIsAtomic);
    129  1.1  mrg   }
    130  1.1  mrg 
    131  1.1  mrg   bool IsAtomic() const { return x_ & kAtomicBit; }
    132  1.1  mrg 
    133  1.1  mrg   bool IsZero() const { return x_ == 0; }
    134  1.1  mrg 
    135  1.1  mrg   static inline bool TidsAreEqual(const Shadow s1, const Shadow s2) {
    136  1.1  mrg     u64 shifted_xor = (s1.x_ ^ s2.x_) >> kTidShift;
    137  1.1  mrg     DCHECK_EQ(shifted_xor == 0, s1.TidWithIgnore() == s2.TidWithIgnore());
    138  1.1  mrg     return shifted_xor == 0;
    139  1.1  mrg   }
    140  1.1  mrg 
    141  1.1  mrg   static ALWAYS_INLINE bool Addr0AndSizeAreEqual(const Shadow s1,
    142  1.1  mrg                                                  const Shadow s2) {
    143  1.1  mrg     u64 masked_xor = ((s1.x_ ^ s2.x_) >> kClkBits) & 31;
    144  1.1  mrg     return masked_xor == 0;
    145  1.1  mrg   }
    146  1.1  mrg 
    147  1.1  mrg   static ALWAYS_INLINE bool TwoRangesIntersect(Shadow s1, Shadow s2,
    148  1.1  mrg                                                unsigned kS2AccessSize) {
    149  1.1  mrg     bool res = false;
    150  1.1  mrg     u64 diff = s1.addr0() - s2.addr0();
    151  1.1  mrg     if ((s64)diff < 0) {  // s1.addr0 < s2.addr0
    152  1.1  mrg       // if (s1.addr0() + size1) > s2.addr0()) return true;
    153  1.1  mrg       if (s1.size() > -diff)
    154  1.1  mrg         res = true;
    155  1.1  mrg     } else {
    156  1.1  mrg       // if (s2.addr0() + kS2AccessSize > s1.addr0()) return true;
    157  1.1  mrg       if (kS2AccessSize > diff)
    158  1.1  mrg         res = true;
    159  1.1  mrg     }
    160  1.1  mrg     DCHECK_EQ(res, TwoRangesIntersectSlow(s1, s2));
    161  1.1  mrg     DCHECK_EQ(res, TwoRangesIntersectSlow(s2, s1));
    162  1.1  mrg     return res;
    163  1.1  mrg   }
    164  1.1  mrg 
    165  1.1  mrg   u64 ALWAYS_INLINE addr0() const { return (x_ >> kClkBits) & 7; }
    166  1.1  mrg   u64 ALWAYS_INLINE size() const { return 1ull << size_log(); }
    167  1.1  mrg   bool ALWAYS_INLINE IsWrite() const { return !IsRead(); }
    168  1.1  mrg   bool ALWAYS_INLINE IsRead() const { return x_ & kReadBit; }
    169  1.1  mrg 
    170  1.1  mrg   // The idea behind the freed bit is as follows.
    171  1.1  mrg   // When the memory is freed (or otherwise unaccessible) we write to the shadow
    172  1.1  mrg   // values with tid/epoch related to the free and the freed bit set.
    173  1.1  mrg   // During memory accesses processing the freed bit is considered
    174  1.1  mrg   // as msb of tid. So any access races with shadow with freed bit set
    175  1.1  mrg   // (it is as if write from a thread with which we never synchronized before).
    176  1.1  mrg   // This allows us to detect accesses to freed memory w/o additional
    177  1.1  mrg   // overheads in memory access processing and at the same time restore
    178  1.1  mrg   // tid/epoch of free.
    179  1.1  mrg   void MarkAsFreed() { x_ |= kFreedBit; }
    180  1.1  mrg 
    181  1.1  mrg   bool IsFreed() const { return x_ & kFreedBit; }
    182  1.1  mrg 
    183  1.1  mrg   bool GetFreedAndReset() {
    184  1.1  mrg     bool res = x_ & kFreedBit;
    185  1.1  mrg     x_ &= ~kFreedBit;
    186  1.1  mrg     return res;
    187  1.1  mrg   }
    188  1.1  mrg 
    189  1.1  mrg   bool ALWAYS_INLINE IsBothReadsOrAtomic(bool kIsWrite, bool kIsAtomic) const {
    190  1.1  mrg     bool v = x_ & ((u64(kIsWrite ^ 1) << kReadShift) |
    191  1.1  mrg                    (u64(kIsAtomic) << kAtomicShift));
    192  1.1  mrg     DCHECK_EQ(v, (!IsWrite() && !kIsWrite) || (IsAtomic() && kIsAtomic));
    193  1.1  mrg     return v;
    194  1.1  mrg   }
    195  1.1  mrg 
    196  1.1  mrg   bool ALWAYS_INLINE IsRWNotWeaker(bool kIsWrite, bool kIsAtomic) const {
    197  1.1  mrg     bool v = ((x_ >> kReadShift) & 3) <= u64((kIsWrite ^ 1) | (kIsAtomic << 1));
    198  1.1  mrg     DCHECK_EQ(v, (IsAtomic() < kIsAtomic) ||
    199  1.1  mrg                      (IsAtomic() == kIsAtomic && !IsWrite() <= !kIsWrite));
    200  1.1  mrg     return v;
    201  1.1  mrg   }
    202  1.1  mrg 
    203  1.1  mrg   bool ALWAYS_INLINE IsRWWeakerOrEqual(bool kIsWrite, bool kIsAtomic) const {
    204  1.1  mrg     bool v = ((x_ >> kReadShift) & 3) >= u64((kIsWrite ^ 1) | (kIsAtomic << 1));
    205  1.1  mrg     DCHECK_EQ(v, (IsAtomic() > kIsAtomic) ||
    206  1.1  mrg                      (IsAtomic() == kIsAtomic && !IsWrite() >= !kIsWrite));
    207  1.1  mrg     return v;
    208  1.1  mrg   }
    209  1.1  mrg 
    210  1.1  mrg  private:
    211  1.1  mrg   static const u64 kReadShift = 5 + kClkBits;
    212  1.1  mrg   static const u64 kReadBit = 1ull << kReadShift;
    213  1.1  mrg   static const u64 kAtomicShift = 6 + kClkBits;
    214  1.1  mrg   static const u64 kAtomicBit = 1ull << kAtomicShift;
    215  1.1  mrg 
    216  1.1  mrg   u64 size_log() const { return (x_ >> (3 + kClkBits)) & 3; }
    217  1.1  mrg 
    218  1.1  mrg   static bool TwoRangesIntersectSlow(const Shadow s1, const Shadow s2) {
    219  1.1  mrg     if (s1.addr0() == s2.addr0())
    220  1.1  mrg       return true;
    221  1.1  mrg     if (s1.addr0() < s2.addr0() && s1.addr0() + s1.size() > s2.addr0())
    222  1.1  mrg       return true;
    223  1.1  mrg     if (s2.addr0() < s1.addr0() && s2.addr0() + s2.size() > s1.addr0())
    224  1.1  mrg       return true;
    225  1.1  mrg     return false;
    226  1.1  mrg   }
    227  1.1  mrg };
    228  1.1  mrg 
    229  1.1  mrg const RawShadow kShadowRodata = (RawShadow)-1;  // .rodata shadow marker
    230  1.1  mrg 
    231  1.1  mrg }  // namespace __tsan
    232  1.1  mrg 
    233  1.1  mrg #endif
    234