master
 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
18namespace __tsan {
19
20class 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    u32 seq;
29    u32 count;
30    bool write;
31
32    Desc() { internal_memset(this, 0, sizeof(*this)); }
33    Desc(const Desc& other) { *this = other; }
34    Desc& operator=(const MutexSet::Desc& other) {
35      internal_memcpy(this, &other, sizeof(*this));
36      return *this;
37    }
38  };
39
40  MutexSet();
41  void Reset();
42  void AddAddr(uptr addr, StackID stack_id, bool write);
43  void DelAddr(uptr addr, bool destroy = false);
44  uptr Size() const;
45  Desc Get(uptr i) const;
46
47 private:
48#if !SANITIZER_GO
49  u32 seq_ = 0;
50  uptr size_ = 0;
51  Desc descs_[kMaxSize];
52
53  void RemovePos(uptr i);
54#endif
55};
56
57// MutexSet is too large to live on stack.
58// DynamicMutexSet can be use used to create local MutexSet's.
59class DynamicMutexSet {
60 public:
61  DynamicMutexSet();
62  ~DynamicMutexSet();
63  MutexSet* operator->() { return ptr_; }
64  operator MutexSet*() { return ptr_; }
65  DynamicMutexSet(const DynamicMutexSet&) = delete;
66  DynamicMutexSet& operator=(const DynamicMutexSet&) = delete;
67
68 private:
69  MutexSet* ptr_;
70#if SANITIZER_GO
71  MutexSet set_;
72#endif
73};
74
75// Go does not have mutexes, so do not spend memory and time.
76// (Go sync.Mutex is actually a semaphore -- can be unlocked
77// in different goroutine).
78#if SANITIZER_GO
79MutexSet::MutexSet() {}
80void MutexSet::Reset() {}
81void MutexSet::AddAddr(uptr addr, StackID stack_id, bool write) {}
82void MutexSet::DelAddr(uptr addr, bool destroy) {}
83uptr MutexSet::Size() const { return 0; }
84MutexSet::Desc MutexSet::Get(uptr i) const { return Desc(); }
85DynamicMutexSet::DynamicMutexSet() : ptr_(&set_) {}
86DynamicMutexSet::~DynamicMutexSet() {}
87#endif
88
89}  // namespace __tsan
90
91#endif  // TSAN_MUTEXSET_H