Backed out changeset 4887ddabba31 (bug 939231) for mochitest hangs.

CLOSED TREE
This commit is contained in:
Ryan VanderMeulen 2013-11-21 09:39:38 -05:00
parent 1c0b7690cc
commit 6a90626b1d
5 changed files with 49 additions and 78 deletions

View File

@ -39,7 +39,7 @@ BlockingResourceBase::DeadlockDetectorEntry::Print(
bool aPrintFirstSeenCx) const
{
CallStack lastAcquisition = mAcquisitionContext; // RACY, but benign
bool maybeCurrentlyAcquired = !lastAcquisition.IsEmpty();
bool maybeCurrentlyAcquired = (CallStack::kNone != lastAcquisition);
CallStack printAcquisition =
(aPrintFirstSeenCx || !maybeCurrentlyAcquired) ?
aFirstSeen.mCallContext : lastAcquisition;
@ -134,7 +134,7 @@ BlockingResourceBase::Acquire(const CallStack& aCallContext)
"FIXME bug 456272: annots. to allow Acquire()ing condvars");
return;
}
NS_ASSERTION(mDDEntry->mAcquisitionContext.IsEmpty(),
NS_ASSERTION(mDDEntry->mAcquisitionContext == CallStack::kNone,
"reacquiring already acquired resource");
ResourceChainAppend(ResourceChainFront());
@ -152,7 +152,8 @@ BlockingResourceBase::Release()
}
BlockingResourceBase* chainFront = ResourceChainFront();
NS_ASSERTION(chainFront && !mDDEntry->mAcquisitionContext.IsEmpty(),
NS_ASSERTION(chainFront
&& CallStack::kNone != mDDEntry->mAcquisitionContext,
"Release()ing something that hasn't been Acquire()ed");
if (chainFront == this) {
@ -177,7 +178,7 @@ BlockingResourceBase::Release()
curr->mChainPrev = prev->mChainPrev;
}
mDDEntry->mAcquisitionContext = CallStack::NullCallStack();
mDDEntry->mAcquisitionContext = CallStack::kNone;
}
@ -300,7 +301,7 @@ ReentrantMonitor::Wait(PRIntervalTime interval)
CallStack savedAcquisitionContext = GetAcquisitionContext();
BlockingResourceBase* savedChainPrev = mChainPrev;
mEntryCount = 0;
SetAcquisitionContext(CallStack::NullCallStack());
SetAcquisitionContext(CallStack::kNone);
mChainPrev = 0;
// give up the monitor until we're back from Wait()
@ -327,7 +328,7 @@ CondVar::Wait(PRIntervalTime interval)
// save mutex state and reset to empty
CallStack savedAcquisitionContext = mLock->GetAcquisitionContext();
BlockingResourceBase* savedChainPrev = mLock->mChainPrev;
mLock->SetAcquisitionContext(CallStack::NullCallStack());
mLock->SetAcquisitionContext(CallStack::kNone);
mLock->mChainPrev = 0;
// give up mutex until we're back from Wait()

View File

@ -74,7 +74,7 @@ private:
BlockingResourceType aType) :
mName(aName),
mType(aType),
mAcquisitionContext(CallStack::NullCallStack())
mAcquisitionContext(CallStack::kNone)
{
NS_ABORT_IF_FALSE(mName, "Name must be nonnull");
}
@ -117,7 +117,7 @@ private:
/**
* mAcquisitionContext
* The calling context from which this resource was acquired, or
* |CallStack::NullCallStack()| if it is currently free (or freed).
* |CallStack::kNone| if it is currently free (or freed).
*/
CallStack mAcquisitionContext;
};
@ -239,7 +239,7 @@ protected:
/**
* GetAcquisitionContext
* Return the calling context from which this resource was acquired,
* or CallStack::NullCallStack() if it's currently free.
* or CallStack::kNone if it's currently free.
*
* *NOT* thread safe. Requires ownership of underlying resource.
*/

View File

@ -5,46 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "DeadlockDetector.h"
#include "nsStackWalk.h"
#include "mozilla/Util.h"
namespace mozilla {
static void
StackCallback(void* pc, void* sp, void* closure)
{
nsTArray<void*>* stack = static_cast<nsTArray<void*>*>(closure);
stack->AppendElement(pc);
}
nsTArray<void*>
CallStack::GetBacktrace()
{
nsTArray<void*> callstack;
callstack.SetCapacity(32); // Hopefully 32 frames is a good average
NS_StackWalk(StackCallback, 2, 0, &callstack, 0, nullptr);
return mozilla::Move(callstack);
}
void
CallStack::Print(FILE* f) const
{
if (mCallStack.IsEmpty()) {
fputs(" [stack trace unavailable]\n", f);
} else {
nsCodeAddressDetails addr;
for (uint32_t i = 0; i < mCallStack.Length(); ++i) {
nsresult rv = NS_DescribeCodeAddress(mCallStack[i], &addr);
if (NS_SUCCEEDED(rv)) {
char buf[1024];
NS_FormatCodeAddressDetails(mCallStack[i], &addr, buf, ArrayLength(buf));
fputs(buf, f);
} else {
fprintf(f, "Frame information for %p unavailable", mCallStack[i]);
}
}
}
fflush(f);
}
const CallStack CallStack::kNone((CallStack::callstack_id) -1);
}

