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 14 namespace __tsan { 15 16 const uptr MutexSet::kMaxSize; 17 18 MutexSet::MutexSet() { 19 size_ = 0; 20 internal_memset(&descs_, 0, sizeof(descs_)); 21 } 22 23 void MutexSet::Add(u64 id, bool write, u64 epoch) { 24 // Look up existing mutex with the same id. 25 for (uptr i = 0; i < size_; i++) { 26 if (descs_[i].id == id) { 27 descs_[i].count++; 28 descs_[i].epoch = epoch; 29 return; 30 } 31 } 32 // On overflow, find the oldest mutex and drop it. 33 if (size_ == kMaxSize) { 34 u64 minepoch = (u64)-1; 35 u64 mini = (u64)-1; 36 for (uptr i = 0; i < size_; i++) { 37 if (descs_[i].epoch < minepoch) { 38 minepoch = descs_[i].epoch; 39 mini = i; 40 } 41 } 42 RemovePos(mini); 43 CHECK_EQ(size_, kMaxSize - 1); 44 } 45 // Add new mutex descriptor. 46 descs_[size_].id = id; 47 descs_[size_].write = write; 48 descs_[size_].epoch = epoch; 49 descs_[size_].count = 1; 50 size_++; 51 } 52 53 void MutexSet::Del(u64 id, bool write) { 54 for (uptr i = 0; i < size_; i++) { 55 if (descs_[i].id == id) { 56 if (--descs_[i].count == 0) 57 RemovePos(i); 58 return; 59 } 60 } 61 } 62 63 void MutexSet::Remove(u64 id) { 64 for (uptr i = 0; i < size_; i++) { 65 if (descs_[i].id == id) { 66 RemovePos(i); 67 return; 68 } 69 } 70 } 71 72 void MutexSet::RemovePos(uptr i) { 73 CHECK_LT(i, size_); 74 descs_[i] = descs_[size_ - 1]; 75 size_--; 76 } 77 78 uptr MutexSet::Size() const { 79 return size_; 80 } 81 82 MutexSet::Desc MutexSet::Get(uptr i) const { 83 CHECK_LT(i, size_); 84 return descs_[i]; 85 } 86 87 } // namespace __tsan 88