1 //===-- tsan_clock.h --------------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file is a part of ThreadSanitizer (TSan), a race detector. 11 // 12 //===----------------------------------------------------------------------===// 13 #ifndef TSAN_CLOCK_H 14 #define TSAN_CLOCK_H 15 16 #include "tsan_defs.h" 17 #include "tsan_vector.h" 18 19 namespace __tsan { 20 21 struct ClockElem { 22 u64 epoch : kClkBits; 23 u64 reused : 64 - kClkBits; 24 }; 25 26 // The clock that lives in sync variables (mutexes, atomics, etc). 27 class SyncClock { 28 public: 29 SyncClock(); 30 31 uptr size() const { 32 return clk_.Size(); 33 } 34 35 u64 get(unsigned tid) const { 36 DCHECK_LT(tid, clk_.Size()); 37 return clk_[tid].epoch; 38 } 39 40 void Reset(); 41 void Zero(); 42 43 void DebugDump(int(*printf)(const char *s, ...)); 44 45 private: 46 unsigned release_store_tid_; 47 unsigned release_store_reused_; 48 static const uptr kDirtyTids = 2; 49 unsigned dirty_tids_[kDirtyTids]; 50 mutable Vector<ClockElem> clk_; 51 friend struct ThreadClock; 52 }; 53 54 // The clock that lives in threads. 55 struct ThreadClock { 56 public: 57 explicit ThreadClock(unsigned tid, unsigned reused = 0); 58 59 u64 get(unsigned tid) const { 60 DCHECK_LT(tid, kMaxTidInClock); 61 return clk_[tid].epoch; 62 } 63 64 void set(unsigned tid, u64 v); 65 66 void set(u64 v) { 67 DCHECK_GE(v, clk_[tid_].epoch); 68 clk_[tid_].epoch = v; 69 } 70 71 void tick() { 72 clk_[tid_].epoch++; 73 } 74 75 uptr size() const { 76 return nclk_; 77 } 78 79 void acquire(const SyncClock *src); 80 void release(SyncClock *dst) const; 81 void acq_rel(SyncClock *dst); 82 void ReleaseStore(SyncClock *dst) const; 83 84 void DebugReset(); 85 void DebugDump(int(*printf)(const char *s, ...)); 86 87 private: 88 static const uptr kDirtyTids = SyncClock::kDirtyTids; 89 const unsigned tid_; 90 const unsigned reused_; 91 u64 last_acquire_; 92 uptr nclk_; 93 ClockElem clk_[kMaxTidInClock]; 94 95 bool IsAlreadyAcquired(const SyncClock *src) const; 96 void UpdateCurrentThread(SyncClock *dst) const; 97 }; 98 99 } // namespace __tsan 100 101 #endif // TSAN_CLOCK_H 102