mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Backed out changeset 4887ddabba31 (bug 939231) for mochitest hangs.
CLOSED TREE
This commit is contained in:
parent
1c0b7690cc
commit
6a90626b1d
@ -39,7 +39,7 @@ BlockingResourceBase::DeadlockDetectorEntry::Print(
|
|||||||
bool aPrintFirstSeenCx) const
|
bool aPrintFirstSeenCx) const
|
||||||
{
|
{
|
||||||
CallStack lastAcquisition = mAcquisitionContext; // RACY, but benign
|
CallStack lastAcquisition = mAcquisitionContext; // RACY, but benign
|
||||||
bool maybeCurrentlyAcquired = !lastAcquisition.IsEmpty();
|
bool maybeCurrentlyAcquired = (CallStack::kNone != lastAcquisition);
|
||||||
CallStack printAcquisition =
|
CallStack printAcquisition =
|
||||||
(aPrintFirstSeenCx || !maybeCurrentlyAcquired) ?
|
(aPrintFirstSeenCx || !maybeCurrentlyAcquired) ?
|
||||||
aFirstSeen.mCallContext : lastAcquisition;
|
aFirstSeen.mCallContext : lastAcquisition;
|
||||||
@ -134,7 +134,7 @@ BlockingResourceBase::Acquire(const CallStack& aCallContext)
|
|||||||
"FIXME bug 456272: annots. to allow Acquire()ing condvars");
|
"FIXME bug 456272: annots. to allow Acquire()ing condvars");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
NS_ASSERTION(mDDEntry->mAcquisitionContext.IsEmpty(),
|
NS_ASSERTION(mDDEntry->mAcquisitionContext == CallStack::kNone,
|
||||||
"reacquiring already acquired resource");
|
"reacquiring already acquired resource");
|
||||||
|
|
||||||
ResourceChainAppend(ResourceChainFront());
|
ResourceChainAppend(ResourceChainFront());
|
||||||
@ -152,7 +152,8 @@ BlockingResourceBase::Release()
|
|||||||
}
|
}
|
||||||
|
|
||||||
BlockingResourceBase* chainFront = ResourceChainFront();
|
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");
|
"Release()ing something that hasn't been Acquire()ed");
|
||||||
|
|
||||||
if (chainFront == this) {
|
if (chainFront == this) {
|
||||||
@ -177,7 +178,7 @@ BlockingResourceBase::Release()
|
|||||||
curr->mChainPrev = prev->mChainPrev;
|
curr->mChainPrev = prev->mChainPrev;
|
||||||
}
|
}
|
||||||
|
|
||||||
mDDEntry->mAcquisitionContext = CallStack::NullCallStack();
|
mDDEntry->mAcquisitionContext = CallStack::kNone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -300,7 +301,7 @@ ReentrantMonitor::Wait(PRIntervalTime interval)
|
|||||||
CallStack savedAcquisitionContext = GetAcquisitionContext();
|
CallStack savedAcquisitionContext = GetAcquisitionContext();
|
||||||
BlockingResourceBase* savedChainPrev = mChainPrev;
|
BlockingResourceBase* savedChainPrev = mChainPrev;
|
||||||
mEntryCount = 0;
|
mEntryCount = 0;
|
||||||
SetAcquisitionContext(CallStack::NullCallStack());
|
SetAcquisitionContext(CallStack::kNone);
|
||||||
mChainPrev = 0;
|
mChainPrev = 0;
|
||||||
|
|
||||||
// give up the monitor until we're back from Wait()
|
// 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
|
// save mutex state and reset to empty
|
||||||
CallStack savedAcquisitionContext = mLock->GetAcquisitionContext();
|
CallStack savedAcquisitionContext = mLock->GetAcquisitionContext();
|
||||||
BlockingResourceBase* savedChainPrev = mLock->mChainPrev;
|
BlockingResourceBase* savedChainPrev = mLock->mChainPrev;
|
||||||
mLock->SetAcquisitionContext(CallStack::NullCallStack());
|
mLock->SetAcquisitionContext(CallStack::kNone);
|
||||||
mLock->mChainPrev = 0;
|
mLock->mChainPrev = 0;
|
||||||
|
|
||||||
// give up mutex until we're back from Wait()
|
// give up mutex until we're back from Wait()
|
||||||
|
@ -74,7 +74,7 @@ private:
|
|||||||
BlockingResourceType aType) :
|
BlockingResourceType aType) :
|
||||||
mName(aName),
|
mName(aName),
|
||||||
mType(aType),
|
mType(aType),
|
||||||
mAcquisitionContext(CallStack::NullCallStack())
|
mAcquisitionContext(CallStack::kNone)
|
||||||
{
|
{
|
||||||
NS_ABORT_IF_FALSE(mName, "Name must be nonnull");
|
NS_ABORT_IF_FALSE(mName, "Name must be nonnull");
|
||||||
}
|
}
|
||||||
@ -117,7 +117,7 @@ private:
|
|||||||
/**
|
/**
|
||||||
* mAcquisitionContext
|
* mAcquisitionContext
|
||||||
* The calling context from which this resource was acquired, or
|
* 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;
|
CallStack mAcquisitionContext;
|
||||||
};
|
};
|
||||||
@ -239,7 +239,7 @@ protected:
|
|||||||
/**
|
/**
|
||||||
* GetAcquisitionContext
|
* GetAcquisitionContext
|
||||||
* Return the calling context from which this resource was acquired,
|
* 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.
|
* *NOT* thread safe. Requires ownership of underlying resource.
|
||||||
*/
|
*/
|
||||||
|
@ -5,46 +5,7 @@
|
|||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "DeadlockDetector.h"
|
#include "DeadlockDetector.h"
|
||||||
#include "nsStackWalk.h"
|
|
||||||
#include "mozilla/Util.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
const CallStack CallStack::kNone((CallStack::callstack_id) -1);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
#define mozilla_DeadlockDetector_h
|
#define mozilla_DeadlockDetector_h
|
||||||
|
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
#include "mozilla/Move.h"
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
@ -16,13 +15,30 @@
|
|||||||
|
|
||||||
#include "nsTArray.h"
|
#include "nsTArray.h"
|
||||||
|
|
||||||
|
#ifdef NS_TRACE_MALLOC
|
||||||
|
# include "nsTraceMalloc.h"
|
||||||
|
#endif // ifdef NS_TRACE_MALLOC
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
|
|
||||||
|
// FIXME bug 456272: split this off into a convenience API on top of
|
||||||
|
// nsStackWalk?
|
||||||
class NS_COM_GLUE CallStack
|
class NS_COM_GLUE CallStack
|
||||||
{
|
{
|
||||||
private:
|
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:
|
public:
|
||||||
/**
|
/**
|
||||||
@ -37,10 +53,12 @@ public:
|
|||||||
* constructor: it *will* construct a backtrace. This can cause
|
* constructor: it *will* construct a backtrace. This can cause
|
||||||
* unexpected performance issues.
|
* unexpected performance issues.
|
||||||
*/
|
*/
|
||||||
CallStack(const nsTArray<void*>& aCallStack = GetBacktrace()) :
|
NS_DEADLOCK_DETECTOR_CONSTEXPR
|
||||||
mCallStack(mozilla::Move(aCallStack))
|
CallStack(const callstack_id aCallStack = NS_GET_BACKTRACE()) :
|
||||||
|
mCallStack(aCallStack)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
NS_DEADLOCK_DETECTOR_CONSTEXPR
|
||||||
CallStack(const CallStack& aFrom) :
|
CallStack(const CallStack& aFrom) :
|
||||||
mCallStack(aFrom.mCallStack)
|
mCallStack(aFrom.mCallStack)
|
||||||
{
|
{
|
||||||
@ -59,19 +77,22 @@ public:
|
|||||||
return mCallStack != aOther.mCallStack;
|
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;
|
/** The "null" callstack. */
|
||||||
|
static const CallStack kNone;
|
||||||
static nsTArray<void*> GetBacktrace();
|
|
||||||
|
|
||||||
static const CallStack NullCallStack()
|
|
||||||
{
|
|
||||||
return CallStack(nsTArray<void*>());
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -137,7 +158,7 @@ public:
|
|||||||
|
|
||||||
ResourceAcquisition(
|
ResourceAcquisition(
|
||||||
const T* aResource,
|
const T* aResource,
|
||||||
const CallStack aCallContext=CallStack::NullCallStack()) :
|
const CallStack aCallContext=CallStack::kNone) :
|
||||||
mResource(aResource),
|
mResource(aResource),
|
||||||
mCallContext(aCallContext)
|
mCallContext(aCallContext)
|
||||||
{
|
{
|
||||||
@ -174,7 +195,7 @@ private:
|
|||||||
struct OrderingEntry
|
struct OrderingEntry
|
||||||
{
|
{
|
||||||
OrderingEntry() :
|
OrderingEntry() :
|
||||||
mFirstSeen(CallStack::NullCallStack()),
|
mFirstSeen(CallStack::kNone),
|
||||||
mOrderedLT() // FIXME bug 456272: set to empirical
|
mOrderedLT() // FIXME bug 456272: set to empirical
|
||||||
{ // dep size?
|
{ // dep size?
|
||||||
}
|
}
|
||||||
@ -386,7 +407,7 @@ public:
|
|||||||
|
|
||||||
PLHashEntry* second = *GetEntry(aProposed);
|
PLHashEntry* second = *GetEntry(aProposed);
|
||||||
OrderingEntry* e = static_cast<OrderingEntry*>(second->value);
|
OrderingEntry* e = static_cast<OrderingEntry*>(second->value);
|
||||||
if (e->mFirstSeen.IsEmpty())
|
if (CallStack::kNone == e->mFirstSeen)
|
||||||
e->mFirstSeen = aCallContext;
|
e->mFirstSeen = aCallContext;
|
||||||
|
|
||||||
if (!aLast)
|
if (!aLast)
|
||||||
|
@ -1653,18 +1653,6 @@ public:
|
|||||||
nsTArray() {}
|
nsTArray() {}
|
||||||
explicit nsTArray(size_type capacity) : base_type(capacity) {}
|
explicit nsTArray(size_type capacity) : base_type(capacity) {}
|
||||||
explicit nsTArray(const nsTArray& other) : base_type(other) {}
|
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>
|
template<class Allocator>
|
||||||
explicit nsTArray(const nsTArray_Impl<E, Allocator>& other) : base_type(other) {}
|
explicit nsTArray(const nsTArray_Impl<E, Allocator>& other) : base_type(other) {}
|
||||||
|
Loading…
Reference in New Issue
Block a user