17ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//===-- tsan_clock.h --------------------------------------------*- C++ -*-===//
27ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//
37ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//                     The LLVM Compiler Infrastructure
47ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//
57ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// This file is distributed under the University of Illinois Open Source
67ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// License. See LICENSE.TXT for details.
77ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//
87ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//===----------------------------------------------------------------------===//
97ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//
107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// This file is a part of ThreadSanitizer (TSan), a race detector.
117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//
127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//===----------------------------------------------------------------------===//
137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#ifndef TSAN_CLOCK_H
147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#define TSAN_CLOCK_H
157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_defs.h"
177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_vector.h"
187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanynamespace __tsan {
207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstruct ClockElem {
222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  u64 epoch  : kClkBits;
232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  u64 reused : 64 - kClkBits;
242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines};
252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// The clock that lives in sync variables (mutexes, atomics, etc).
277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyclass SyncClock {
287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany public:
297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  SyncClock();
307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  uptr size() const {
327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return clk_.Size();
337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  u64 get(unsigned tid) const {
362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    DCHECK_LT(tid, clk_.Size());
372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    return clk_[tid].epoch;
387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  void Reset();
415d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  void Zero();
422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  void DebugDump(int(*printf)(const char *s, ...));
442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany private:
462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  unsigned release_store_tid_;
472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  unsigned release_store_reused_;
482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  static const uptr kDirtyTids = 2;
492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  unsigned dirty_tids_[kDirtyTids];
502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  mutable Vector<ClockElem> clk_;
517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  friend struct ThreadClock;
527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany};
537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// The clock that lives in threads.
557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystruct ThreadClock {
567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany public:
572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  explicit ThreadClock(unsigned tid, unsigned reused = 0);
587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
593d6ae1580e5f34f02d24ff0c8bb352a5026c327aKostya Serebryany  u64 get(unsigned tid) const {
60adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov    DCHECK_LT(tid, kMaxTidInClock);
612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    return clk_[tid].epoch;
627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  void set(unsigned tid, u64 v);
652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  void set(u64 v) {
672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    DCHECK_GE(v, clk_[tid_].epoch);
682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    clk_[tid_].epoch = v;
697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
712d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  void tick() {
722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    clk_[tid_].epoch++;
737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  uptr size() const {
767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return nclk_;
777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  void acquire(const SyncClock *src);
807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  void release(SyncClock *dst) const;
817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  void acq_rel(SyncClock *dst);
829d150bdb433ddd092073dabd87ba15aa176603a1Dmitry Vyukov  void ReleaseStore(SyncClock *dst) const;
837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
842d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  void DebugReset();
852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  void DebugDump(int(*printf)(const char *s, ...));
862d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany private:
882d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  static const uptr kDirtyTids = SyncClock::kDirtyTids;
892d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  const unsigned tid_;
902d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  const unsigned reused_;
912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  u64 last_acquire_;
927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  uptr nclk_;
932d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  ClockElem clk_[kMaxTidInClock];
942d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
952d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  bool IsAlreadyAcquired(const SyncClock *src) const;
962d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  void UpdateCurrentThread(SyncClock *dst) const;
977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany};
987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}  // namespace __tsan
1007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
1017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif  // TSAN_CLOCK_H
102