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