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