1*7c3d14c8STreehugger Robot //===-- tsan_sync.h ---------------------------------------------*- C++ -*-===// 2*7c3d14c8STreehugger Robot // 3*7c3d14c8STreehugger Robot // The LLVM Compiler Infrastructure 4*7c3d14c8STreehugger Robot // 5*7c3d14c8STreehugger Robot // This file is distributed under the University of Illinois Open Source 6*7c3d14c8STreehugger Robot // License. See LICENSE.TXT for details. 7*7c3d14c8STreehugger Robot // 8*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===// 9*7c3d14c8STreehugger Robot // 10*7c3d14c8STreehugger Robot // This file is a part of ThreadSanitizer (TSan), a race detector. 11*7c3d14c8STreehugger Robot // 12*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===// 13*7c3d14c8STreehugger Robot #ifndef TSAN_SYNC_H 14*7c3d14c8STreehugger Robot #define TSAN_SYNC_H 15*7c3d14c8STreehugger Robot 16*7c3d14c8STreehugger Robot #include "sanitizer_common/sanitizer_atomic.h" 17*7c3d14c8STreehugger Robot #include "sanitizer_common/sanitizer_common.h" 18*7c3d14c8STreehugger Robot #include "sanitizer_common/sanitizer_deadlock_detector_interface.h" 19*7c3d14c8STreehugger Robot #include "tsan_defs.h" 20*7c3d14c8STreehugger Robot #include "tsan_clock.h" 21*7c3d14c8STreehugger Robot #include "tsan_mutex.h" 22*7c3d14c8STreehugger Robot #include "tsan_dense_alloc.h" 23*7c3d14c8STreehugger Robot 24*7c3d14c8STreehugger Robot namespace __tsan { 25*7c3d14c8STreehugger Robot 26*7c3d14c8STreehugger Robot struct SyncVar { 27*7c3d14c8STreehugger Robot SyncVar(); 28*7c3d14c8STreehugger Robot 29*7c3d14c8STreehugger Robot static const int kInvalidTid = -1; 30*7c3d14c8STreehugger Robot 31*7c3d14c8STreehugger Robot uptr addr; // overwritten by DenseSlabAlloc freelist 32*7c3d14c8STreehugger Robot Mutex mtx; 33*7c3d14c8STreehugger Robot u64 uid; // Globally unique id. 34*7c3d14c8STreehugger Robot u32 creation_stack_id; 35*7c3d14c8STreehugger Robot int owner_tid; // Set only by exclusive owners. 36*7c3d14c8STreehugger Robot u64 last_lock; 37*7c3d14c8STreehugger Robot int recursion; 38*7c3d14c8STreehugger Robot bool is_rw; 39*7c3d14c8STreehugger Robot bool is_recursive; 40*7c3d14c8STreehugger Robot bool is_broken; 41*7c3d14c8STreehugger Robot bool is_linker_init; 42*7c3d14c8STreehugger Robot u32 next; // in MetaMap 43*7c3d14c8STreehugger Robot DDMutex dd; 44*7c3d14c8STreehugger Robot SyncClock read_clock; // Used for rw mutexes only. 45*7c3d14c8STreehugger Robot // The clock is placed last, so that it is situated on a different cache line 46*7c3d14c8STreehugger Robot // with the mtx. This reduces contention for hot sync objects. 47*7c3d14c8STreehugger Robot SyncClock clock; 48*7c3d14c8STreehugger Robot 49*7c3d14c8STreehugger Robot void Init(ThreadState *thr, uptr pc, uptr addr, u64 uid); 50*7c3d14c8STreehugger Robot void Reset(Processor *proc); 51*7c3d14c8STreehugger Robot GetIdSyncVar52*7c3d14c8STreehugger Robot u64 GetId() const { 53*7c3d14c8STreehugger Robot // 47 lsb is addr, then 14 bits is low part of uid, then 3 zero bits. 54*7c3d14c8STreehugger Robot return GetLsb((u64)addr | (uid << 47), 61); 55*7c3d14c8STreehugger Robot } CheckIdSyncVar56*7c3d14c8STreehugger Robot bool CheckId(u64 uid) const { 57*7c3d14c8STreehugger Robot CHECK_EQ(uid, GetLsb(uid, 14)); 58*7c3d14c8STreehugger Robot return GetLsb(this->uid, 14) == uid; 59*7c3d14c8STreehugger Robot } SplitIdSyncVar60*7c3d14c8STreehugger Robot static uptr SplitId(u64 id, u64 *uid) { 61*7c3d14c8STreehugger Robot *uid = id >> 47; 62*7c3d14c8STreehugger Robot return (uptr)GetLsb(id, 47); 63*7c3d14c8STreehugger Robot } 64*7c3d14c8STreehugger Robot }; 65*7c3d14c8STreehugger Robot 66*7c3d14c8STreehugger Robot /* MetaMap allows to map arbitrary user pointers onto various descriptors. 67*7c3d14c8STreehugger Robot Currently it maps pointers to heap block descriptors and sync var descs. 68*7c3d14c8STreehugger Robot It uses 1/2 direct shadow, see tsan_platform.h. 69*7c3d14c8STreehugger Robot */ 70*7c3d14c8STreehugger Robot class MetaMap { 71*7c3d14c8STreehugger Robot public: 72*7c3d14c8STreehugger Robot MetaMap(); 73*7c3d14c8STreehugger Robot 74*7c3d14c8STreehugger Robot void AllocBlock(ThreadState *thr, uptr pc, uptr p, uptr sz); 75*7c3d14c8STreehugger Robot uptr FreeBlock(Processor *proc, uptr p); 76*7c3d14c8STreehugger Robot bool FreeRange(Processor *proc, uptr p, uptr sz); 77*7c3d14c8STreehugger Robot void ResetRange(Processor *proc, uptr p, uptr sz); 78*7c3d14c8STreehugger Robot MBlock* GetBlock(uptr p); 79*7c3d14c8STreehugger Robot 80*7c3d14c8STreehugger Robot SyncVar* GetOrCreateAndLock(ThreadState *thr, uptr pc, 81*7c3d14c8STreehugger Robot uptr addr, bool write_lock); 82*7c3d14c8STreehugger Robot SyncVar* GetIfExistsAndLock(uptr addr, bool write_lock); 83*7c3d14c8STreehugger Robot 84*7c3d14c8STreehugger Robot void MoveMemory(uptr src, uptr dst, uptr sz); 85*7c3d14c8STreehugger Robot 86*7c3d14c8STreehugger Robot void OnProcIdle(Processor *proc); 87*7c3d14c8STreehugger Robot 88*7c3d14c8STreehugger Robot private: 89*7c3d14c8STreehugger Robot static const u32 kFlagMask = 3u << 30; 90*7c3d14c8STreehugger Robot static const u32 kFlagBlock = 1u << 30; 91*7c3d14c8STreehugger Robot static const u32 kFlagSync = 2u << 30; 92*7c3d14c8STreehugger Robot typedef DenseSlabAlloc<MBlock, 1<<16, 1<<12> BlockAlloc; 93*7c3d14c8STreehugger Robot typedef DenseSlabAlloc<SyncVar, 1<<16, 1<<10> SyncAlloc; 94*7c3d14c8STreehugger Robot BlockAlloc block_alloc_; 95*7c3d14c8STreehugger Robot SyncAlloc sync_alloc_; 96*7c3d14c8STreehugger Robot atomic_uint64_t uid_gen_; 97*7c3d14c8STreehugger Robot 98*7c3d14c8STreehugger Robot SyncVar* GetAndLock(ThreadState *thr, uptr pc, uptr addr, bool write_lock, 99*7c3d14c8STreehugger Robot bool create); 100*7c3d14c8STreehugger Robot }; 101*7c3d14c8STreehugger Robot 102*7c3d14c8STreehugger Robot } // namespace __tsan 103*7c3d14c8STreehugger Robot 104*7c3d14c8STreehugger Robot #endif // TSAN_SYNC_H 105