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