tsan_sync.h revision 1.1.1.1
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
20namespace __tsan {
21
22class SlabCache;
23
24class 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
50struct 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
85class 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