blob: 7b4de555a87a682a74fc72ebd728d804e8df8df1 [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"
Dmitry Vyukov70db9d42014-08-05 18:45:02 +000017#include "tsan_dense_alloc.h"
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000018
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
Dmitry Vyukov70db9d42014-08-05 18:45:02 +000026struct ClockBlock {
27 static const uptr kSize = 512;
28 static const uptr kTableSize = kSize / sizeof(u32);
29 static const uptr kClockCount = kSize / sizeof(ClockElem);
30
31 union {
32 u32 table[kTableSize];
33 ClockElem clock[kClockCount];
34 };
35
36 ClockBlock() {
37 }
38};
39
40typedef DenseSlabAlloc<ClockBlock, 1<<16, 1<<10> ClockAlloc;
41typedef DenseSlabAllocCache ClockCache;
42
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000043// The clock that lives in sync variables (mutexes, atomics, etc).
44class SyncClock {
45 public:
46 SyncClock();
Dmitry Vyukov70db9d42014-08-05 18:45:02 +000047 ~SyncClock();
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000048
49 uptr size() const {
Dmitry Vyukov70db9d42014-08-05 18:45:02 +000050 return size_;
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000051 }
52
Dmitry Vyukovd23118c2014-03-24 18:54:20 +000053 u64 get(unsigned tid) const {
Dmitry Vyukov70db9d42014-08-05 18:45:02 +000054 return elem(tid).epoch;
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000055 }
56
Dmitry Vyukov70db9d42014-08-05 18:45:02 +000057 void Reset(ClockCache *c);
Dmitry Vyukovd23118c2014-03-24 18:54:20 +000058
59 void DebugDump(int(*printf)(const char *s, ...));
60
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000061 private:
Dmitry Vyukov70db9d42014-08-05 18:45:02 +000062 friend struct ThreadClock;
63 static const uptr kDirtyTids = 2;
64
Dmitry Vyukovd23118c2014-03-24 18:54:20 +000065 unsigned release_store_tid_;
Dmitry Vyukovb5eb8f02014-04-11 15:38:03 +000066 unsigned release_store_reused_;
Dmitry Vyukovd23118c2014-03-24 18:54:20 +000067 unsigned dirty_tids_[kDirtyTids];
Dmitry Vyukov70db9d42014-08-05 18:45:02 +000068 // tab_ contains indirect pointer to a 512b block using DenseSlabAlloc.
69 // If size_ <= 64, then tab_ points to an array with 64 ClockElem's.
70 // Otherwise, tab_ points to an array with 128 u32 elements,
71 // each pointing to the second-level 512b block with 64 ClockElem's.
72 ClockBlock *tab_;
73 u32 tab_idx_;
74 u32 size_;
75
76 ClockElem &elem(unsigned tid) const;
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000077};
78
79// The clock that lives in threads.
80struct ThreadClock {
81 public:
Dmitry Vyukov70db9d42014-08-05 18:45:02 +000082 typedef DenseSlabAllocCache Cache;
83
Dmitry Vyukovb5eb8f02014-04-11 15:38:03 +000084 explicit ThreadClock(unsigned tid, unsigned reused = 0);
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000085
Kostya Serebryany07c48052012-05-11 14:42:24 +000086 u64 get(unsigned tid) const {
Dmitry Vyukov302cebb2012-05-22 18:07:45 +000087 DCHECK_LT(tid, kMaxTidInClock);
Dmitry Vyukovb5eb8f02014-04-11 15:38:03 +000088 return clk_[tid].epoch;
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000089 }
90
Dmitry Vyukovd23118c2014-03-24 18:54:20 +000091 void set(unsigned tid, u64 v);
92
93 void set(u64 v) {
Dmitry Vyukovb5eb8f02014-04-11 15:38:03 +000094 DCHECK_GE(v, clk_[tid_].epoch);
95 clk_[tid_].epoch = v;
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000096 }
97
Dmitry Vyukovd23118c2014-03-24 18:54:20 +000098 void tick() {
Dmitry Vyukovb5eb8f02014-04-11 15:38:03 +000099 clk_[tid_].epoch++;
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000100 }
101
102 uptr size() const {
103 return nclk_;
104 }
105
Dmitry Vyukov70db9d42014-08-05 18:45:02 +0000106 void acquire(ClockCache *c, const SyncClock *src);
107 void release(ClockCache *c, SyncClock *dst) const;
108 void acq_rel(ClockCache *c, SyncClock *dst);
109 void ReleaseStore(ClockCache *c, SyncClock *dst) const;
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000110
Dmitry Vyukovb5eb8f02014-04-11 15:38:03 +0000111 void DebugReset();
Dmitry Vyukovd23118c2014-03-24 18:54:20 +0000112 void DebugDump(int(*printf)(const char *s, ...));
113
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000114 private:
Dmitry Vyukovd23118c2014-03-24 18:54:20 +0000115 static const uptr kDirtyTids = SyncClock::kDirtyTids;
116 const unsigned tid_;
Dmitry Vyukovb5eb8f02014-04-11 15:38:03 +0000117 const unsigned reused_;
Dmitry Vyukovd23118c2014-03-24 18:54:20 +0000118 u64 last_acquire_;
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000119 uptr nclk_;
Dmitry Vyukovb5eb8f02014-04-11 15:38:03 +0000120 ClockElem clk_[kMaxTidInClock];
Dmitry Vyukovd23118c2014-03-24 18:54:20 +0000121
122 bool IsAlreadyAcquired(const SyncClock *src) const;
123 void UpdateCurrentThread(SyncClock *dst) const;
Dmitry Vyukov70db9d42014-08-05 18:45:02 +0000124 void Resize(ClockCache *c, SyncClock *dst) const;
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000125};
126
127} // namespace __tsan
128
129#endif // TSAN_CLOCK_H