blob: 4e352cb81d1100b0c9cb9ab2de8c76c28d2d691c [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 Vyukovdc1caa72014-09-02 09:34:34 +000057 void Resize(ClockCache *c, uptr nclk);
Dmitry Vyukov70db9d42014-08-05 18:45:02 +000058 void Reset(ClockCache *c);
Dmitry Vyukovd23118c2014-03-24 18:54:20 +000059
60 void DebugDump(int(*printf)(const char *s, ...));
61
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000062 private:
Dmitry Vyukov70db9d42014-08-05 18:45:02 +000063 friend struct ThreadClock;
64 static const uptr kDirtyTids = 2;
65
Dmitry Vyukovd23118c2014-03-24 18:54:20 +000066 unsigned release_store_tid_;
Dmitry Vyukovb5eb8f02014-04-11 15:38:03 +000067 unsigned release_store_reused_;
Dmitry Vyukovd23118c2014-03-24 18:54:20 +000068 unsigned dirty_tids_[kDirtyTids];
Dmitry Vyukov70db9d42014-08-05 18:45:02 +000069 // tab_ contains indirect pointer to a 512b block using DenseSlabAlloc.
70 // If size_ <= 64, then tab_ points to an array with 64 ClockElem's.
71 // Otherwise, tab_ points to an array with 128 u32 elements,
72 // each pointing to the second-level 512b block with 64 ClockElem's.
73 ClockBlock *tab_;
74 u32 tab_idx_;
75 u32 size_;
76
77 ClockElem &elem(unsigned tid) const;
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000078};
79
80// The clock that lives in threads.
81struct ThreadClock {
82 public:
Dmitry Vyukov70db9d42014-08-05 18:45:02 +000083 typedef DenseSlabAllocCache Cache;
84
Dmitry Vyukovb5eb8f02014-04-11 15:38:03 +000085 explicit ThreadClock(unsigned tid, unsigned reused = 0);
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000086
Kostya Serebryany07c48052012-05-11 14:42:24 +000087 u64 get(unsigned tid) const {
Dmitry Vyukov302cebb2012-05-22 18:07:45 +000088 DCHECK_LT(tid, kMaxTidInClock);
Dmitry Vyukovb5eb8f02014-04-11 15:38:03 +000089 return clk_[tid].epoch;
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000090 }
91
Dmitry Vyukovd23118c2014-03-24 18:54:20 +000092 void set(unsigned tid, u64 v);
93
94 void set(u64 v) {
Dmitry Vyukovb5eb8f02014-04-11 15:38:03 +000095 DCHECK_GE(v, clk_[tid_].epoch);
96 clk_[tid_].epoch = v;
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000097 }
98
Dmitry Vyukovd23118c2014-03-24 18:54:20 +000099 void tick() {
Dmitry Vyukovb5eb8f02014-04-11 15:38:03 +0000100 clk_[tid_].epoch++;
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000101 }
102
103 uptr size() const {
104 return nclk_;
105 }
106
Dmitry Vyukov70db9d42014-08-05 18:45:02 +0000107 void acquire(ClockCache *c, const SyncClock *src);
108 void release(ClockCache *c, SyncClock *dst) const;
109 void acq_rel(ClockCache *c, SyncClock *dst);
110 void ReleaseStore(ClockCache *c, SyncClock *dst) const;
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000111
Dmitry Vyukovb5eb8f02014-04-11 15:38:03 +0000112 void DebugReset();
Dmitry Vyukovd23118c2014-03-24 18:54:20 +0000113 void DebugDump(int(*printf)(const char *s, ...));
114
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000115 private:
Dmitry Vyukovd23118c2014-03-24 18:54:20 +0000116 static const uptr kDirtyTids = SyncClock::kDirtyTids;
117 const unsigned tid_;
Dmitry Vyukovb5eb8f02014-04-11 15:38:03 +0000118 const unsigned reused_;
Dmitry Vyukovd23118c2014-03-24 18:54:20 +0000119 u64 last_acquire_;
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000120 uptr nclk_;
Dmitry Vyukovb5eb8f02014-04-11 15:38:03 +0000121 ClockElem clk_[kMaxTidInClock];
Dmitry Vyukovd23118c2014-03-24 18:54:20 +0000122
123 bool IsAlreadyAcquired(const SyncClock *src) const;
124 void UpdateCurrentThread(SyncClock *dst) const;
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000125};
126
127} // namespace __tsan
128
129#endif // TSAN_CLOCK_H