xref: /aosp_15_r20/external/compiler-rt/lib/tsan/rtl/tsan_clock.h (revision 7c3d14c8b49c529e04be81a3ce6f5cc23712e4c6)
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