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