Index: clangd/Threading.h =================================================================== --- clangd/Threading.h +++ clangd/Threading.h @@ -13,7 +13,9 @@ #include "Context.h" #include "Function.h" #include "llvm/ADT/Twine.h" +#include #include +#include #include #include #include @@ -118,6 +120,18 @@ std::size_t InFlightTasks = 0; }; +class Mutex { +public: + ~Mutex(); + + void lock(); + void unlock(); + +private: + std::mutex Mut; + std::chrono::steady_clock::duration WaitAllCPUs; +}; + enum class ThreadPriority { Low = 0, Normal = 1, Index: clangd/Threading.cpp =================================================================== --- clangd/Threading.cpp +++ clangd/Threading.cpp @@ -1,9 +1,11 @@ #include "Threading.h" +#include "Logger.h" #include "Trace.h" #include "llvm/ADT/ScopeExit.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/Threading.h" #include +#include #include #ifdef __USE_POSIX #include @@ -127,5 +129,23 @@ void preventThreadStarvationInTests() { AvoidThreadStarvation = true; } +Mutex::~Mutex() { + log("Lock '{0}' was contended for {1} ms.", this, + std::chrono::duration_cast(WaitAllCPUs).count()); +} + +void Mutex::lock() { + if (Mut.try_lock()) + return; + + auto Start = std::chrono::steady_clock::now(); + Mut.lock(); + WaitAllCPUs += std::chrono::steady_clock::now() - Start; +} + +void Mutex::unlock() { + Mut.unlock(); +} + } // namespace clangd } // namespace clang