Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions src/gpgmm/common/EventTraceWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,13 +218,19 @@ namespace gpgmm {

ScopedTraceBufferInTLS* EventTraceWriter::GetOrCreateBufferFromTLS(
std::shared_ptr<EventTraceWriter> writer) {
thread_local std::unique_ptr<ScopedTraceBufferInTLS> bufferInTLS;
if (bufferInTLS == nullptr) {
bufferInTLS.reset(new ScopedTraceBufferInTLS(std::move(writer)));
std::lock_guard<std::mutex> mutex(mMutex);

std::lock_guard<std::mutex> mutex(mMutex);
// Prevent |bufferInTLS| from being accessed after destruction by checking if it was removed
// from the thread id cache then always relinquishing ownership before creation to avoid a
// double delete. This was because the thread storage for |bufferInTLS| was found to be
// reused and never re-initialized to nullptr.
thread_local std::unique_ptr<ScopedTraceBufferInTLS> bufferInTLS;
if (mBufferPerThread.find(std::this_thread::get_id()) == mBufferPerThread.end()) {
bufferInTLS.release();
bufferInTLS = std::make_unique<ScopedTraceBufferInTLS>(std::move(writer));
mBufferPerThread[std::this_thread::get_id()] = bufferInTLS.get();
}

ASSERT(bufferInTLS != nullptr);
return bufferInTLS.get();
}
Expand Down
23 changes: 17 additions & 6 deletions src/gpgmm/common/TraceEvent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,25 @@

namespace gpgmm {

static std::shared_ptr<EventTraceWriter> gEventTrace;
static std::shared_ptr<EventTraceWriter> gEventTraceWriter;
static std::mutex mMutex;

void OnFlushAtExit() {
std::lock_guard<std::mutex> lock(mMutex);
if (gEventTraceWriter != nullptr) {
gEventTraceWriter->FlushQueuedEventsToDisk();
}
}

static EventTraceWriter* GetInstance() {
std::lock_guard<std::mutex> lock(mMutex);
if (gEventTrace == nullptr) {
gEventTrace = std::make_shared<EventTraceWriter>();
if (gEventTraceWriter == nullptr) {
gEventTraceWriter = std::make_shared<EventTraceWriter>();

// Unmerged events never merge if all threads using the writer never terminate.
std::atexit(OnFlushAtExit);
}
return gEventTrace.get();
return gEventTraceWriter.get();
}

void StartupEventTrace(const char* traceFile, const TraceEventPhase& ignoreMask) {
Expand All @@ -53,7 +63,7 @@ namespace gpgmm {

bool IsEventTraceEnabled() {
std::lock_guard<std::mutex> lock(mMutex);
return gEventTrace != nullptr;
return gEventTraceWriter != nullptr;
}

size_t GetQueuedEventsForTesting() {
Expand Down Expand Up @@ -88,7 +98,8 @@ namespace gpgmm {
uint32_t flags,
const JSONDict& args) {
if (IsEventTraceEnabled()) {
GetInstance()->EnqueueTraceEvent(gEventTrace, phase, category, name, id, flags, args);
GetInstance()->EnqueueTraceEvent(gEventTraceWriter, phase, category, name, id, flags,
args);
}
}
} // namespace gpgmm