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