10b57cec5SDimitry Andric //===-- tsan_mutexset.h -----------------------------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file is a part of ThreadSanitizer (TSan), a race detector.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric // MutexSet holds the set of mutexes currently held by a thread.
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric #ifndef TSAN_MUTEXSET_H
140b57cec5SDimitry Andric #define TSAN_MUTEXSET_H
150b57cec5SDimitry Andric
160b57cec5SDimitry Andric #include "tsan_defs.h"
170b57cec5SDimitry Andric
180b57cec5SDimitry Andric namespace __tsan {
190b57cec5SDimitry Andric
200b57cec5SDimitry Andric class MutexSet {
210b57cec5SDimitry Andric public:
220b57cec5SDimitry Andric // Holds limited number of mutexes.
230b57cec5SDimitry Andric // The oldest mutexes are discarded on overflow.
24349cc55cSDimitry Andric static constexpr uptr kMaxSize = 16;
250b57cec5SDimitry Andric struct Desc {
26349cc55cSDimitry Andric uptr addr;
27349cc55cSDimitry Andric StackID stack_id;
28349cc55cSDimitry Andric u32 seq;
29349cc55cSDimitry Andric u32 count;
300b57cec5SDimitry Andric bool write;
31349cc55cSDimitry Andric
DescDesc32349cc55cSDimitry Andric Desc() { internal_memset(this, 0, sizeof(*this)); }
DescDesc33349cc55cSDimitry Andric Desc(const Desc& other) { *this = other; }
34349cc55cSDimitry Andric Desc& operator=(const MutexSet::Desc& other) {
35349cc55cSDimitry Andric internal_memcpy(this, &other, sizeof(*this));
36349cc55cSDimitry Andric return *this;
37349cc55cSDimitry Andric }
380b57cec5SDimitry Andric };
390b57cec5SDimitry Andric
400b57cec5SDimitry Andric MutexSet();
41*0eae32dcSDimitry Andric void Reset();
42349cc55cSDimitry Andric void AddAddr(uptr addr, StackID stack_id, bool write);
43349cc55cSDimitry Andric void DelAddr(uptr addr, bool destroy = false);
440b57cec5SDimitry Andric uptr Size() const;
450b57cec5SDimitry Andric Desc Get(uptr i) const;
460b57cec5SDimitry Andric
470b57cec5SDimitry Andric private:
480b57cec5SDimitry Andric #if !SANITIZER_GO
49349cc55cSDimitry Andric u32 seq_ = 0;
50349cc55cSDimitry Andric uptr size_ = 0;
510b57cec5SDimitry Andric Desc descs_[kMaxSize];
520b57cec5SDimitry Andric
530b57cec5SDimitry Andric void RemovePos(uptr i);
54349cc55cSDimitry Andric #endif
55349cc55cSDimitry Andric };
56349cc55cSDimitry Andric
57349cc55cSDimitry Andric // MutexSet is too large to live on stack.
58349cc55cSDimitry Andric // DynamicMutexSet can be use used to create local MutexSet's.
59349cc55cSDimitry Andric class DynamicMutexSet {
60349cc55cSDimitry Andric public:
61349cc55cSDimitry Andric DynamicMutexSet();
62349cc55cSDimitry Andric ~DynamicMutexSet();
63349cc55cSDimitry Andric MutexSet* operator->() { return ptr_; }
64349cc55cSDimitry Andric operator MutexSet*() { return ptr_; }
65349cc55cSDimitry Andric DynamicMutexSet(const DynamicMutexSet&) = delete;
66349cc55cSDimitry Andric DynamicMutexSet& operator=(const DynamicMutexSet&) = delete;
67349cc55cSDimitry Andric
68349cc55cSDimitry Andric private:
69349cc55cSDimitry Andric MutexSet* ptr_;
70349cc55cSDimitry Andric #if SANITIZER_GO
71349cc55cSDimitry Andric MutexSet set_;
72349cc55cSDimitry Andric #endif
730b57cec5SDimitry Andric };
740b57cec5SDimitry Andric
750b57cec5SDimitry Andric // Go does not have mutexes, so do not spend memory and time.
760b57cec5SDimitry Andric // (Go sync.Mutex is actually a semaphore -- can be unlocked
770b57cec5SDimitry Andric // in different goroutine).
780b57cec5SDimitry Andric #if SANITIZER_GO
MutexSet()790b57cec5SDimitry Andric MutexSet::MutexSet() {}
Reset()80*0eae32dcSDimitry Andric void MutexSet::Reset() {}
AddAddr(uptr addr,StackID stack_id,bool write)81349cc55cSDimitry Andric void MutexSet::AddAddr(uptr addr, StackID stack_id, bool write) {}
DelAddr(uptr addr,bool destroy)82349cc55cSDimitry Andric void MutexSet::DelAddr(uptr addr, bool destroy) {}
Size()830b57cec5SDimitry Andric uptr MutexSet::Size() const { return 0; }
Get(uptr i)840b57cec5SDimitry Andric MutexSet::Desc MutexSet::Get(uptr i) const { return Desc(); }
DynamicMutexSet()85349cc55cSDimitry Andric DynamicMutexSet::DynamicMutexSet() : ptr_(&set_) {}
~DynamicMutexSet()86349cc55cSDimitry Andric DynamicMutexSet::~DynamicMutexSet() {}
870b57cec5SDimitry Andric #endif
880b57cec5SDimitry Andric
890b57cec5SDimitry Andric } // namespace __tsan
900b57cec5SDimitry Andric
910b57cec5SDimitry Andric #endif // TSAN_MUTEXSET_H
92