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