tsan_mutexset.h 2.5 KB

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