diff --git a/llvm/lib/Support/TimeProfiler.cpp b/llvm/lib/Support/TimeProfiler.cpp --- a/llvm/lib/Support/TimeProfiler.cpp +++ b/llvm/lib/Support/TimeProfiler.cpp @@ -14,7 +14,6 @@ #include "llvm/ADT/STLFunctionalExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/JSON.h" -#include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Path.h" #include "llvm/Support/Process.h" #include "llvm/Support/Threading.h" @@ -28,10 +27,20 @@ using namespace std::chrono; using namespace llvm; -static std::mutex Mu; -// List of all instances -static ManagedStatic> - ThreadTimeTraceProfilerInstances; // GUARDED_BY(Mu) +namespace { + +struct TimeTraceProfilerInstances { + std::mutex Lock; + std::vector List; +}; + +TimeTraceProfilerInstances &getTimeTraceProfilerInstances() { + static TimeTraceProfilerInstances Instances; + return Instances; +} + +} // anonymous namespace + // Per Thread instance static LLVM_THREAD_LOCAL TimeTraceProfiler *TimeTraceProfilerInstance = nullptr; @@ -124,10 +133,11 @@ // ThreadTimeTraceProfilerInstances. void write(raw_pwrite_stream &OS) { // Acquire Mutex as reading ThreadTimeTraceProfilerInstances. - std::lock_guard Lock(Mu); + auto &Instances = getTimeTraceProfilerInstances(); + std::lock_guard Lock(Instances.Lock); assert(Stack.empty() && "All profiler sections should be ended when calling write"); - assert(llvm::all_of(*ThreadTimeTraceProfilerInstances, + assert(llvm::all_of(Instances.List, [](const auto &TTP) { return TTP->Stack.empty(); }) && "All profiler sections should be ended when calling write"); @@ -155,7 +165,7 @@ }; for (const Entry &E : Entries) writeEvent(E, this->Tid); - for (const TimeTraceProfiler *TTP : *ThreadTimeTraceProfilerInstances) + for (const TimeTraceProfiler *TTP : Instances.List) for (const Entry &E : TTP->Entries) writeEvent(E, TTP->Tid); @@ -163,7 +173,7 @@ // longest one. // Find highest used thread id. uint64_t MaxTid = this->Tid; - for (const TimeTraceProfiler *TTP : *ThreadTimeTraceProfilerInstances) + for (const TimeTraceProfiler *TTP : Instances.List) MaxTid = std::max(MaxTid, TTP->Tid); // Combine all CountAndTotalPerName from threads into one. @@ -177,7 +187,7 @@ }; for (const auto &Stat : CountAndTotalPerName) combineStat(Stat); - for (const TimeTraceProfiler *TTP : *ThreadTimeTraceProfilerInstances) + for (const TimeTraceProfiler *TTP : Instances.List) for (const auto &Stat : TTP->CountAndTotalPerName) combineStat(Stat); @@ -228,7 +238,7 @@ writeMetadataEvent("process_name", Tid, ProcName); writeMetadataEvent("thread_name", Tid, ThreadName); - for (const TimeTraceProfiler *TTP : *ThreadTimeTraceProfilerInstances) + for (const TimeTraceProfiler *TTP : Instances.List) writeMetadataEvent("thread_name", TTP->Tid, TTP->ThreadName); J.arrayEnd(); @@ -272,17 +282,20 @@ void llvm::timeTraceProfilerCleanup() { delete TimeTraceProfilerInstance; TimeTraceProfilerInstance = nullptr; - std::lock_guard Lock(Mu); - for (auto *TTP : *ThreadTimeTraceProfilerInstances) + + auto &Instances = getTimeTraceProfilerInstances(); + std::lock_guard Lock(Instances.Lock); + for (auto *TTP : Instances.List) delete TTP; - ThreadTimeTraceProfilerInstances->clear(); + Instances.List.clear(); } // Finish TimeTraceProfilerInstance on a worker thread. // This doesn't remove the instance, just moves the pointer to global vector. void llvm::timeTraceProfilerFinishThread() { - std::lock_guard Lock(Mu); - ThreadTimeTraceProfilerInstances->push_back(TimeTraceProfilerInstance); + auto &Instances = getTimeTraceProfilerInstances(); + std::lock_guard Lock(Instances.Lock); + Instances.List.push_back(TimeTraceProfilerInstance); TimeTraceProfilerInstance = nullptr; }