1*68d75effSDimitry Andric //===-- tsan_mutexset.cpp -------------------------------------------------===// 2*68d75effSDimitry Andric // 3*68d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*68d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*68d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*68d75effSDimitry Andric // 7*68d75effSDimitry Andric //===----------------------------------------------------------------------===// 8*68d75effSDimitry Andric // 9*68d75effSDimitry Andric // This file is a part of ThreadSanitizer (TSan), a race detector. 10*68d75effSDimitry Andric // 11*68d75effSDimitry Andric //===----------------------------------------------------------------------===// 12*68d75effSDimitry Andric #include "tsan_mutexset.h" 13*68d75effSDimitry Andric #include "tsan_rtl.h" 14*68d75effSDimitry Andric 15*68d75effSDimitry Andric namespace __tsan { 16*68d75effSDimitry Andric 17*68d75effSDimitry Andric const uptr MutexSet::kMaxSize; 18*68d75effSDimitry Andric 19*68d75effSDimitry Andric MutexSet::MutexSet() { 20*68d75effSDimitry Andric size_ = 0; 21*68d75effSDimitry Andric internal_memset(&descs_, 0, sizeof(descs_)); 22*68d75effSDimitry Andric } 23*68d75effSDimitry Andric 24*68d75effSDimitry Andric void MutexSet::Add(u64 id, bool write, u64 epoch) { 25*68d75effSDimitry Andric // Look up existing mutex with the same id. 26*68d75effSDimitry Andric for (uptr i = 0; i < size_; i++) { 27*68d75effSDimitry Andric if (descs_[i].id == id) { 28*68d75effSDimitry Andric descs_[i].count++; 29*68d75effSDimitry Andric descs_[i].epoch = epoch; 30*68d75effSDimitry Andric return; 31*68d75effSDimitry Andric } 32*68d75effSDimitry Andric } 33*68d75effSDimitry Andric // On overflow, find the oldest mutex and drop it. 34*68d75effSDimitry Andric if (size_ == kMaxSize) { 35*68d75effSDimitry Andric u64 minepoch = (u64)-1; 36*68d75effSDimitry Andric u64 mini = (u64)-1; 37*68d75effSDimitry Andric for (uptr i = 0; i < size_; i++) { 38*68d75effSDimitry Andric if (descs_[i].epoch < minepoch) { 39*68d75effSDimitry Andric minepoch = descs_[i].epoch; 40*68d75effSDimitry Andric mini = i; 41*68d75effSDimitry Andric } 42*68d75effSDimitry Andric } 43*68d75effSDimitry Andric RemovePos(mini); 44*68d75effSDimitry Andric CHECK_EQ(size_, kMaxSize - 1); 45*68d75effSDimitry Andric } 46*68d75effSDimitry Andric // Add new mutex descriptor. 47*68d75effSDimitry Andric descs_[size_].id = id; 48*68d75effSDimitry Andric descs_[size_].write = write; 49*68d75effSDimitry Andric descs_[size_].epoch = epoch; 50*68d75effSDimitry Andric descs_[size_].count = 1; 51*68d75effSDimitry Andric size_++; 52*68d75effSDimitry Andric } 53*68d75effSDimitry Andric 54*68d75effSDimitry Andric void MutexSet::Del(u64 id, bool write) { 55*68d75effSDimitry Andric for (uptr i = 0; i < size_; i++) { 56*68d75effSDimitry Andric if (descs_[i].id == id) { 57*68d75effSDimitry Andric if (--descs_[i].count == 0) 58*68d75effSDimitry Andric RemovePos(i); 59*68d75effSDimitry Andric return; 60*68d75effSDimitry Andric } 61*68d75effSDimitry Andric } 62*68d75effSDimitry Andric } 63*68d75effSDimitry Andric 64*68d75effSDimitry Andric void MutexSet::Remove(u64 id) { 65*68d75effSDimitry Andric for (uptr i = 0; i < size_; i++) { 66*68d75effSDimitry Andric if (descs_[i].id == id) { 67*68d75effSDimitry Andric RemovePos(i); 68*68d75effSDimitry Andric return; 69*68d75effSDimitry Andric } 70*68d75effSDimitry Andric } 71*68d75effSDimitry Andric } 72*68d75effSDimitry Andric 73*68d75effSDimitry Andric void MutexSet::RemovePos(uptr i) { 74*68d75effSDimitry Andric CHECK_LT(i, size_); 75*68d75effSDimitry Andric descs_[i] = descs_[size_ - 1]; 76*68d75effSDimitry Andric size_--; 77*68d75effSDimitry Andric } 78*68d75effSDimitry Andric 79*68d75effSDimitry Andric uptr MutexSet::Size() const { 80*68d75effSDimitry Andric return size_; 81*68d75effSDimitry Andric } 82*68d75effSDimitry Andric 83*68d75effSDimitry Andric MutexSet::Desc MutexSet::Get(uptr i) const { 84*68d75effSDimitry Andric CHECK_LT(i, size_); 85*68d75effSDimitry Andric return descs_[i]; 86*68d75effSDimitry Andric } 87*68d75effSDimitry Andric 88*68d75effSDimitry Andric } // namespace __tsan 89