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