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