xref: /freebsd-src/contrib/llvm-project/compiler-rt/lib/tsan/rtl/tsan_mutexset.cpp (revision 0eae32dcef82f6f06de6419a0d623d7def0cc8f6)
168d75effSDimitry Andric //===-- tsan_mutexset.cpp -------------------------------------------------===//
268d75effSDimitry Andric //
368d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
468d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
568d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
668d75effSDimitry Andric //
768d75effSDimitry Andric //===----------------------------------------------------------------------===//
868d75effSDimitry Andric //
968d75effSDimitry Andric // This file is a part of ThreadSanitizer (TSan), a race detector.
1068d75effSDimitry Andric //
1168d75effSDimitry Andric //===----------------------------------------------------------------------===//
1268d75effSDimitry Andric #include "tsan_mutexset.h"
13349cc55cSDimitry Andric 
14349cc55cSDimitry Andric #include "sanitizer_common/sanitizer_placement_new.h"
1568d75effSDimitry Andric #include "tsan_rtl.h"
1668d75effSDimitry Andric 
1768d75effSDimitry Andric namespace __tsan {
1868d75effSDimitry Andric 
MutexSet()1968d75effSDimitry Andric MutexSet::MutexSet() {
2068d75effSDimitry Andric }
2168d75effSDimitry Andric 
Reset()22*0eae32dcSDimitry Andric void MutexSet::Reset() { internal_memset(this, 0, sizeof(*this)); }
2368d75effSDimitry Andric 
AddAddr(uptr addr,StackID stack_id,bool write)24349cc55cSDimitry Andric void MutexSet::AddAddr(uptr addr, StackID stack_id, bool write) {
25349cc55cSDimitry Andric   // Look up existing mutex with the same id.
26349cc55cSDimitry Andric   for (uptr i = 0; i < size_; i++) {
27349cc55cSDimitry Andric     if (descs_[i].addr == addr) {
28349cc55cSDimitry Andric       descs_[i].count++;
29349cc55cSDimitry Andric       descs_[i].seq = seq_++;
30349cc55cSDimitry Andric       return;
31349cc55cSDimitry Andric     }
32349cc55cSDimitry Andric   }
33349cc55cSDimitry Andric   // On overflow, find the oldest mutex and drop it.
34349cc55cSDimitry Andric   if (size_ == kMaxSize) {
35349cc55cSDimitry Andric     uptr min = 0;
36349cc55cSDimitry Andric     for (uptr i = 0; i < size_; i++) {
37349cc55cSDimitry Andric       if (descs_[i].seq < descs_[min].seq)
38349cc55cSDimitry Andric         min = i;
39349cc55cSDimitry Andric     }
40349cc55cSDimitry Andric     RemovePos(min);
41349cc55cSDimitry Andric     CHECK_EQ(size_, kMaxSize - 1);
42349cc55cSDimitry Andric   }
43349cc55cSDimitry Andric   // Add new mutex descriptor.
44349cc55cSDimitry Andric   descs_[size_].addr = addr;
45349cc55cSDimitry Andric   descs_[size_].stack_id = stack_id;
46349cc55cSDimitry Andric   descs_[size_].write = write;
47349cc55cSDimitry Andric   descs_[size_].seq = seq_++;
48349cc55cSDimitry Andric   descs_[size_].count = 1;
49349cc55cSDimitry Andric   size_++;
50349cc55cSDimitry Andric }
51349cc55cSDimitry Andric 
DelAddr(uptr addr,bool destroy)52349cc55cSDimitry Andric void MutexSet::DelAddr(uptr addr, bool destroy) {
53349cc55cSDimitry Andric   for (uptr i = 0; i < size_; i++) {
54349cc55cSDimitry Andric     if (descs_[i].addr == addr) {
55349cc55cSDimitry Andric       if (destroy || --descs_[i].count == 0)
56349cc55cSDimitry Andric         RemovePos(i);
57349cc55cSDimitry Andric       return;
58349cc55cSDimitry Andric     }
59349cc55cSDimitry Andric   }
60349cc55cSDimitry Andric }
61349cc55cSDimitry Andric 
RemovePos(uptr i)6268d75effSDimitry Andric void MutexSet::RemovePos(uptr i) {
6368d75effSDimitry Andric   CHECK_LT(i, size_);
6468d75effSDimitry Andric   descs_[i] = descs_[size_ - 1];
6568d75effSDimitry Andric   size_--;
6668d75effSDimitry Andric }
6768d75effSDimitry Andric 
Size() const6868d75effSDimitry Andric uptr MutexSet::Size() const {
6968d75effSDimitry Andric   return size_;
7068d75effSDimitry Andric }
7168d75effSDimitry Andric 
Get(uptr i) const7268d75effSDimitry Andric MutexSet::Desc MutexSet::Get(uptr i) const {
7368d75effSDimitry Andric   CHECK_LT(i, size_);
7468d75effSDimitry Andric   return descs_[i];
7568d75effSDimitry Andric }
7668d75effSDimitry Andric 
DynamicMutexSet()77349cc55cSDimitry Andric DynamicMutexSet::DynamicMutexSet() : ptr_(New<MutexSet>()) {}
~DynamicMutexSet()78349cc55cSDimitry Andric DynamicMutexSet::~DynamicMutexSet() { DestroyAndFree(ptr_); }
79349cc55cSDimitry Andric 
8068d75effSDimitry Andric }  // namespace __tsan
81