xref: /openbsd-src/gnu/llvm/compiler-rt/lib/tsan/rtl/tsan_mutexset.h (revision 810390e339a5425391477d5d41c78d7cab2424ac)
13cab2bb3Spatrick //===-- tsan_mutexset.h -----------------------------------------*- C++ -*-===//
23cab2bb3Spatrick //
33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information.
53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63cab2bb3Spatrick //
73cab2bb3Spatrick //===----------------------------------------------------------------------===//
83cab2bb3Spatrick //
93cab2bb3Spatrick // This file is a part of ThreadSanitizer (TSan), a race detector.
103cab2bb3Spatrick //
113cab2bb3Spatrick // MutexSet holds the set of mutexes currently held by a thread.
123cab2bb3Spatrick //===----------------------------------------------------------------------===//
133cab2bb3Spatrick #ifndef TSAN_MUTEXSET_H
143cab2bb3Spatrick #define TSAN_MUTEXSET_H
153cab2bb3Spatrick 
163cab2bb3Spatrick #include "tsan_defs.h"
173cab2bb3Spatrick 
183cab2bb3Spatrick namespace __tsan {
193cab2bb3Spatrick 
203cab2bb3Spatrick class MutexSet {
213cab2bb3Spatrick  public:
223cab2bb3Spatrick   // Holds limited number of mutexes.
233cab2bb3Spatrick   // The oldest mutexes are discarded on overflow.
24*810390e3Srobert   static constexpr uptr kMaxSize = 16;
253cab2bb3Spatrick   struct Desc {
26*810390e3Srobert     uptr addr;
27*810390e3Srobert     StackID stack_id;
28*810390e3Srobert     u32 seq;
29*810390e3Srobert     u32 count;
303cab2bb3Spatrick     bool write;
31*810390e3Srobert 
DescDesc32*810390e3Srobert     Desc() { internal_memset(this, 0, sizeof(*this)); }
DescDesc33*810390e3Srobert     Desc(const Desc& other) { *this = other; }
34*810390e3Srobert     Desc& operator=(const MutexSet::Desc& other) {
35*810390e3Srobert       internal_memcpy(this, &other, sizeof(*this));
36*810390e3Srobert       return *this;
37*810390e3Srobert     }
383cab2bb3Spatrick   };
393cab2bb3Spatrick 
403cab2bb3Spatrick   MutexSet();
41*810390e3Srobert   void Reset();
42*810390e3Srobert   void AddAddr(uptr addr, StackID stack_id, bool write);
43*810390e3Srobert   void DelAddr(uptr addr, bool destroy = false);
443cab2bb3Spatrick   uptr Size() const;
453cab2bb3Spatrick   Desc Get(uptr i) const;
463cab2bb3Spatrick 
473cab2bb3Spatrick  private:
483cab2bb3Spatrick #if !SANITIZER_GO
49*810390e3Srobert   u32 seq_ = 0;
50*810390e3Srobert   uptr size_ = 0;
513cab2bb3Spatrick   Desc descs_[kMaxSize];
523cab2bb3Spatrick 
533cab2bb3Spatrick   void RemovePos(uptr i);
54*810390e3Srobert #endif
55*810390e3Srobert };
56*810390e3Srobert 
57*810390e3Srobert // MutexSet is too large to live on stack.
58*810390e3Srobert // DynamicMutexSet can be use used to create local MutexSet's.
59*810390e3Srobert class DynamicMutexSet {
60*810390e3Srobert  public:
61*810390e3Srobert   DynamicMutexSet();
62*810390e3Srobert   ~DynamicMutexSet();
63*810390e3Srobert   MutexSet* operator->() { return ptr_; }
64*810390e3Srobert   operator MutexSet*() { return ptr_; }
65*810390e3Srobert   DynamicMutexSet(const DynamicMutexSet&) = delete;
66*810390e3Srobert   DynamicMutexSet& operator=(const DynamicMutexSet&) = delete;
67*810390e3Srobert 
68*810390e3Srobert  private:
69*810390e3Srobert   MutexSet* ptr_;
70*810390e3Srobert #if SANITIZER_GO
71*810390e3Srobert   MutexSet set_;
72*810390e3Srobert #endif
733cab2bb3Spatrick };
743cab2bb3Spatrick 
753cab2bb3Spatrick // Go does not have mutexes, so do not spend memory and time.
763cab2bb3Spatrick // (Go sync.Mutex is actually a semaphore -- can be unlocked
773cab2bb3Spatrick // in different goroutine).
783cab2bb3Spatrick #if SANITIZER_GO
MutexSet()793cab2bb3Spatrick MutexSet::MutexSet() {}
Reset()80*810390e3Srobert void MutexSet::Reset() {}
AddAddr(uptr addr,StackID stack_id,bool write)81*810390e3Srobert void MutexSet::AddAddr(uptr addr, StackID stack_id, bool write) {}
DelAddr(uptr addr,bool destroy)82*810390e3Srobert void MutexSet::DelAddr(uptr addr, bool destroy) {}
Size()833cab2bb3Spatrick uptr MutexSet::Size() const { return 0; }
Get(uptr i)843cab2bb3Spatrick MutexSet::Desc MutexSet::Get(uptr i) const { return Desc(); }
DynamicMutexSet()85*810390e3Srobert DynamicMutexSet::DynamicMutexSet() : ptr_(&set_) {}
~DynamicMutexSet()86*810390e3Srobert DynamicMutexSet::~DynamicMutexSet() {}
873cab2bb3Spatrick #endif
883cab2bb3Spatrick 
893cab2bb3Spatrick }  // namespace __tsan
903cab2bb3Spatrick 
913cab2bb3Spatrick #endif  // TSAN_MUTEXSET_H
92