xref: /aosp_15_r20/external/compiler-rt/lib/tsan/rtl/tsan_mutexset.cc (revision 7c3d14c8b49c529e04be81a3ce6f5cc23712e4c6)
1*7c3d14c8STreehugger Robot //===-- tsan_mutexset.cc --------------------------------------------------===//
2*7c3d14c8STreehugger Robot //
3*7c3d14c8STreehugger Robot //                     The LLVM Compiler Infrastructure
4*7c3d14c8STreehugger Robot //
5*7c3d14c8STreehugger Robot // This file is distributed under the University of Illinois Open Source
6*7c3d14c8STreehugger Robot // License. See LICENSE.TXT for details.
7*7c3d14c8STreehugger Robot //
8*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===//
9*7c3d14c8STreehugger Robot //
10*7c3d14c8STreehugger Robot // This file is a part of ThreadSanitizer (TSan), a race detector.
11*7c3d14c8STreehugger Robot //
12*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===//
13*7c3d14c8STreehugger Robot #include "tsan_mutexset.h"
14*7c3d14c8STreehugger Robot #include "tsan_rtl.h"
15*7c3d14c8STreehugger Robot 
16*7c3d14c8STreehugger Robot namespace __tsan {
17*7c3d14c8STreehugger Robot 
18*7c3d14c8STreehugger Robot const uptr MutexSet::kMaxSize;
19*7c3d14c8STreehugger Robot 
MutexSet()20*7c3d14c8STreehugger Robot MutexSet::MutexSet() {
21*7c3d14c8STreehugger Robot   size_ = 0;
22*7c3d14c8STreehugger Robot   internal_memset(&descs_, 0, sizeof(descs_));
23*7c3d14c8STreehugger Robot }
24*7c3d14c8STreehugger Robot 
Add(u64 id,bool write,u64 epoch)25*7c3d14c8STreehugger Robot void MutexSet::Add(u64 id, bool write, u64 epoch) {
26*7c3d14c8STreehugger Robot   // Look up existing mutex with the same id.
27*7c3d14c8STreehugger Robot   for (uptr i = 0; i < size_; i++) {
28*7c3d14c8STreehugger Robot     if (descs_[i].id == id) {
29*7c3d14c8STreehugger Robot       descs_[i].count++;
30*7c3d14c8STreehugger Robot       descs_[i].epoch = epoch;
31*7c3d14c8STreehugger Robot       return;
32*7c3d14c8STreehugger Robot     }
33*7c3d14c8STreehugger Robot   }
34*7c3d14c8STreehugger Robot   // On overflow, find the oldest mutex and drop it.
35*7c3d14c8STreehugger Robot   if (size_ == kMaxSize) {
36*7c3d14c8STreehugger Robot     u64 minepoch = (u64)-1;
37*7c3d14c8STreehugger Robot     u64 mini = (u64)-1;
38*7c3d14c8STreehugger Robot     for (uptr i = 0; i < size_; i++) {
39*7c3d14c8STreehugger Robot       if (descs_[i].epoch < minepoch) {
40*7c3d14c8STreehugger Robot         minepoch = descs_[i].epoch;
41*7c3d14c8STreehugger Robot         mini = i;
42*7c3d14c8STreehugger Robot       }
43*7c3d14c8STreehugger Robot     }
44*7c3d14c8STreehugger Robot     RemovePos(mini);
45*7c3d14c8STreehugger Robot     CHECK_EQ(size_, kMaxSize - 1);
46*7c3d14c8STreehugger Robot   }
47*7c3d14c8STreehugger Robot   // Add new mutex descriptor.
48*7c3d14c8STreehugger Robot   descs_[size_].id = id;
49*7c3d14c8STreehugger Robot   descs_[size_].write = write;
50*7c3d14c8STreehugger Robot   descs_[size_].epoch = epoch;
51*7c3d14c8STreehugger Robot   descs_[size_].count = 1;
52*7c3d14c8STreehugger Robot   size_++;
53*7c3d14c8STreehugger Robot }
54*7c3d14c8STreehugger Robot 
Del(u64 id,bool write)55*7c3d14c8STreehugger Robot void MutexSet::Del(u64 id, bool write) {
56*7c3d14c8STreehugger Robot   for (uptr i = 0; i < size_; i++) {
57*7c3d14c8STreehugger Robot     if (descs_[i].id == id) {
58*7c3d14c8STreehugger Robot       if (--descs_[i].count == 0)
59*7c3d14c8STreehugger Robot         RemovePos(i);
60*7c3d14c8STreehugger Robot       return;
61*7c3d14c8STreehugger Robot     }
62*7c3d14c8STreehugger Robot   }
63*7c3d14c8STreehugger Robot }
64*7c3d14c8STreehugger Robot 
Remove(u64 id)65*7c3d14c8STreehugger Robot void MutexSet::Remove(u64 id) {
66*7c3d14c8STreehugger Robot   for (uptr i = 0; i < size_; i++) {
67*7c3d14c8STreehugger Robot     if (descs_[i].id == id) {
68*7c3d14c8STreehugger Robot       RemovePos(i);
69*7c3d14c8STreehugger Robot       return;
70*7c3d14c8STreehugger Robot     }
71*7c3d14c8STreehugger Robot   }
72*7c3d14c8STreehugger Robot }
73*7c3d14c8STreehugger Robot 
RemovePos(uptr i)74*7c3d14c8STreehugger Robot void MutexSet::RemovePos(uptr i) {
75*7c3d14c8STreehugger Robot   CHECK_LT(i, size_);
76*7c3d14c8STreehugger Robot   descs_[i] = descs_[size_ - 1];
77*7c3d14c8STreehugger Robot   size_--;
78*7c3d14c8STreehugger Robot }
79*7c3d14c8STreehugger Robot 
Size() const80*7c3d14c8STreehugger Robot uptr MutexSet::Size() const {
81*7c3d14c8STreehugger Robot   return size_;
82*7c3d14c8STreehugger Robot }
83*7c3d14c8STreehugger Robot 
Get(uptr i) const84*7c3d14c8STreehugger Robot MutexSet::Desc MutexSet::Get(uptr i) const {
85*7c3d14c8STreehugger Robot   CHECK_LT(i, size_);
86*7c3d14c8STreehugger Robot   return descs_[i];
87*7c3d14c8STreehugger Robot }
88*7c3d14c8STreehugger Robot 
89*7c3d14c8STreehugger Robot }  // namespace __tsan
90