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