From a54ea933155986a0af84cbd5426f4beebed778e0 Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Tue, 3 Nov 2015 15:13:09 -0500 Subject: [PATCH] Bug 1221160 - fix AutoTraceLogLock deadlock on Windows; r=froydnj From e3a1e57c0c8be8214a12e31c6e4950a676efd9bc Mon Sep 17 00:00:00 2001 MozReview-Commit-ID: JrPiE7eixpy --HG-- extra : rebase_source : 7f322a0c95c46c0bd1721f982fab8ab421866d70 extra : source : 883ed100b755b9a528104a62ed631beaff6c8cf2 --- xpcom/base/nsTraceRefcnt.cpp | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/xpcom/base/nsTraceRefcnt.cpp b/xpcom/base/nsTraceRefcnt.cpp index caa30e000afb..13ba3f7f7871 100644 --- a/xpcom/base/nsTraceRefcnt.cpp +++ b/xpcom/base/nsTraceRefcnt.cpp @@ -61,17 +61,24 @@ // only held for a very short time, and gets grabbed at a very high frequency // (~100000 times per second). On Mac, the overhead of using a regular lock // is very high, see bug 1137963. -static mozilla::Atomic gTraceLogLocked; +static mozilla::Atomic gTraceLogLocked; struct MOZ_STACK_CLASS AutoTraceLogLock final { + bool doRelease; AutoTraceLogLock() + : doRelease(true) { - while (!gTraceLogLocked.compareExchange(false, true)) { - PR_Sleep(PR_INTERVAL_NO_WAIT); /* yield */ + uintptr_t currentThread = reinterpret_cast(PR_GetCurrentThread()); + if (gTraceLogLocked == currentThread) { + doRelease = false; + } else { + while (!gTraceLogLocked.compareExchange(0, currentThread)) { + PR_Sleep(PR_INTERVAL_NO_WAIT); /* yield */ + } } } - ~AutoTraceLogLock() { gTraceLogLocked = false; } + ~AutoTraceLogLock() { if (doRelease) gTraceLogLocked = 0; } }; static PLHashTable* gBloatView; @@ -1119,14 +1126,14 @@ NS_LogAddRef(void* aPtr, nsrefcnt aRefcnt, bool loggingThisObject = (!gObjectsToLog || LogThisObj(serialno)); if (aRefcnt == 1 && gAllocLog && loggingThisType && loggingThisObject) { - fprintf(gAllocLog, "\n<%s> %p %" PRIdPTR " Create\n", aClass, aPtr, serialno); + fprintf(gAllocLog, "\n<%s> %p %" PRIdPTR " Create [thread %p]\n", aClass, aPtr, serialno, PR_GetCurrentThread()); nsTraceRefcnt::WalkTheStackCached(gAllocLog); } if (gRefcntsLog && loggingThisType && loggingThisObject) { // Can't use MOZ_LOG(), b/c it truncates the line - fprintf(gRefcntsLog, "\n<%s> %p %" PRIuPTR " AddRef %" PRIuPTR "\n", - aClass, aPtr, serialno, aRefcnt); + fprintf(gRefcntsLog, "\n<%s> %p %" PRIuPTR " AddRef %" PRIuPTR " [thread %p]\n", + aClass, aPtr, serialno, aRefcnt, PR_GetCurrentThread()); nsTraceRefcnt::WalkTheStackCached(gRefcntsLog); fflush(gRefcntsLog); } @@ -1173,8 +1180,8 @@ NS_LogRelease(void* aPtr, nsrefcnt aRefcnt, const char* aClass) if (gRefcntsLog && loggingThisType && loggingThisObject) { // Can't use MOZ_LOG(), b/c it truncates the line fprintf(gRefcntsLog, - "\n<%s> %p %" PRIuPTR " Release %" PRIuPTR "\n", - aClass, aPtr, serialno, aRefcnt); + "\n<%s> %p %" PRIuPTR " Release %" PRIuPTR " [thread %p]\n", + aClass, aPtr, serialno, aRefcnt, PR_GetCurrentThread()); nsTraceRefcnt::WalkTheStackCached(gRefcntsLog); fflush(gRefcntsLog); } @@ -1183,7 +1190,7 @@ NS_LogRelease(void* aPtr, nsrefcnt aRefcnt, const char* aClass) // yet we still want to see deletion information: if (aRefcnt == 0 && gAllocLog && loggingThisType && loggingThisObject) { - fprintf(gAllocLog, "\n<%s> %p %" PRIdPTR " Destroy\n", aClass, aPtr, serialno); + fprintf(gAllocLog, "\n<%s> %p %" PRIdPTR " Destroy [thread %p]\n", aClass, aPtr, serialno, PR_GetCurrentThread()); nsTraceRefcnt::WalkTheStackCached(gAllocLog); }