diff --git a/clients/drcachesim/common/mutex_dbg_owned.h b/clients/drcachesim/common/mutex_dbg_owned.h index f41f0e512fc..fefa68e441d 100644 --- a/clients/drcachesim/common/mutex_dbg_owned.h +++ b/clients/drcachesim/common/mutex_dbg_owned.h @@ -50,9 +50,18 @@ class mutex_dbg_owned { void lock() { +#ifdef NDEBUG lock_.lock(); -#ifndef NDEBUG +#else + bool contended = true; + if (lock_.try_lock()) + contended = false; + else + lock_.lock(); owner_ = std::this_thread::get_id(); + ++count_acquired_; + if (contended) + ++count_contended_; #endif } bool @@ -76,6 +85,8 @@ class mutex_dbg_owned { #endif lock_.unlock(); } + +#ifndef NDEBUG // This query should only be called when the lock is required to be held // as it is racy when the lock is not held. bool @@ -84,9 +95,27 @@ class mutex_dbg_owned { return owner_ == std::this_thread::get_id(); } + // These statistics only count lock(): they do *not* count try_lock() + // (we could count try_lock with std::atomic on count_contended). + int64_t + get_count_acquired() + { + return count_acquired_; + } + int64_t + get_count_contended() + { + return count_contended_; + } +#endif + private: std::mutex lock_; +#ifndef NDEBUG std::thread::id owner_; + int64_t count_acquired_ = 0; + int64_t count_contended_ = 0; +#endif }; } // namespace drmemtrace diff --git a/clients/drcachesim/scheduler/scheduler.cpp b/clients/drcachesim/scheduler/scheduler.cpp index 793f4a149ec..c005063739d 100644 --- a/clients/drcachesim/scheduler/scheduler.cpp +++ b/clients/drcachesim/scheduler/scheduler.cpp @@ -687,6 +687,10 @@ scheduler_tmpl_t::~scheduler_tmpl_t() VPRINT(this, 1, " %-25s: %9" PRId64 "\n", "Migrations", outputs_[i].stats[memtrace_stream_t::SCHED_STAT_MIGRATIONS]); } + VPRINT(this, 1, "%-27s: %9" PRId64 "\n", "Schedule lock acquired", + sched_lock_.get_count_acquired()); + VPRINT(this, 1, "%-27s: %9" PRId64 "\n", "Schedule lock contended", + sched_lock_.get_count_contended()); } template