View File

@ -7,7 +7,6 @@
#define mozilla_DeadlockDetector_h
#include "mozilla/Attributes.h"
#include "mozilla/Move.h"
#include <stdlib.h>
@ -16,13 +15,30 @@
#include "nsTArray.h"
#ifdef NS_TRACE_MALLOC
# include "nsTraceMalloc.h"
#endif // ifdef NS_TRACE_MALLOC
namespace mozilla {
// FIXME bug 456272: split this off into a convenience API on top of
// nsStackWalk?
class NS_COM_GLUE CallStack
{
private:
nsTArray<void*> mCallStack;
#ifdef NS_TRACE_MALLOC
typedef nsTMStackTraceID callstack_id;
// needs to be a macro to avoid disturbing the backtrace
# define NS_GET_BACKTRACE() NS_TraceMallocGetStackTrace()
# define NS_DEADLOCK_DETECTOR_CONSTEXPR
#else
typedef void* callstack_id;
# define NS_GET_BACKTRACE() 0
# define NS_DEADLOCK_DETECTOR_CONSTEXPR MOZ_CONSTEXPR
#endif // ifdef NS_TRACE_MALLOC
callstack_id mCallStack;
public:
/**
@ -37,10 +53,12 @@ public:
* constructor: it *will* construct a backtrace. This can cause
* unexpected performance issues.
*/
CallStack(const nsTArray<void*>& aCallStack = GetBacktrace()) :
mCallStack(mozilla::Move(aCallStack))
NS_DEADLOCK_DETECTOR_CONSTEXPR
CallStack(const callstack_id aCallStack = NS_GET_BACKTRACE()) :
mCallStack(aCallStack)
{
}
NS_DEADLOCK_DETECTOR_CONSTEXPR
CallStack(const CallStack& aFrom) :
mCallStack(aFrom.mCallStack)
{
@ -59,19 +77,22 @@ public:
return mCallStack != aOther.mCallStack;
}
bool IsEmpty() const
// FIXME bug 456272: if this is split off,
// NS_TraceMallocPrintStackTrace should be modified to print into
// an nsACString
void Print(FILE* f) const
{
return mCallStack.IsEmpty();
#ifdef NS_TRACE_MALLOC
if (this != &kNone && mCallStack) {
NS_TraceMallocPrintStackTrace(f, mCallStack);
return;
}
#endif
fputs(" [stack trace unavailable]\n", f);
}
void Print(FILE* f) const;
static nsTArray<void*> GetBacktrace();
static const CallStack NullCallStack()
{
return CallStack(nsTArray<void*>());
}
/** The "null" callstack. */
static const CallStack kNone;
};
@ -137,7 +158,7 @@ public:
ResourceAcquisition(
const T* aResource,
const CallStack aCallContext=CallStack::NullCallStack()) :
const CallStack aCallContext=CallStack::kNone) :
mResource(aResource),
mCallContext(aCallContext)
{
@ -174,7 +195,7 @@ private:
struct OrderingEntry
{
OrderingEntry() :
mFirstSeen(CallStack::NullCallStack()),
mFirstSeen(CallStack::kNone),
mOrderedLT() // FIXME bug 456272: set to empirical
{ // dep size?
}
@ -386,7 +407,7 @@ public:
PLHashEntry* second = *GetEntry(aProposed);
OrderingEntry* e = static_cast<OrderingEntry*>(second->value);
if (e->mFirstSeen.IsEmpty())
if (CallStack::kNone == e->mFirstSeen)
e->mFirstSeen = aCallContext;
if (!aLast)

View File

@ -1653,18 +1653,6 @@ public:
nsTArray() {}
explicit nsTArray(size_type capacity) : base_type(capacity) {}
explicit nsTArray(const nsTArray& other) : base_type(other) {}
nsTArray(nsTArray&& other) {
this->SwapElements(other);
}
nsTArray& operator=(const nsTArray& other) {
base_type::operator=(other);
return *this;
}
nsTArray& operator=(nsTArray&& other) {
this->SwapElements(other);
return *this;
}
template<class Allocator>
explicit nsTArray(const nsTArray_Impl<E, Allocator>& other) : base_type(other) {}