]>
Commit | Line | Data |
---|---|---|
2fc4da48 | 1 | //===-- tsan_mutexset.cpp -------------------------------------------------===// |
f5ed5428 | 2 | // |
2fc4da48 | 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 | |
f5ed5428 | 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 |