gcc/
[official-gcc.git] / libsanitizer / tsan / tsan_sync.h
blob3838df91d7574e727d433b7bf083599acb16b904
1 //===-- tsan_sync.h ---------------------------------------------*- C++ -*-===//
2 //
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // This file is a part of ThreadSanitizer (TSan), a race detector.
9 //
10 //===----------------------------------------------------------------------===//
11 #ifndef TSAN_SYNC_H
12 #define TSAN_SYNC_H
14 #include "sanitizer_common/sanitizer_atomic.h"
15 #include "sanitizer_common/sanitizer_common.h"
16 #include "sanitizer_common/sanitizer_deadlock_detector_interface.h"
17 #include "tsan_clock.h"
18 #include "tsan_defs.h"
19 #include "tsan_mutex.h"
21 namespace __tsan {
23 class StackTrace {
24 public:
25 StackTrace();
26 // Initialized the object in "static mode",
27 // in this mode it never calls malloc/free but uses the provided buffer.
28 StackTrace(uptr *buf, uptr cnt);
29 ~StackTrace();
30 void Reset();
32 void Init(const uptr *pcs, uptr cnt);
33 void ObtainCurrent(ThreadState *thr, uptr toppc);
34 bool IsEmpty() const;
35 uptr Size() const;
36 uptr Get(uptr i) const;
37 const uptr *Begin() const;
38 void CopyFrom(const StackTrace& other);
40 private:
41 uptr n_;
42 uptr *s_;
43 const uptr c_;
45 StackTrace(const StackTrace&);
46 void operator = (const StackTrace&);
49 struct SyncVar {
50 explicit SyncVar(uptr addr, u64 uid);
52 static const int kInvalidTid = -1;
54 Mutex mtx;
55 uptr addr;
56 const u64 uid; // Globally unique id.
57 u32 creation_stack_id;
58 int owner_tid; // Set only by exclusive owners.
59 u64 last_lock;
60 int recursion;
61 bool is_rw;
62 bool is_recursive;
63 bool is_broken;
64 bool is_linker_init;
65 SyncVar *next; // In SyncTab hashtable.
66 DDMutex dd;
67 SyncClock read_clock; // Used for rw mutexes only.
68 // The clock is placed last, so that it is situated on a different cache line
69 // with the mtx. This reduces contention for hot sync objects.
70 SyncClock clock;
72 u64 GetId() const {
73 // 47 lsb is addr, then 14 bits is low part of uid, then 3 zero bits.
74 return GetLsb((u64)addr | (uid << 47), 61);
76 bool CheckId(u64 uid) const {
77 CHECK_EQ(uid, GetLsb(uid, 14));
78 return GetLsb(this->uid, 14) == uid;
80 static uptr SplitId(u64 id, u64 *uid) {
81 *uid = id >> 47;
82 return (uptr)GetLsb(id, 47);
86 class SyncTab {
87 public:
88 SyncTab();
89 ~SyncTab();
91 SyncVar* GetOrCreateAndLock(ThreadState *thr, uptr pc,
92 uptr addr, bool write_lock);
93 SyncVar* GetIfExistsAndLock(uptr addr, bool write_lock);
95 // If the SyncVar does not exist, returns 0.
96 SyncVar* GetAndRemove(ThreadState *thr, uptr pc, uptr addr);
98 SyncVar* Create(ThreadState *thr, uptr pc, uptr addr);
100 private:
101 struct Part {
102 Mutex mtx;
103 SyncVar *val;
104 char pad[kCacheLineSize - sizeof(Mutex) - sizeof(SyncVar*)]; // NOLINT
105 Part();
108 // FIXME: Implement something more sane.
109 static const int kPartCount = 1009;
110 Part tab_[kPartCount];
111 atomic_uint64_t uid_gen_;
113 int PartIdx(uptr addr);
115 SyncVar* GetAndLock(ThreadState *thr, uptr pc,
116 uptr addr, bool write_lock, bool create);
118 SyncTab(const SyncTab&); // Not implemented.
119 void operator = (const SyncTab&); // Not implemented.
122 } // namespace __tsan
124 #endif // TSAN_SYNC_H