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