1*7c3d14c8STreehugger Robot //===-- tsan_clock.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_CLOCK_H 14*7c3d14c8STreehugger Robot #define TSAN_CLOCK_H 15*7c3d14c8STreehugger Robot 16*7c3d14c8STreehugger Robot #include "tsan_defs.h" 17*7c3d14c8STreehugger Robot #include "tsan_dense_alloc.h" 18*7c3d14c8STreehugger Robot 19*7c3d14c8STreehugger Robot namespace __tsan { 20*7c3d14c8STreehugger Robot 21*7c3d14c8STreehugger Robot struct ClockElem { 22*7c3d14c8STreehugger Robot u64 epoch : kClkBits; 23*7c3d14c8STreehugger Robot u64 reused : 64 - kClkBits; 24*7c3d14c8STreehugger Robot }; 25*7c3d14c8STreehugger Robot 26*7c3d14c8STreehugger Robot struct ClockBlock { 27*7c3d14c8STreehugger Robot static const uptr kSize = 512; 28*7c3d14c8STreehugger Robot static const uptr kTableSize = kSize / sizeof(u32); 29*7c3d14c8STreehugger Robot static const uptr kClockCount = kSize / sizeof(ClockElem); 30*7c3d14c8STreehugger Robot 31*7c3d14c8STreehugger Robot union { 32*7c3d14c8STreehugger Robot u32 table[kTableSize]; 33*7c3d14c8STreehugger Robot ClockElem clock[kClockCount]; 34*7c3d14c8STreehugger Robot }; 35*7c3d14c8STreehugger Robot ClockBlockClockBlock36*7c3d14c8STreehugger Robot ClockBlock() { 37*7c3d14c8STreehugger Robot } 38*7c3d14c8STreehugger Robot }; 39*7c3d14c8STreehugger Robot 40*7c3d14c8STreehugger Robot typedef DenseSlabAlloc<ClockBlock, 1<<16, 1<<10> ClockAlloc; 41*7c3d14c8STreehugger Robot typedef DenseSlabAllocCache ClockCache; 42*7c3d14c8STreehugger Robot 43*7c3d14c8STreehugger Robot // The clock that lives in sync variables (mutexes, atomics, etc). 44*7c3d14c8STreehugger Robot class SyncClock { 45*7c3d14c8STreehugger Robot public: 46*7c3d14c8STreehugger Robot SyncClock(); 47*7c3d14c8STreehugger Robot ~SyncClock(); 48*7c3d14c8STreehugger Robot size()49*7c3d14c8STreehugger Robot uptr size() const { 50*7c3d14c8STreehugger Robot return size_; 51*7c3d14c8STreehugger Robot } 52*7c3d14c8STreehugger Robot get(unsigned tid)53*7c3d14c8STreehugger Robot u64 get(unsigned tid) const { 54*7c3d14c8STreehugger Robot return elem(tid).epoch; 55*7c3d14c8STreehugger Robot } 56*7c3d14c8STreehugger Robot 57*7c3d14c8STreehugger Robot void Resize(ClockCache *c, uptr nclk); 58*7c3d14c8STreehugger Robot void Reset(ClockCache *c); 59*7c3d14c8STreehugger Robot 60*7c3d14c8STreehugger Robot void DebugDump(int(*printf)(const char *s, ...)); 61*7c3d14c8STreehugger Robot 62*7c3d14c8STreehugger Robot private: 63*7c3d14c8STreehugger Robot friend struct ThreadClock; 64*7c3d14c8STreehugger Robot static const uptr kDirtyTids = 2; 65*7c3d14c8STreehugger Robot 66*7c3d14c8STreehugger Robot unsigned release_store_tid_; 67*7c3d14c8STreehugger Robot unsigned release_store_reused_; 68*7c3d14c8STreehugger Robot unsigned dirty_tids_[kDirtyTids]; 69*7c3d14c8STreehugger Robot // tab_ contains indirect pointer to a 512b block using DenseSlabAlloc. 70*7c3d14c8STreehugger Robot // If size_ <= 64, then tab_ points to an array with 64 ClockElem's. 71*7c3d14c8STreehugger Robot // Otherwise, tab_ points to an array with 128 u32 elements, 72*7c3d14c8STreehugger Robot // each pointing to the second-level 512b block with 64 ClockElem's. 73*7c3d14c8STreehugger Robot ClockBlock *tab_; 74*7c3d14c8STreehugger Robot u32 tab_idx_; 75*7c3d14c8STreehugger Robot u32 size_; 76*7c3d14c8STreehugger Robot 77*7c3d14c8STreehugger Robot ClockElem &elem(unsigned tid) const; 78*7c3d14c8STreehugger Robot }; 79*7c3d14c8STreehugger Robot 80*7c3d14c8STreehugger Robot // The clock that lives in threads. 81*7c3d14c8STreehugger Robot struct ThreadClock { 82*7c3d14c8STreehugger Robot public: 83*7c3d14c8STreehugger Robot typedef DenseSlabAllocCache Cache; 84*7c3d14c8STreehugger Robot 85*7c3d14c8STreehugger Robot explicit ThreadClock(unsigned tid, unsigned reused = 0); 86*7c3d14c8STreehugger Robot getThreadClock87*7c3d14c8STreehugger Robot u64 get(unsigned tid) const { 88*7c3d14c8STreehugger Robot DCHECK_LT(tid, kMaxTidInClock); 89*7c3d14c8STreehugger Robot return clk_[tid].epoch; 90*7c3d14c8STreehugger Robot } 91*7c3d14c8STreehugger Robot 92*7c3d14c8STreehugger Robot void set(unsigned tid, u64 v); 93*7c3d14c8STreehugger Robot setThreadClock94*7c3d14c8STreehugger Robot void set(u64 v) { 95*7c3d14c8STreehugger Robot DCHECK_GE(v, clk_[tid_].epoch); 96*7c3d14c8STreehugger Robot clk_[tid_].epoch = v; 97*7c3d14c8STreehugger Robot } 98*7c3d14c8STreehugger Robot tickThreadClock99*7c3d14c8STreehugger Robot void tick() { 100*7c3d14c8STreehugger Robot clk_[tid_].epoch++; 101*7c3d14c8STreehugger Robot } 102*7c3d14c8STreehugger Robot sizeThreadClock103*7c3d14c8STreehugger Robot uptr size() const { 104*7c3d14c8STreehugger Robot return nclk_; 105*7c3d14c8STreehugger Robot } 106*7c3d14c8STreehugger Robot 107*7c3d14c8STreehugger Robot void acquire(ClockCache *c, const SyncClock *src); 108*7c3d14c8STreehugger Robot void release(ClockCache *c, SyncClock *dst) const; 109*7c3d14c8STreehugger Robot void acq_rel(ClockCache *c, SyncClock *dst); 110*7c3d14c8STreehugger Robot void ReleaseStore(ClockCache *c, SyncClock *dst) const; 111*7c3d14c8STreehugger Robot 112*7c3d14c8STreehugger Robot void DebugReset(); 113*7c3d14c8STreehugger Robot void DebugDump(int(*printf)(const char *s, ...)); 114*7c3d14c8STreehugger Robot 115*7c3d14c8STreehugger Robot private: 116*7c3d14c8STreehugger Robot static const uptr kDirtyTids = SyncClock::kDirtyTids; 117*7c3d14c8STreehugger Robot const unsigned tid_; 118*7c3d14c8STreehugger Robot const unsigned reused_; 119*7c3d14c8STreehugger Robot u64 last_acquire_; 120*7c3d14c8STreehugger Robot uptr nclk_; 121*7c3d14c8STreehugger Robot ClockElem clk_[kMaxTidInClock]; 122*7c3d14c8STreehugger Robot 123*7c3d14c8STreehugger Robot bool IsAlreadyAcquired(const SyncClock *src) const; 124*7c3d14c8STreehugger Robot void UpdateCurrentThread(SyncClock *dst) const; 125*7c3d14c8STreehugger Robot }; 126*7c3d14c8STreehugger Robot 127*7c3d14c8STreehugger Robot } // namespace __tsan 128*7c3d14c8STreehugger Robot 129*7c3d14c8STreehugger Robot #endif // TSAN_CLOCK_H 130