tsan_mutexset.cc 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. //===-- tsan_mutexset.cc --------------------------------------------------===//
  2. //
  3. // This file is distributed under the University of Illinois Open Source
  4. // License. See LICENSE.TXT for details.
  5. //
  6. //===----------------------------------------------------------------------===//
  7. //
  8. // This file is a part of ThreadSanitizer (TSan), a race detector.
  9. //
  10. //===----------------------------------------------------------------------===//
  11. #include "tsan_mutexset.h"
  12. #include "tsan_rtl.h"
  13. namespace __tsan {
  14. const uptr MutexSet::kMaxSize;
  15. MutexSet::MutexSet() {
  16. size_ = 0;
  17. internal_memset(&descs_, 0, sizeof(descs_));
  18. }
  19. void MutexSet::Add(u64 id, bool write, u64 epoch) {
  20. // Look up existing mutex with the same id.
  21. for (uptr i = 0; i < size_; i++) {
  22. if (descs_[i].id == id) {
  23. descs_[i].count++;
  24. descs_[i].epoch = epoch;
  25. return;
  26. }
  27. }
  28. // On overflow, find the oldest mutex and drop it.
  29. if (size_ == kMaxSize) {
  30. u64 minepoch = (u64)-1;
  31. u64 mini = (u64)-1;
  32. for (uptr i = 0; i < size_; i++) {
  33. if (descs_[i].epoch < minepoch) {
  34. minepoch = descs_[i].epoch;
  35. mini = i;
  36. }
  37. }
  38. RemovePos(mini);
  39. CHECK_EQ(size_, kMaxSize - 1);
  40. }
  41. // Add new mutex descriptor.
  42. descs_[size_].id = id;
  43. descs_[size_].write = write;
  44. descs_[size_].epoch = epoch;
  45. descs_[size_].count = 1;
  46. size_++;
  47. }
  48. void MutexSet::Del(u64 id, bool write) {
  49. for (uptr i = 0; i < size_; i++) {
  50. if (descs_[i].id == id) {
  51. if (--descs_[i].count == 0)
  52. RemovePos(i);
  53. return;
  54. }
  55. }
  56. }
  57. void MutexSet::Remove(u64 id) {
  58. for (uptr i = 0; i < size_; i++) {
  59. if (descs_[i].id == id) {
  60. RemovePos(i);
  61. return;
  62. }
  63. }
  64. }
  65. void MutexSet::RemovePos(uptr i) {
  66. CHECK_LT(i, size_);
  67. descs_[i] = descs_[size_ - 1];
  68. size_--;
  69. }
  70. uptr MutexSet::Size() const {
  71. return size_;
  72. }
  73. MutexSet::Desc MutexSet::Get(uptr i) const {
  74. CHECK_LT(i, size_);
  75. return descs_[i];
  76. }
  77. } // namespace __tsan