(root)/
gcc-13.2.0/
libsanitizer/
tsan/
tsan_defs.h
       1  //===-- tsan_defs.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  //
       9  // This file is a part of ThreadSanitizer (TSan), a race detector.
      10  //
      11  //===----------------------------------------------------------------------===//
      12  
      13  #ifndef TSAN_DEFS_H
      14  #define TSAN_DEFS_H
      15  
      16  #include "sanitizer_common/sanitizer_internal_defs.h"
      17  #include "sanitizer_common/sanitizer_libc.h"
      18  #include "sanitizer_common/sanitizer_mutex.h"
      19  #include "ubsan/ubsan_platform.h"
      20  
      21  #ifndef TSAN_VECTORIZE
      22  #  define TSAN_VECTORIZE __SSE4_2__
      23  #endif
      24  
      25  #if TSAN_VECTORIZE
      26  // <emmintrin.h> transitively includes <stdlib.h>,
      27  // and it's prohibited to include std headers into tsan runtime.
      28  // So we do this dirty trick.
      29  #  define _MM_MALLOC_H_INCLUDED
      30  #  define __MM_MALLOC_H
      31  #  include <emmintrin.h>
      32  #  include <smmintrin.h>
      33  #  define VECTOR_ALIGNED ALIGNED(16)
      34  typedef __m128i m128;
      35  #else
      36  #  define VECTOR_ALIGNED
      37  #endif
      38  
      39  // Setup defaults for compile definitions.
      40  #ifndef TSAN_NO_HISTORY
      41  # define TSAN_NO_HISTORY 0
      42  #endif
      43  
      44  #ifndef TSAN_CONTAINS_UBSAN
      45  # if CAN_SANITIZE_UB && !SANITIZER_GO
      46  #  define TSAN_CONTAINS_UBSAN 1
      47  # else
      48  #  define TSAN_CONTAINS_UBSAN 0
      49  # endif
      50  #endif
      51  
      52  namespace __tsan {
      53  
      54  constexpr uptr kByteBits = 8;
      55  
      56  // Thread slot ID.
      57  enum class Sid : u8 {};
      58  constexpr uptr kThreadSlotCount = 256;
      59  constexpr Sid kFreeSid = static_cast<Sid>(255);
      60  
      61  // Abstract time unit, vector clock element.
      62  enum class Epoch : u16 {};
      63  constexpr uptr kEpochBits = 14;
      64  constexpr Epoch kEpochZero = static_cast<Epoch>(0);
      65  constexpr Epoch kEpochOver = static_cast<Epoch>(1 << kEpochBits);
      66  constexpr Epoch kEpochLast = static_cast<Epoch>((1 << kEpochBits) - 1);
      67  
      68  inline Epoch EpochInc(Epoch epoch) {
      69    return static_cast<Epoch>(static_cast<u16>(epoch) + 1);
      70  }
      71  
      72  inline bool EpochOverflow(Epoch epoch) { return epoch == kEpochOver; }
      73  
      74  const uptr kShadowStackSize = 64 * 1024;
      75  
      76  // Count of shadow values in a shadow cell.
      77  const uptr kShadowCnt = 4;
      78  
      79  // That many user bytes are mapped onto a single shadow cell.
      80  const uptr kShadowCell = 8;
      81  
      82  // Single shadow value.
      83  enum class RawShadow : u32 {};
      84  const uptr kShadowSize = sizeof(RawShadow);
      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  // All addresses and PCs are assumed to be compressable to that many bits.
      97  const uptr kCompressedAddrBits = 44;
      98  
      99  #if TSAN_NO_HISTORY
     100  const bool kCollectHistory = false;
     101  #else
     102  const bool kCollectHistory = true;
     103  #endif
     104  
     105  // The following "build consistency" machinery ensures that all source files
     106  // are built in the same configuration. Inconsistent builds lead to
     107  // hard to debug crashes.
     108  #if SANITIZER_DEBUG
     109  void build_consistency_debug();
     110  #else
     111  void build_consistency_release();
     112  #endif
     113  
     114  static inline void USED build_consistency() {
     115  #if SANITIZER_DEBUG
     116    build_consistency_debug();
     117  #else
     118    build_consistency_release();
     119  #endif
     120  }
     121  
     122  template<typename T>
     123  T min(T a, T b) {
     124    return a < b ? a : b;
     125  }
     126  
     127  template<typename T>
     128  T max(T a, T b) {
     129    return a > b ? a : b;
     130  }
     131  
     132  template<typename T>
     133  T RoundUp(T p, u64 align) {
     134    DCHECK_EQ(align & (align - 1), 0);
     135    return (T)(((u64)p + align - 1) & ~(align - 1));
     136  }
     137  
     138  template<typename T>
     139  T RoundDown(T p, u64 align) {
     140    DCHECK_EQ(align & (align - 1), 0);
     141    return (T)((u64)p & ~(align - 1));
     142  }
     143  
     144  // Zeroizes high part, returns 'bits' lsb bits.
     145  template<typename T>
     146  T GetLsb(T v, int bits) {
     147    return (T)((u64)v & ((1ull << bits) - 1));
     148  }
     149  
     150  struct MD5Hash {
     151    u64 hash[2];
     152    bool operator==(const MD5Hash &other) const;
     153  };
     154  
     155  MD5Hash md5_hash(const void *data, uptr size);
     156  
     157  struct Processor;
     158  struct ThreadState;
     159  class ThreadContext;
     160  struct TidSlot;
     161  struct Context;
     162  struct ReportStack;
     163  class ReportDesc;
     164  class RegionAlloc;
     165  struct Trace;
     166  struct TracePart;
     167  
     168  typedef uptr AccessType;
     169  
     170  enum : AccessType {
     171    kAccessWrite = 0,
     172    kAccessRead = 1 << 0,
     173    kAccessAtomic = 1 << 1,
     174    kAccessVptr = 1 << 2,  // read or write of an object virtual table pointer
     175    kAccessFree = 1 << 3,  // synthetic memory access during memory freeing
     176    kAccessExternalPC = 1 << 4,  // access PC can have kExternalPCBit set
     177    kAccessCheckOnly = 1 << 5,   // check for races, but don't store
     178    kAccessNoRodata = 1 << 6,    // don't check for .rodata marker
     179    kAccessSlotLocked = 1 << 7,  // memory access with TidSlot locked
     180  };
     181  
     182  // Descriptor of user's memory block.
     183  struct MBlock {
     184    u64  siz : 48;
     185    u64  tag : 16;
     186    StackID stk;
     187    Tid tid;
     188  };
     189  
     190  COMPILER_CHECK(sizeof(MBlock) == 16);
     191  
     192  enum ExternalTag : uptr {
     193    kExternalTagNone = 0,
     194    kExternalTagSwiftModifyingAccess = 1,
     195    kExternalTagFirstUserAvailable = 2,
     196    kExternalTagMax = 1024,
     197    // Don't set kExternalTagMax over 65,536, since MBlock only stores tags
     198    // as 16-bit values, see tsan_defs.h.
     199  };
     200  
     201  enum {
     202    MutexTypeReport = MutexLastCommon,
     203    MutexTypeSyncVar,
     204    MutexTypeAnnotations,
     205    MutexTypeAtExit,
     206    MutexTypeFired,
     207    MutexTypeRacy,
     208    MutexTypeGlobalProc,
     209    MutexTypeInternalAlloc,
     210    MutexTypeTrace,
     211    MutexTypeSlot,
     212    MutexTypeSlots,
     213  };
     214  
     215  }  // namespace __tsan
     216  
     217  #endif  // TSAN_DEFS_H