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