tsan_shadow.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. //===-- tsan_shadow.h -------------------------------------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #ifndef TSAN_SHADOW_H
  9. #define TSAN_SHADOW_H
  10. #include "tsan_defs.h"
  11. namespace __tsan {
  12. class FastState {
  13. public:
  14. FastState() { Reset(); }
  15. void Reset() {
  16. part_.unused0_ = 0;
  17. part_.sid_ = static_cast<u8>(kFreeSid);
  18. part_.epoch_ = static_cast<u16>(kEpochLast);
  19. part_.unused1_ = 0;
  20. part_.ignore_accesses_ = false;
  21. }
  22. void SetSid(Sid sid) { part_.sid_ = static_cast<u8>(sid); }
  23. Sid sid() const { return static_cast<Sid>(part_.sid_); }
  24. Epoch epoch() const { return static_cast<Epoch>(part_.epoch_); }
  25. void SetEpoch(Epoch epoch) { part_.epoch_ = static_cast<u16>(epoch); }
  26. void SetIgnoreBit() { part_.ignore_accesses_ = 1; }
  27. void ClearIgnoreBit() { part_.ignore_accesses_ = 0; }
  28. bool GetIgnoreBit() const { return part_.ignore_accesses_; }
  29. private:
  30. friend class Shadow;
  31. struct Parts {
  32. u32 unused0_ : 8;
  33. u32 sid_ : 8;
  34. u32 epoch_ : kEpochBits;
  35. u32 unused1_ : 1;
  36. u32 ignore_accesses_ : 1;
  37. };
  38. union {
  39. Parts part_;
  40. u32 raw_;
  41. };
  42. };
  43. static_assert(sizeof(FastState) == kShadowSize, "bad FastState size");
  44. class Shadow {
  45. public:
  46. static constexpr RawShadow kEmpty = static_cast<RawShadow>(0);
  47. Shadow(FastState state, u32 addr, u32 size, AccessType typ) {
  48. raw_ = state.raw_;
  49. DCHECK_GT(size, 0);
  50. DCHECK_LE(size, 8);
  51. UNUSED Sid sid0 = part_.sid_;
  52. UNUSED u16 epoch0 = part_.epoch_;
  53. raw_ |= (!!(typ & kAccessAtomic) << kIsAtomicShift) |
  54. (!!(typ & kAccessRead) << kIsReadShift) |
  55. (((((1u << size) - 1) << (addr & 0x7)) & 0xff) << kAccessShift);
  56. // Note: we don't check kAccessAtomic because it overlaps with
  57. // FastState::ignore_accesses_ and it may be set spuriously.
  58. DCHECK_EQ(part_.is_read_, !!(typ & kAccessRead));
  59. DCHECK_EQ(sid(), sid0);
  60. DCHECK_EQ(epoch(), epoch0);
  61. }
  62. explicit Shadow(RawShadow x = Shadow::kEmpty) { raw_ = static_cast<u32>(x); }
  63. RawShadow raw() const { return static_cast<RawShadow>(raw_); }
  64. Sid sid() const { return part_.sid_; }
  65. Epoch epoch() const { return static_cast<Epoch>(part_.epoch_); }
  66. u8 access() const { return part_.access_; }
  67. void GetAccess(uptr *addr, uptr *size, AccessType *typ) const {
  68. DCHECK(part_.access_ != 0 || raw_ == static_cast<u32>(Shadow::kRodata));
  69. if (addr)
  70. *addr = part_.access_ ? __builtin_ffs(part_.access_) - 1 : 0;
  71. if (size)
  72. *size = part_.access_ == kFreeAccess ? kShadowCell
  73. : __builtin_popcount(part_.access_);
  74. if (typ) {
  75. *typ = part_.is_read_ ? kAccessRead : kAccessWrite;
  76. if (part_.is_atomic_)
  77. *typ |= kAccessAtomic;
  78. if (part_.access_ == kFreeAccess)
  79. *typ |= kAccessFree;
  80. }
  81. }
  82. ALWAYS_INLINE
  83. bool IsBothReadsOrAtomic(AccessType typ) const {
  84. u32 is_read = !!(typ & kAccessRead);
  85. u32 is_atomic = !!(typ & kAccessAtomic);
  86. bool res =
  87. raw_ & ((is_atomic << kIsAtomicShift) | (is_read << kIsReadShift));
  88. DCHECK_EQ(res,
  89. (part_.is_read_ && is_read) || (part_.is_atomic_ && is_atomic));
  90. return res;
  91. }
  92. ALWAYS_INLINE
  93. bool IsRWWeakerOrEqual(AccessType typ) const {
  94. u32 is_read = !!(typ & kAccessRead);
  95. u32 is_atomic = !!(typ & kAccessAtomic);
  96. UNUSED u32 res0 =
  97. (part_.is_atomic_ > is_atomic) ||
  98. (part_.is_atomic_ == is_atomic && part_.is_read_ >= is_read);
  99. #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
  100. const u32 kAtomicReadMask = (1 << kIsAtomicShift) | (1 << kIsReadShift);
  101. bool res = (raw_ & kAtomicReadMask) >=
  102. ((is_atomic << kIsAtomicShift) | (is_read << kIsReadShift));
  103. DCHECK_EQ(res, res0);
  104. return res;
  105. #else
  106. return res0;
  107. #endif
  108. }
  109. // The FreedMarker must not pass "the same access check" so that we don't
  110. // return from the race detection algorithm early.
  111. static RawShadow FreedMarker() {
  112. FastState fs;
  113. fs.SetSid(kFreeSid);
  114. fs.SetEpoch(kEpochLast);
  115. Shadow s(fs, 0, 8, kAccessWrite);
  116. return s.raw();
  117. }
  118. static RawShadow FreedInfo(Sid sid, Epoch epoch) {
  119. Shadow s;
  120. s.part_.sid_ = sid;
  121. s.part_.epoch_ = static_cast<u16>(epoch);
  122. s.part_.access_ = kFreeAccess;
  123. return s.raw();
  124. }
  125. private:
  126. struct Parts {
  127. u8 access_;
  128. Sid sid_;
  129. u16 epoch_ : kEpochBits;
  130. u16 is_read_ : 1;
  131. u16 is_atomic_ : 1;
  132. };
  133. union {
  134. Parts part_;
  135. u32 raw_;
  136. };
  137. static constexpr u8 kFreeAccess = 0x81;
  138. #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
  139. static constexpr uptr kAccessShift = 0;
  140. static constexpr uptr kIsReadShift = 30;
  141. static constexpr uptr kIsAtomicShift = 31;
  142. #else
  143. static constexpr uptr kAccessShift = 24;
  144. static constexpr uptr kIsReadShift = 1;
  145. static constexpr uptr kIsAtomicShift = 0;
  146. #endif
  147. public:
  148. // .rodata shadow marker, see MapRodata and ContainsSameAccessFast.
  149. static constexpr RawShadow kRodata =
  150. static_cast<RawShadow>(1 << kIsReadShift);
  151. };
  152. static_assert(sizeof(Shadow) == kShadowSize, "bad Shadow size");
  153. ALWAYS_INLINE RawShadow LoadShadow(RawShadow *p) {
  154. return static_cast<RawShadow>(
  155. atomic_load((atomic_uint32_t *)p, memory_order_relaxed));
  156. }
  157. ALWAYS_INLINE void StoreShadow(RawShadow *sp, RawShadow s) {
  158. atomic_store((atomic_uint32_t *)sp, static_cast<u32>(s),
  159. memory_order_relaxed);
  160. }
  161. } // namespace __tsan
  162. #endif