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