xref: /openbsd-src/gnu/llvm/compiler-rt/lib/tsan/rtl/tsan_mutexset.cpp (revision 810390e339a5425391477d5d41c78d7cab2424ac)
13cab2bb3Spatrick //===-- tsan_mutexset.cpp -------------------------------------------------===//
23cab2bb3Spatrick //
33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information.
53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63cab2bb3Spatrick //
73cab2bb3Spatrick //===----------------------------------------------------------------------===//
83cab2bb3Spatrick //
93cab2bb3Spatrick // This file is a part of ThreadSanitizer (TSan), a race detector.
103cab2bb3Spatrick //
113cab2bb3Spatrick //===----------------------------------------------------------------------===//
123cab2bb3Spatrick #include "tsan_mutexset.h"
13*810390e3Srobert 
14*810390e3Srobert #include "sanitizer_common/sanitizer_placement_new.h"
153cab2bb3Spatrick #include "tsan_rtl.h"
163cab2bb3Spatrick 
173cab2bb3Spatrick namespace __tsan {
183cab2bb3Spatrick 
MutexSet()193cab2bb3Spatrick MutexSet::MutexSet() {
203cab2bb3Spatrick }
213cab2bb3Spatrick 
Reset()22*810390e3Srobert void MutexSet::Reset() { internal_memset(this, 0, sizeof(*this)); }
23*810390e3Srobert 
AddAddr(uptr addr,StackID stack_id,bool write)24*810390e3Srobert void MutexSet::AddAddr(uptr addr, StackID stack_id, bool write) {
253cab2bb3Spatrick   // Look up existing mutex with the same id.
263cab2bb3Spatrick   for (uptr i = 0; i < size_; i++) {
27*810390e3Srobert     if (descs_[i].addr == addr) {
283cab2bb3Spatrick       descs_[i].count++;
29*810390e3Srobert       descs_[i].seq = seq_++;
303cab2bb3Spatrick       return;
313cab2bb3Spatrick     }
323cab2bb3Spatrick   }
333cab2bb3Spatrick   // On overflow, find the oldest mutex and drop it.
343cab2bb3Spatrick   if (size_ == kMaxSize) {
35*810390e3Srobert     uptr min = 0;
363cab2bb3Spatrick     for (uptr i = 0; i < size_; i++) {
37*810390e3Srobert       if (descs_[i].seq < descs_[min].seq)
38*810390e3Srobert         min = i;
393cab2bb3Spatrick     }
40*810390e3Srobert     RemovePos(min);
413cab2bb3Spatrick     CHECK_EQ(size_, kMaxSize - 1);
423cab2bb3Spatrick   }
433cab2bb3Spatrick   // Add new mutex descriptor.
44*810390e3Srobert   descs_[size_].addr = addr;
45*810390e3Srobert   descs_[size_].stack_id = stack_id;
463cab2bb3Spatrick   descs_[size_].write = write;
47*810390e3Srobert   descs_[size_].seq = seq_++;
483cab2bb3Spatrick   descs_[size_].count = 1;
493cab2bb3Spatrick   size_++;
503cab2bb3Spatrick }
513cab2bb3Spatrick 
DelAddr(uptr addr,bool destroy)52*810390e3Srobert void MutexSet::DelAddr(uptr addr, bool destroy) {
533cab2bb3Spatrick   for (uptr i = 0; i < size_; i++) {
54*810390e3Srobert     if (descs_[i].addr == addr) {
55*810390e3Srobert       if (destroy || --descs_[i].count == 0)
563cab2bb3Spatrick         RemovePos(i);
573cab2bb3Spatrick       return;
583cab2bb3Spatrick     }
593cab2bb3Spatrick   }
603cab2bb3Spatrick }
613cab2bb3Spatrick 
RemovePos(uptr i)623cab2bb3Spatrick void MutexSet::RemovePos(uptr i) {
633cab2bb3Spatrick   CHECK_LT(i, size_);
643cab2bb3Spatrick   descs_[i] = descs_[size_ - 1];
653cab2bb3Spatrick   size_--;
663cab2bb3Spatrick }
673cab2bb3Spatrick 
Size() const683cab2bb3Spatrick uptr MutexSet::Size() const {
693cab2bb3Spatrick   return size_;
703cab2bb3Spatrick }
713cab2bb3Spatrick 
Get(uptr i) const723cab2bb3Spatrick MutexSet::Desc MutexSet::Get(uptr i) const {
733cab2bb3Spatrick   CHECK_LT(i, size_);
743cab2bb3Spatrick   return descs_[i];
753cab2bb3Spatrick }
763cab2bb3Spatrick 
DynamicMutexSet()77*810390e3Srobert DynamicMutexSet::DynamicMutexSet() : ptr_(New<MutexSet>()) {}
~DynamicMutexSet()78*810390e3Srobert DynamicMutexSet::~DynamicMutexSet() { DestroyAndFree(ptr_); }
79*810390e3Srobert 
803cab2bb3Spatrick }  // namespace __tsan
81