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