Home | History | Annotate | Download | only in rtl
      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();
     73   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   }
     77   bool CheckId(u64 uid) const {
     78     CHECK_EQ(uid, GetLsb(uid, 14));
     79     return GetLsb(this->uid, 14) == uid;
     80   }
     81   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