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 19namespace __tsan { 20 21struct ClockElem { 22 u64 epoch : kClkBits; 23 u64 reused : 64 - kClkBits; 24}; 25 26// The clock that lives in sync variables (mutexes, atomics, etc). 27class 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. 55struct 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