tsan_mutexset.cpp 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. //===-- tsan_mutexset.cpp -------------------------------------------------===//
  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. //===----------------------------------------------------------------------===//
  12. #include "tsan_mutexset.h"
  13. #include "sanitizer_common/sanitizer_placement_new.h"
  14. #include "tsan_rtl.h"
  15. namespace __tsan {
  16. MutexSet::MutexSet() {
  17. }
  18. void MutexSet::Reset() { internal_memset(this, 0, sizeof(*this)); }
  19. void MutexSet::AddAddr(uptr addr, StackID stack_id, bool write) {
  20. // Look up existing mutex with the same id.
  21. for (uptr i = 0; i < size_; i++) {
  22. if (descs_[i].addr == addr) {
  23. descs_[i].count++;
  24. descs_[i].seq = seq_++;
  25. return;
  26. }
  27. }
  28. // On overflow, find the oldest mutex and drop it.
  29. if (size_ == kMaxSize) {
  30. uptr min = 0;
  31. for (uptr i = 0; i < size_; i++) {
  32. if (descs_[i].seq < descs_[min].seq)
  33. min = i;
  34. }
  35. RemovePos(min);
  36. CHECK_EQ(size_, kMaxSize - 1);
  37. }
  38. // Add new mutex descriptor.
  39. descs_[size_].addr = addr;
  40. descs_[size_].stack_id = stack_id;
  41. descs_[size_].write = write;
  42. descs_[size_].seq = seq_++;
  43. descs_[size_].count = 1;
  44. size_++;
  45. }
  46. void MutexSet::DelAddr(uptr addr, bool destroy) {
  47. for (uptr i = 0; i < size_; i++) {
  48. if (descs_[i].addr == addr) {
  49. if (destroy || --descs_[i].count == 0)
  50. RemovePos(i);
  51. return;
  52. }
  53. }
  54. }
  55. void MutexSet::RemovePos(uptr i) {
  56. CHECK_LT(i, size_);
  57. descs_[i] = descs_[size_ - 1];
  58. size_--;
  59. }
  60. uptr MutexSet::Size() const {
  61. return size_;
  62. }
  63. MutexSet::Desc MutexSet::Get(uptr i) const {
  64. CHECK_LT(i, size_);
  65. return descs_[i];
  66. }
  67. DynamicMutexSet::DynamicMutexSet() : ptr_(New<MutexSet>()) {}
  68. DynamicMutexSet::~DynamicMutexSet() { DestroyAndFree(ptr_); }
  69. } // namespace __tsan