tsan_mutexset.cpp revision 360784
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
15namespace __tsan {
16
17const uptr MutexSet::kMaxSize;
18
19MutexSet::MutexSet() {
20  size_ = 0;
21  internal_memset(&descs_, 0, sizeof(descs_));
22}
23
24void 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
54void 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
64void 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
73void MutexSet::RemovePos(uptr i) {
74  CHECK_LT(i, size_);
75  descs_[i] = descs_[size_ - 1];
76  size_--;
77}
78
79uptr MutexSet::Size() const {
80  return size_;
81}
82
83MutexSet::Desc MutexSet::Get(uptr i) const {
84  CHECK_LT(i, size_);
85  return descs_[i];
86}
87
88}  // namespace __tsan
89