xref: /netbsd-src/external/gpl3/gcc/dist/libsanitizer/tsan/tsan_mutexset.h (revision ff6d591ca308ed13e9c5ae142cf113a246c2cdc6)
1 //===-- tsan_mutexset.h -----------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file is a part of ThreadSanitizer (TSan), a race detector.
10 //
11 // MutexSet holds the set of mutexes currently held by a thread.
12 //===----------------------------------------------------------------------===//
13 #ifndef TSAN_MUTEXSET_H
14 #define TSAN_MUTEXSET_H
15 
16 #include "tsan_defs.h"
17 
18 namespace __tsan {
19 
20 class MutexSet {
21  public:
22   // Holds limited number of mutexes.
23   // The oldest mutexes are discarded on overflow.
24   static constexpr uptr kMaxSize = 16;
25   struct Desc {
26     uptr addr;
27     StackID stack_id;
28     u64 id;
29     u64 epoch;
30     u32 seq;
31     u32 count;
32     bool write;
33 
DescDesc34     Desc() { internal_memset(this, 0, sizeof(*this)); }
DescDesc35     Desc(const Desc& other) { *this = other; }
36     Desc& operator=(const MutexSet::Desc& other) {
37       internal_memcpy(this, &other, sizeof(*this));
38       return *this;
39     }
40   };
41 
42   MutexSet();
43   // The 'id' is obtained from SyncVar::GetId().
44   void Add(u64 id, bool write, u64 epoch);
45   void Del(u64 id, bool write);
46   void Remove(u64 id);  // Removes the mutex completely (if it's destroyed).
47   void AddAddr(uptr addr, StackID stack_id, bool write);
48   void DelAddr(uptr addr, bool destroy = false);
49   uptr Size() const;
50   Desc Get(uptr i) const;
51 
52  private:
53 #if !SANITIZER_GO
54   u32 seq_ = 0;
55   uptr size_ = 0;
56   Desc descs_[kMaxSize];
57 
58   void RemovePos(uptr i);
59 #endif
60 };
61 
62 // MutexSet is too large to live on stack.
63 // DynamicMutexSet can be use used to create local MutexSet's.
64 class DynamicMutexSet {
65  public:
66   DynamicMutexSet();
67   ~DynamicMutexSet();
68   MutexSet* operator->() { return ptr_; }
69   operator MutexSet*() { return ptr_; }
70   DynamicMutexSet(const DynamicMutexSet&) = delete;
71   DynamicMutexSet& operator=(const DynamicMutexSet&) = delete;
72 
73  private:
74   MutexSet* ptr_;
75 #if SANITIZER_GO
76   MutexSet set_;
77 #endif
78 };
79 
80 // Go does not have mutexes, so do not spend memory and time.
81 // (Go sync.Mutex is actually a semaphore -- can be unlocked
82 // in different goroutine).
83 #if SANITIZER_GO
MutexSet()84 MutexSet::MutexSet() {}
Add(u64 id,bool write,u64 epoch)85 void MutexSet::Add(u64 id, bool write, u64 epoch) {}
Del(u64 id,bool write)86 void MutexSet::Del(u64 id, bool write) {}
Remove(u64 id)87 void MutexSet::Remove(u64 id) {}
AddAddr(uptr addr,StackID stack_id,bool write)88 void MutexSet::AddAddr(uptr addr, StackID stack_id, bool write) {}
DelAddr(uptr addr,bool destroy)89 void MutexSet::DelAddr(uptr addr, bool destroy) {}
Size()90 uptr MutexSet::Size() const { return 0; }
Get(uptr i)91 MutexSet::Desc MutexSet::Get(uptr i) const { return Desc(); }
DynamicMutexSet()92 DynamicMutexSet::DynamicMutexSet() : ptr_(&set_) {}
~DynamicMutexSet()93 DynamicMutexSet::~DynamicMutexSet() {}
94 #endif
95 
96 }  // namespace __tsan
97 
98 #endif  // TSAN_MUTEXSET_H
99