xref: /openbsd-src/gnu/llvm/compiler-rt/lib/tsan/rtl/tsan_defs.h (revision 810390e339a5425391477d5d41c78d7cab2424ac)
13cab2bb3Spatrick //===-- tsan_defs.h ---------------------------------------------*- C++ -*-===//
23cab2bb3Spatrick //
33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information.
53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63cab2bb3Spatrick //
73cab2bb3Spatrick //===----------------------------------------------------------------------===//
83cab2bb3Spatrick //
93cab2bb3Spatrick // This file is a part of ThreadSanitizer (TSan), a race detector.
103cab2bb3Spatrick //
113cab2bb3Spatrick //===----------------------------------------------------------------------===//
123cab2bb3Spatrick 
133cab2bb3Spatrick #ifndef TSAN_DEFS_H
143cab2bb3Spatrick #define TSAN_DEFS_H
153cab2bb3Spatrick 
163cab2bb3Spatrick #include "sanitizer_common/sanitizer_internal_defs.h"
173cab2bb3Spatrick #include "sanitizer_common/sanitizer_libc.h"
18d89ec533Spatrick #include "sanitizer_common/sanitizer_mutex.h"
193cab2bb3Spatrick #include "ubsan/ubsan_platform.h"
203cab2bb3Spatrick 
21*810390e3Srobert #ifndef TSAN_VECTORIZE
22*810390e3Srobert #  define TSAN_VECTORIZE __SSE4_2__
23*810390e3Srobert #endif
24*810390e3Srobert 
25*810390e3Srobert #if TSAN_VECTORIZE
26*810390e3Srobert // <emmintrin.h> transitively includes <stdlib.h>,
27*810390e3Srobert // and it's prohibited to include std headers into tsan runtime.
28*810390e3Srobert // So we do this dirty trick.
29*810390e3Srobert #  define _MM_MALLOC_H_INCLUDED
30*810390e3Srobert #  define __MM_MALLOC_H
31*810390e3Srobert #  include <emmintrin.h>
32*810390e3Srobert #  include <smmintrin.h>
33*810390e3Srobert #  define VECTOR_ALIGNED ALIGNED(16)
34*810390e3Srobert typedef __m128i m128;
35*810390e3Srobert #else
36*810390e3Srobert #  define VECTOR_ALIGNED
37*810390e3Srobert #endif
38*810390e3Srobert 
393cab2bb3Spatrick // Setup defaults for compile definitions.
403cab2bb3Spatrick #ifndef TSAN_NO_HISTORY
413cab2bb3Spatrick # define TSAN_NO_HISTORY 0
423cab2bb3Spatrick #endif
433cab2bb3Spatrick 
443cab2bb3Spatrick #ifndef TSAN_CONTAINS_UBSAN
453cab2bb3Spatrick # if CAN_SANITIZE_UB && !SANITIZER_GO
463cab2bb3Spatrick #  define TSAN_CONTAINS_UBSAN 1
473cab2bb3Spatrick # else
483cab2bb3Spatrick #  define TSAN_CONTAINS_UBSAN 0
493cab2bb3Spatrick # endif
503cab2bb3Spatrick #endif
513cab2bb3Spatrick 
523cab2bb3Spatrick namespace __tsan {
533cab2bb3Spatrick 
54*810390e3Srobert constexpr uptr kByteBits = 8;
553cab2bb3Spatrick 
56*810390e3Srobert // Thread slot ID.
57*810390e3Srobert enum class Sid : u8 {};
58*810390e3Srobert constexpr uptr kThreadSlotCount = 256;
59*810390e3Srobert constexpr Sid kFreeSid = static_cast<Sid>(255);
603cab2bb3Spatrick 
61*810390e3Srobert // Abstract time unit, vector clock element.
62*810390e3Srobert enum class Epoch : u16 {};
63*810390e3Srobert constexpr uptr kEpochBits = 14;
64*810390e3Srobert constexpr Epoch kEpochZero = static_cast<Epoch>(0);
65*810390e3Srobert constexpr Epoch kEpochOver = static_cast<Epoch>(1 << kEpochBits);
66*810390e3Srobert constexpr Epoch kEpochLast = static_cast<Epoch>((1 << kEpochBits) - 1);
673cab2bb3Spatrick 
EpochInc(Epoch epoch)68*810390e3Srobert inline Epoch EpochInc(Epoch epoch) {
69*810390e3Srobert   return static_cast<Epoch>(static_cast<u16>(epoch) + 1);
703cab2bb3Spatrick }
713cab2bb3Spatrick 
EpochOverflow(Epoch epoch)72*810390e3Srobert inline bool EpochOverflow(Epoch epoch) { return epoch == kEpochOver; }
73*810390e3Srobert 
743cab2bb3Spatrick const uptr kShadowStackSize = 64 * 1024;
753cab2bb3Spatrick 
763cab2bb3Spatrick // Count of shadow values in a shadow cell.
773cab2bb3Spatrick const uptr kShadowCnt = 4;
783cab2bb3Spatrick 
793cab2bb3Spatrick // That many user bytes are mapped onto a single shadow cell.
803cab2bb3Spatrick const uptr kShadowCell = 8;
813cab2bb3Spatrick 
82*810390e3Srobert // Single shadow value.
83*810390e3Srobert enum class RawShadow : u32 {};
84*810390e3Srobert const uptr kShadowSize = sizeof(RawShadow);
853cab2bb3Spatrick 
863cab2bb3Spatrick // Shadow memory is kShadowMultiplier times larger than user memory.
873cab2bb3Spatrick const uptr kShadowMultiplier = kShadowSize * kShadowCnt / kShadowCell;
883cab2bb3Spatrick 
893cab2bb3Spatrick // That many user bytes are mapped onto a single meta shadow cell.
903cab2bb3Spatrick // Must be less or equal to minimal memory allocator alignment.
913cab2bb3Spatrick const uptr kMetaShadowCell = 8;
923cab2bb3Spatrick 
933cab2bb3Spatrick // Size of a single meta shadow value (u32).
943cab2bb3Spatrick const uptr kMetaShadowSize = 4;
953cab2bb3Spatrick 
96*810390e3Srobert // All addresses and PCs are assumed to be compressable to that many bits.
97*810390e3Srobert const uptr kCompressedAddrBits = 44;
98*810390e3Srobert 
993cab2bb3Spatrick #if TSAN_NO_HISTORY
1003cab2bb3Spatrick const bool kCollectHistory = false;
1013cab2bb3Spatrick #else
1023cab2bb3Spatrick const bool kCollectHistory = true;
1033cab2bb3Spatrick #endif
1043cab2bb3Spatrick 
1053cab2bb3Spatrick // The following "build consistency" machinery ensures that all source files
1063cab2bb3Spatrick // are built in the same configuration. Inconsistent builds lead to
1073cab2bb3Spatrick // hard to debug crashes.
1083cab2bb3Spatrick #if SANITIZER_DEBUG
1093cab2bb3Spatrick void build_consistency_debug();
1103cab2bb3Spatrick #else
1113cab2bb3Spatrick void build_consistency_release();
1123cab2bb3Spatrick #endif
1133cab2bb3Spatrick 
build_consistency()1143cab2bb3Spatrick static inline void USED build_consistency() {
1153cab2bb3Spatrick #if SANITIZER_DEBUG
1163cab2bb3Spatrick   build_consistency_debug();
1173cab2bb3Spatrick #else
1183cab2bb3Spatrick   build_consistency_release();
1193cab2bb3Spatrick #endif
1203cab2bb3Spatrick }
1213cab2bb3Spatrick 
1223cab2bb3Spatrick template<typename T>
min(T a,T b)1233cab2bb3Spatrick T min(T a, T b) {
1243cab2bb3Spatrick   return a < b ? a : b;
1253cab2bb3Spatrick }
1263cab2bb3Spatrick 
1273cab2bb3Spatrick template<typename T>
max(T a,T b)1283cab2bb3Spatrick T max(T a, T b) {
1293cab2bb3Spatrick   return a > b ? a : b;
1303cab2bb3Spatrick }
1313cab2bb3Spatrick 
1323cab2bb3Spatrick template<typename T>
RoundUp(T p,u64 align)1333cab2bb3Spatrick T RoundUp(T p, u64 align) {
1343cab2bb3Spatrick   DCHECK_EQ(align & (align - 1), 0);
1353cab2bb3Spatrick   return (T)(((u64)p + align - 1) & ~(align - 1));
1363cab2bb3Spatrick }
1373cab2bb3Spatrick 
1383cab2bb3Spatrick template<typename T>
RoundDown(T p,u64 align)1393cab2bb3Spatrick T RoundDown(T p, u64 align) {
1403cab2bb3Spatrick   DCHECK_EQ(align & (align - 1), 0);
1413cab2bb3Spatrick   return (T)((u64)p & ~(align - 1));
1423cab2bb3Spatrick }
1433cab2bb3Spatrick 
1443cab2bb3Spatrick // Zeroizes high part, returns 'bits' lsb bits.
1453cab2bb3Spatrick template<typename T>
GetLsb(T v,int bits)1463cab2bb3Spatrick T GetLsb(T v, int bits) {
1473cab2bb3Spatrick   return (T)((u64)v & ((1ull << bits) - 1));
1483cab2bb3Spatrick }
1493cab2bb3Spatrick 
1503cab2bb3Spatrick struct MD5Hash {
1513cab2bb3Spatrick   u64 hash[2];
1523cab2bb3Spatrick   bool operator==(const MD5Hash &other) const;
1533cab2bb3Spatrick };
1543cab2bb3Spatrick 
1553cab2bb3Spatrick MD5Hash md5_hash(const void *data, uptr size);
1563cab2bb3Spatrick 
1573cab2bb3Spatrick struct Processor;
1583cab2bb3Spatrick struct ThreadState;
1593cab2bb3Spatrick class ThreadContext;
160*810390e3Srobert struct TidSlot;
1613cab2bb3Spatrick struct Context;
1623cab2bb3Spatrick struct ReportStack;
1633cab2bb3Spatrick class ReportDesc;
1643cab2bb3Spatrick class RegionAlloc;
165*810390e3Srobert struct Trace;
166*810390e3Srobert struct TracePart;
167*810390e3Srobert 
168*810390e3Srobert typedef uptr AccessType;
169*810390e3Srobert 
170*810390e3Srobert enum : AccessType {
171*810390e3Srobert   kAccessWrite = 0,
172*810390e3Srobert   kAccessRead = 1 << 0,
173*810390e3Srobert   kAccessAtomic = 1 << 1,
174*810390e3Srobert   kAccessVptr = 1 << 2,  // read or write of an object virtual table pointer
175*810390e3Srobert   kAccessFree = 1 << 3,  // synthetic memory access during memory freeing
176*810390e3Srobert   kAccessExternalPC = 1 << 4,  // access PC can have kExternalPCBit set
177*810390e3Srobert   kAccessCheckOnly = 1 << 5,   // check for races, but don't store
178*810390e3Srobert   kAccessNoRodata = 1 << 6,    // don't check for .rodata marker
179*810390e3Srobert   kAccessSlotLocked = 1 << 7,  // memory access with TidSlot locked
180*810390e3Srobert };
1813cab2bb3Spatrick 
1823cab2bb3Spatrick // Descriptor of user's memory block.
1833cab2bb3Spatrick struct MBlock {
1843cab2bb3Spatrick   u64  siz : 48;
1853cab2bb3Spatrick   u64  tag : 16;
186*810390e3Srobert   StackID stk;
187*810390e3Srobert   Tid tid;
1883cab2bb3Spatrick };
1893cab2bb3Spatrick 
1903cab2bb3Spatrick COMPILER_CHECK(sizeof(MBlock) == 16);
1913cab2bb3Spatrick 
1923cab2bb3Spatrick enum ExternalTag : uptr {
1933cab2bb3Spatrick   kExternalTagNone = 0,
1943cab2bb3Spatrick   kExternalTagSwiftModifyingAccess = 1,
1953cab2bb3Spatrick   kExternalTagFirstUserAvailable = 2,
1963cab2bb3Spatrick   kExternalTagMax = 1024,
1973cab2bb3Spatrick   // Don't set kExternalTagMax over 65,536, since MBlock only stores tags
1983cab2bb3Spatrick   // as 16-bit values, see tsan_defs.h.
1993cab2bb3Spatrick };
2003cab2bb3Spatrick 
201*810390e3Srobert enum {
202*810390e3Srobert   MutexTypeReport = MutexLastCommon,
203d89ec533Spatrick   MutexTypeSyncVar,
204d89ec533Spatrick   MutexTypeAnnotations,
205d89ec533Spatrick   MutexTypeAtExit,
206d89ec533Spatrick   MutexTypeFired,
207d89ec533Spatrick   MutexTypeRacy,
208d89ec533Spatrick   MutexTypeGlobalProc,
209*810390e3Srobert   MutexTypeInternalAlloc,
210*810390e3Srobert   MutexTypeTrace,
211*810390e3Srobert   MutexTypeSlot,
212*810390e3Srobert   MutexTypeSlots,
213d89ec533Spatrick };
214d89ec533Spatrick 
2153cab2bb3Spatrick }  // namespace __tsan
2163cab2bb3Spatrick 
2173cab2bb3Spatrick #endif  // TSAN_DEFS_H
218