18808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf//===-- tsan_mutexset.h -----------------------------------------*- C++ -*-===//
28808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf//
38808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf//                     The LLVM Compiler Infrastructure
48808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf//
58808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf// This file is distributed under the University of Illinois Open Source
68808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf// License. See LICENSE.TXT for details.
78808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf//
88808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf//===----------------------------------------------------------------------===//
98808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf//
108808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf// This file is a part of ThreadSanitizer (TSan), a race detector.
118808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf//
128808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf// MutexSet holds the set of mutexes currently held by a thread.
138808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf//===----------------------------------------------------------------------===//
148808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf#ifndef TSAN_MUTEXSET_H
158808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf#define TSAN_MUTEXSET_H
168808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf
178808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf#include "tsan_defs.h"
188808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf
198808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Grafnamespace __tsan {
208808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf
218808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Grafclass MutexSet {
228808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf public:
238808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf  // Holds limited number of mutexes.
248808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf  // The oldest mutexes are discarded on overflow.
258808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf  static const uptr kMaxSize = 16;
268808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf  struct Desc {
278808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf    u64 id;
288808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf    u64 epoch;
298808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf    int count;
308808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf    bool write;
318808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf  };
328808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf
338808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf  MutexSet();
348808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf  // The 'id' is obtained from SyncVar::GetId().
358808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf  void Add(u64 id, bool write, u64 epoch);
368808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf  void Del(u64 id, bool write);
378808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf  void Remove(u64 id);  // Removes the mutex completely (if it's destroyed).
388808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf  uptr Size() const;
398808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf  Desc Get(uptr i) const;
408808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf
418808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf  void operator=(const MutexSet &other) {
428808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf    internal_memcpy(this, &other, sizeof(*this));
438808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf  }
448808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf
458808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf private:
468808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf#ifndef TSAN_GO
478808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf  uptr size_;
488808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf  Desc descs_[kMaxSize];
498808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf#endif
508808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf
518808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf  void RemovePos(uptr i);
528808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf  MutexSet(const MutexSet&);
538808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf};
548808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf
558808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf// Go does not have mutexes, so do not spend memory and time.
568808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf// (Go sync.Mutex is actually a semaphore -- can be unlocked
578808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf// in different goroutine).
588808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf#ifdef TSAN_GO
598808743839b0f459394ecd00cb0f7c1896c0ab7aThomas GrafMutexSet::MutexSet() {}
608808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Grafvoid MutexSet::Add(u64 id, bool write, u64 epoch) {}
618808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Grafvoid MutexSet::Del(u64 id, bool write) {}
628808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Grafvoid MutexSet::Remove(u64 id) {}
638808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Grafvoid MutexSet::RemovePos(uptr i) {}
648808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Grafuptr MutexSet::Size() const { return 0; }
658808743839b0f459394ecd00cb0f7c1896c0ab7aThomas GrafMutexSet::Desc MutexSet::Get(uptr i) const { return Desc(); }
668808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf#endif
678808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf
688808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf}  // namespace __tsan
698808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf
708808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf#endif  // TSAN_MUTEXSET_H
718808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf