xref: /netbsd-src/external/gpl3/gcc/dist/libsanitizer/tsan/tsan_sync.h (revision d11b170b9000ada93db553723522a63d5deac310)
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
13 
14 #include "sanitizer_common/sanitizer_atomic.h"
15 #include "sanitizer_common/sanitizer_common.h"
16 #include "tsan_clock.h"
17 #include "tsan_defs.h"
18 #include "tsan_mutex.h"
19 
20 namespace __tsan {
21 
22 class SlabCache;
23 
24 class StackTrace {
25  public:
26   StackTrace();
27   // Initialized the object in "static mode",
28   // in this mode it never calls malloc/free but uses the provided buffer.
29   StackTrace(uptr *buf, uptr cnt);
30   ~StackTrace();
31   void Reset();
32 
33   void Init(const uptr *pcs, uptr cnt);
34   void ObtainCurrent(ThreadState *thr, uptr toppc);
35   bool IsEmpty() const;
36   uptr Size() const;
37   uptr Get(uptr i) const;
38   const uptr *Begin() const;
39   void CopyFrom(const StackTrace& other);
40 
41  private:
42   uptr n_;
43   uptr *s_;
44   const uptr c_;
45 
46   StackTrace(const StackTrace&);
47   void operator = (const StackTrace&);
48 };
49 
50 struct SyncVar {
51   explicit SyncVar(uptr addr, u64 uid);
52 
53   static const int kInvalidTid = -1;
54 
55   Mutex mtx;
56   uptr addr;
57   const u64 uid;  // Globally unique id.
58   SyncClock clock;
59   SyncClock read_clock;  // Used for rw mutexes only.
60   StackTrace creation_stack;
61   int owner_tid;  // Set only by exclusive owners.
62   u64 last_lock;
63   int recursion;
64   bool is_rw;
65   bool is_recursive;
66   bool is_broken;
67   bool is_linker_init;
68   SyncVar *next;  // In SyncTab hashtable.
69 
70   uptr GetMemoryConsumption();
71   u64 GetId() const {
72     // 47 lsb is addr, then 14 bits is low part of uid, then 3 zero bits.
73     return GetLsb((u64)addr | (uid << 47), 61);
74   }
75   bool CheckId(u64 uid) const {
76     CHECK_EQ(uid, GetLsb(uid, 14));
77     return GetLsb(this->uid, 14) == uid;
78   }
79   static uptr SplitId(u64 id, u64 *uid) {
80     *uid = id >> 47;
81     return (uptr)GetLsb(id, 47);
82   }
83 };
84 
85 class SyncTab {
86  public:
87   SyncTab();
88   ~SyncTab();
89 
90   SyncVar* GetOrCreateAndLock(ThreadState *thr, uptr pc,
91                               uptr addr, bool write_lock);
92   SyncVar* GetIfExistsAndLock(uptr addr, bool write_lock);
93 
94   // If the SyncVar does not exist, returns 0.
95   SyncVar* GetAndRemove(ThreadState *thr, uptr pc, uptr addr);
96 
97   SyncVar* Create(ThreadState *thr, uptr pc, uptr addr);
98 
99   uptr GetMemoryConsumption(uptr *nsync);
100 
101  private:
102   struct Part {
103     Mutex mtx;
104     SyncVar *val;
105     char pad[kCacheLineSize - sizeof(Mutex) - sizeof(SyncVar*)];  // NOLINT
106     Part();
107   };
108 
109   // FIXME: Implement something more sane.
110   static const int kPartCount = 1009;
111   Part tab_[kPartCount];
112   atomic_uint64_t uid_gen_;
113 
114   int PartIdx(uptr addr);
115 
116   SyncVar* GetAndLock(ThreadState *thr, uptr pc,
117                       uptr addr, bool write_lock, bool create);
118 
119   SyncTab(const SyncTab&);  // Not implemented.
120   void operator = (const SyncTab&);  // Not implemented.
121 };
122 
123 }  // namespace __tsan
124 
125 #endif  // TSAN_SYNC_H
126