Viewing file: tsan_mutexset.h (2.77 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
//===-- tsan_mutexset.h -----------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file is a part of ThreadSanitizer (TSan), a race detector. // // MutexSet holds the set of mutexes currently held by a thread. //===----------------------------------------------------------------------===// #ifndef TSAN_MUTEXSET_H #define TSAN_MUTEXSET_H
#include "tsan_defs.h"
namespace __tsan {
class MutexSet { public: // Holds limited number of mutexes. // The oldest mutexes are discarded on overflow. static constexpr uptr kMaxSize = 16; struct Desc { uptr addr; StackID stack_id; u64 id; u64 epoch; u32 seq; u32 count; bool write;
Desc() { internal_memset(this, 0, sizeof(*this)); } Desc(const Desc& other) { *this = other; } Desc& operator=(const MutexSet::Desc& other) { internal_memcpy(this, &other, sizeof(*this)); return *this; } };
MutexSet(); // The 'id' is obtained from SyncVar::GetId(). void Add(u64 id, bool write, u64 epoch); void Del(u64 id, bool write); void Remove(u64 id); // Removes the mutex completely (if it's destroyed). void AddAddr(uptr addr, StackID stack_id, bool write); void DelAddr(uptr addr, bool destroy = false); uptr Size() const; Desc Get(uptr i) const;
private: #if !SANITIZER_GO u32 seq_ = 0; uptr size_ = 0; Desc descs_[kMaxSize];
void RemovePos(uptr i); #endif };
// MutexSet is too large to live on stack. // DynamicMutexSet can be use used to create local MutexSet's. class DynamicMutexSet { public: DynamicMutexSet(); ~DynamicMutexSet(); MutexSet* operator->() { return ptr_; } operator MutexSet*() { return ptr_; } DynamicMutexSet(const DynamicMutexSet&) = delete; DynamicMutexSet& operator=(const DynamicMutexSet&) = delete;
private: MutexSet* ptr_; #if SANITIZER_GO MutexSet set_; #endif };
// Go does not have mutexes, so do not spend memory and time. // (Go sync.Mutex is actually a semaphore -- can be unlocked // in different goroutine). #if SANITIZER_GO MutexSet::MutexSet() {} void MutexSet::Add(u64 id, bool write, u64 epoch) {} void MutexSet::Del(u64 id, bool write) {} void MutexSet::Remove(u64 id) {} void MutexSet::AddAddr(uptr addr, StackID stack_id, bool write) {} void MutexSet::DelAddr(uptr addr, bool destroy) {} uptr MutexSet::Size() const { return 0; } MutexSet::Desc MutexSet::Get(uptr i) const { return Desc(); } DynamicMutexSet::DynamicMutexSet() : ptr_(&set_) {} DynamicMutexSet::~DynamicMutexSet() {} #endif
} // namespace __tsan
#endif // TSAN_MUTEXSET_H
|