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