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 "sanitizer_common/sanitizer_deadlock_detector_interface.h"
     19 #include "tsan_defs.h"
     20 #include "tsan_clock.h"
     21 #include "tsan_mutex.h"
     22 #include "tsan_dense_alloc.h"
     23 
     24 namespace __tsan {
     25 
     26 struct SyncVar {
     27   SyncVar();
     28 
     29   static const int kInvalidTid = -1;
     30 
     31   uptr addr;  // overwritten by DenseSlabAlloc freelist
     32   Mutex mtx;
     33   u64 uid;  // Globally unique id.
     34   u32 creation_stack_id;
     35   int owner_tid;  // Set only by exclusive owners.
     36   u64 last_lock;
     37   int recursion;
     38   bool is_rw;
     39   bool is_recursive;
     40   bool is_broken;
     41   bool is_linker_init;
     42   u32 next;  // in MetaMap
     43   DDMutex dd;
     44   SyncClock read_clock;  // Used for rw mutexes only.
     45   // The clock is placed last, so that it is situated on a different cache line
     46   // with the mtx. This reduces contention for hot sync objects.
     47   SyncClock clock;
     48 
     49   void Init(ThreadState *thr, uptr pc, uptr addr, u64 uid);
     50   void Reset(Processor *proc);
     51 
     52   u64 GetId() const {
     53     // 47 lsb is addr, then 14 bits is low part of uid, then 3 zero bits.
     54     return GetLsb((u64)addr | (uid << 47), 61);
     55   }
     56   bool CheckId(u64 uid) const {
     57     CHECK_EQ(uid, GetLsb(uid, 14));
     58     return GetLsb(this->uid, 14) == uid;
     59   }
     60   static uptr SplitId(u64 id, u64 *uid) {
     61     *uid = id >> 47;
     62     return (uptr)GetLsb(id, 47);
     63   }
     64 };
     65 
     66 /* MetaMap allows to map arbitrary user pointers onto various descriptors.
     67    Currently it maps pointers to heap block descriptors and sync var descs.
     68    It uses 1/2 direct shadow, see tsan_platform.h.
     69 */
     70 class MetaMap {
     71  public:
     72   MetaMap();
     73 
     74   void AllocBlock(ThreadState *thr, uptr pc, uptr p, uptr sz);
     75   uptr FreeBlock(Processor *proc, uptr p);
     76   bool FreeRange(Processor *proc, uptr p, uptr sz);
     77   void ResetRange(Processor *proc, uptr p, uptr sz);
     78   MBlock* GetBlock(uptr p);
     79 
     80   SyncVar* GetOrCreateAndLock(ThreadState *thr, uptr pc,
     81                               uptr addr, bool write_lock);
     82   SyncVar* GetIfExistsAndLock(uptr addr, bool write_lock);
     83 
     84   void MoveMemory(uptr src, uptr dst, uptr sz);
     85 
     86   void OnProcIdle(Processor *proc);
     87 
     88  private:
     89   static const u32 kFlagMask  = 3u << 30;
     90   static const u32 kFlagBlock = 1u << 30;
     91   static const u32 kFlagSync  = 2u << 30;
     92   typedef DenseSlabAlloc<MBlock, 1<<16, 1<<12> BlockAlloc;
     93   typedef DenseSlabAlloc<SyncVar, 1<<16, 1<<10> SyncAlloc;
     94   BlockAlloc block_alloc_;
     95   SyncAlloc sync_alloc_;
     96   atomic_uint64_t uid_gen_;
     97 
     98   SyncVar* GetAndLock(ThreadState *thr, uptr pc, uptr addr, bool write_lock,
     99                       bool create);
    100 };
    101 
    102 }  // namespace __tsan
    103 
    104 #endif  // TSAN_SYNC_H
    105