blob: f7ab69a3a816c4f23bf5f3a3351fe5896f8054ae [file] [log] [blame]
Kostya Serebryany4ad375f2012-05-10 13:48:04 +00001//===-- 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
Dmitry Vyukovb5eb8f02014-04-11 15:38:03 +000021struct ClockElem {
22 u64 epoch : kClkBits;
23 u64 reused : 64 - kClkBits;
24};
Dmitry Vyukovd23118c2014-03-24 18:54:20 +000025
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000026// 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
Dmitry Vyukovd23118c2014-03-24 18:54:20 +000035 u64 get(unsigned tid) const {
36 DCHECK_LT(tid, clk_.Size());
Dmitry Vyukovb5eb8f02014-04-11 15:38:03 +000037 return clk_[tid].epoch;
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000038 }
39
Dmitry Vyukovd23118c2014-03-24 18:54:20 +000040 void Reset();
Dmitry Vyukovbde4c9c2014-05-29 13:50:54 +000041 void Zero();
Dmitry Vyukovd23118c2014-03-24 18:54:20 +000042
43 void DebugDump(int(*printf)(const char *s, ...));
44
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000045 private:
Dmitry Vyukovd23118c2014-03-24 18:54:20 +000046 unsigned release_store_tid_;
Dmitry Vyukovb5eb8f02014-04-11 15:38:03 +000047 unsigned release_store_reused_;
Dmitry Vyukovd23118c2014-03-24 18:54:20 +000048 static const uptr kDirtyTids = 2;
49 unsigned dirty_tids_[kDirtyTids];
Dmitry Vyukovb5eb8f02014-04-11 15:38:03 +000050 mutable Vector<ClockElem> clk_;
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000051 friend struct ThreadClock;
52};
53
54// The clock that lives in threads.
55struct ThreadClock {
56 public:
Dmitry Vyukovb5eb8f02014-04-11 15:38:03 +000057 explicit ThreadClock(unsigned tid, unsigned reused = 0);
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000058
Kostya Serebryany07c48052012-05-11 14:42:24 +000059 u64 get(unsigned tid) const {
Dmitry Vyukov302cebb2012-05-22 18:07:45 +000060 DCHECK_LT(tid, kMaxTidInClock);
Dmitry Vyukovb5eb8f02014-04-11 15:38:03 +000061 return clk_[tid].epoch;
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000062 }
63
Dmitry Vyukovd23118c2014-03-24 18:54:20 +000064 void set(unsigned tid, u64 v);
65
66 void set(u64 v) {
Dmitry Vyukovb5eb8f02014-04-11 15:38:03 +000067 DCHECK_GE(v, clk_[tid_].epoch);
68 clk_[tid_].epoch = v;
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000069 }
70
Dmitry Vyukovd23118c2014-03-24 18:54:20 +000071 void tick() {
Dmitry Vyukovb5eb8f02014-04-11 15:38:03 +000072 clk_[tid_].epoch++;
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000073 }
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);
Dmitry Vyukov904d3f92012-07-28 15:27:41 +000082 void ReleaseStore(SyncClock *dst) const;
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000083
Dmitry Vyukovb5eb8f02014-04-11 15:38:03 +000084 void DebugReset();
Dmitry Vyukovd23118c2014-03-24 18:54:20 +000085 void DebugDump(int(*printf)(const char *s, ...));
86
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000087 private:
Dmitry Vyukovd23118c2014-03-24 18:54:20 +000088 static const uptr kDirtyTids = SyncClock::kDirtyTids;
89 const unsigned tid_;
Dmitry Vyukovb5eb8f02014-04-11 15:38:03 +000090 const unsigned reused_;
Dmitry Vyukovd23118c2014-03-24 18:54:20 +000091 u64 last_acquire_;
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000092 uptr nclk_;
Dmitry Vyukovb5eb8f02014-04-11 15:38:03 +000093 ClockElem clk_[kMaxTidInClock];
Dmitry Vyukovd23118c2014-03-24 18:54:20 +000094
95 bool IsAlreadyAcquired(const SyncClock *src) const;
96 void UpdateCurrentThread(SyncClock *dst) const;
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000097};
98
99} // namespace __tsan
100
101#endif // TSAN_CLOCK_H