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