Backed out 10 changesets (bug 1033358, bug 774388, bug 1028383) for causing frequent shutdown crashes on a CLOSED TREE.

Backed out changeset a54b05c9e4a1 (bug 1028383)
Backed out changeset 37985f79e0c2 (bug 774388)
Backed out changeset d07521729077 (bug 774388)
Backed out changeset 9f14b17f358c (bug 774388)
Backed out changeset 2d347d6aa9bc (bug 774388)
Backed out changeset 99581dfb5ec4 (bug 774388)
Backed out changeset 2532e22d6135 (bug 774388)
Backed out changeset 719844108f1a (bug 774388)
Backed out changeset 7829c78348a4 (bug 1033358)
Backed out changeset c571df9a85de (bug 1033358)
This commit is contained in:
Ryan VanderMeulen 2014-07-03 20:37:05 -04:00
parent 3f9e56aab8
commit 6d9424856d
17 changed files with 199 additions and 308 deletions

View File

@ -17,7 +17,6 @@
#include "nsCOMPtr.h" // for nsCOMPtr #include "nsCOMPtr.h" // for nsCOMPtr
#include "nsHashKeys.h" // for nsUint64HashKey #include "nsHashKeys.h" // for nsUint64HashKey
#include "nsISupportsImpl.h" // for NS_INLINE_DECL_REFCOUNTING #include "nsISupportsImpl.h" // for NS_INLINE_DECL_REFCOUNTING
#include "ThreadSafeRefcountingWithMainThreadDestruction.h"
class nsIObserver; class nsIObserver;
@ -30,8 +29,7 @@ struct FrameMetrics;
class CompositorChild MOZ_FINAL : public PCompositorChild class CompositorChild MOZ_FINAL : public PCompositorChild
{ {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(CompositorChild) NS_INLINE_DECL_REFCOUNTING(CompositorChild)
public: public:
CompositorChild(ClientLayerManager *aLayerManager); CompositorChild(ClientLayerManager *aLayerManager);

View File

@ -53,7 +53,6 @@
#include "mozilla/unused.h" #include "mozilla/unused.h"
#include "mozilla/Hal.h" #include "mozilla/Hal.h"
#include "mozilla/HalTypes.h" #include "mozilla/HalTypes.h"
#include "mozilla/StaticPtr.h"
namespace mozilla { namespace mozilla {
namespace layers { namespace layers {
@ -74,78 +73,64 @@ CompositorParent::LayerTreeState::LayerTreeState()
typedef map<uint64_t, CompositorParent::LayerTreeState> LayerTreeMap; typedef map<uint64_t, CompositorParent::LayerTreeState> LayerTreeMap;
static LayerTreeMap sIndirectLayerTrees; static LayerTreeMap sIndirectLayerTrees;
/** // FIXME/bug 774386: we're assuming that there's only one
* A global map referencing each compositor by ID. // CompositorParent, but that's not always true. This assumption only
* // affects CrossProcessCompositorParent below.
* This map is used by the ImageBridge protocol to trigger static Thread* sCompositorThread = nullptr;
* compositions without having to keep references to the // manual reference count of the compositor thread.
* compositor static int sCompositorThreadRefCount = 0;
*/ static MessageLoop* sMainLoop = nullptr;
typedef map<uint64_t,CompositorParent*> CompositorMap;
static CompositorMap* sCompositorMap;
static void CreateCompositorMap()
{
MOZ_ASSERT(!sCompositorMap);
sCompositorMap = new CompositorMap;
}
static void DestroyCompositorMap()
{
MOZ_ASSERT(sCompositorMap);
MOZ_ASSERT(sCompositorMap->empty());
delete sCompositorMap;
sCompositorMap = nullptr;
}
// See ImageBridgeChild.cpp // See ImageBridgeChild.cpp
void ReleaseImageBridgeParentSingleton(); void ReleaseImageBridgeParentSingleton();
class CompositorThreadHolder MOZ_FINAL static void DeferredDeleteCompositorParent(CompositorParent* aNowReadyToDie)
{ {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(CompositorThreadHolder) aNowReadyToDie->Release();
}
public: static void DeleteCompositorThread()
CompositorThreadHolder()
: mCompositorThread(CreateCompositorThread())
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_COUNT_CTOR(CompositorThreadHolder);
}
Thread* GetCompositorThread() const {
return mCompositorThread;
}
private:
~CompositorThreadHolder()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_COUNT_DTOR(CompositorThreadHolder);
DestroyCompositorThread(mCompositorThread);
}
Thread* const mCompositorThread;
static Thread* CreateCompositorThread();
static void DestroyCompositorThread(Thread* aCompositorThread);
friend class CompositorParent;
};
static StaticRefPtr<CompositorThreadHolder> sCompositorThreadHolder;
static bool sFinishedCompositorShutDown = false;
/* static */ Thread*
CompositorThreadHolder::CreateCompositorThread()
{ {
MOZ_ASSERT(NS_IsMainThread()); if (NS_IsMainThread()){
ReleaseImageBridgeParentSingleton();
delete sCompositorThread;
sCompositorThread = nullptr;
} else {
sMainLoop->PostTask(FROM_HERE, NewRunnableFunction(&DeleteCompositorThread));
}
}
MOZ_ASSERT(!sCompositorThreadHolder, "The compositor thread has already been started!"); static void ReleaseCompositorThread()
{
if(--sCompositorThreadRefCount == 0) {
DeleteCompositorThread();
}
}
Thread* compositorThread = new Thread("Compositor"); static void SetThreadPriority()
{
hal::SetCurrentThreadPriority(hal::THREAD_PRIORITY_COMPOSITOR);
}
void CompositorParent::StartUp()
{
CreateCompositorMap();
CreateThread();
sMainLoop = MessageLoop::current();
}
void CompositorParent::ShutDown()
{
DestroyThread();
DestroyCompositorMap();
}
bool CompositorParent::CreateThread()
{
NS_ASSERTION(NS_IsMainThread(), "Should be on the main Thread!");
MOZ_ASSERT(!sCompositorThread);
sCompositorThreadRefCount = 1;
sCompositorThread = new Thread("Compositor");
Thread::Options options; Thread::Options options;
/* Timeout values are powers-of-two to enable us get better data. /* Timeout values are powers-of-two to enable us get better data.
@ -156,63 +141,24 @@ CompositorThreadHolder::CreateCompositorThread()
than the default hang timeout on major platforms (about 5 seconds). */ than the default hang timeout on major platforms (about 5 seconds). */
options.permanent_hang_timeout = 8192; // milliseconds options.permanent_hang_timeout = 8192; // milliseconds
if (!compositorThread->StartWithOptions(options)) { if (!sCompositorThread->StartWithOptions(options)) {
delete compositorThread; delete sCompositorThread;
return nullptr; sCompositorThread = nullptr;
return false;
} }
CreateCompositorMap(); return true;
return compositorThread;
} }
/* static */ void void CompositorParent::DestroyThread()
CompositorThreadHolder::DestroyCompositorThread(Thread* aCompositorThread)
{ {
MOZ_ASSERT(NS_IsMainThread()); NS_ASSERTION(NS_IsMainThread(), "Should be on the main Thread!");
ReleaseCompositorThread();
MOZ_ASSERT(!sCompositorThreadHolder, "We shouldn't be destroying the compositor thread yet.");
DestroyCompositorMap();
ReleaseImageBridgeParentSingleton();
delete aCompositorThread;
sFinishedCompositorShutDown = true;
}
static Thread* CompositorThread() {
return sCompositorThreadHolder ? sCompositorThreadHolder->GetCompositorThread() : nullptr;
}
static void SetThreadPriority()
{
hal::SetCurrentThreadPriority(hal::THREAD_PRIORITY_COMPOSITOR);
}
void CompositorParent::StartUp()
{
MOZ_ASSERT(NS_IsMainThread(), "Should be on the main Thread!");
MOZ_ASSERT(!sCompositorThreadHolder, "The compositor thread has already been started!");
sCompositorThreadHolder = new CompositorThreadHolder();
}
void CompositorParent::ShutDown()
{
MOZ_ASSERT(NS_IsMainThread(), "Should be on the main Thread!");
MOZ_ASSERT(sCompositorThreadHolder, "The compositor thread has already been shut down!");
sCompositorThreadHolder = nullptr;
// No locking is needed around sFinishedCompositorShutDown because it is only
// ever accessed on the main thread.
while (!sFinishedCompositorShutDown) {
NS_ProcessNextEvent(nullptr, true);
}
} }
MessageLoop* CompositorParent::CompositorLoop() MessageLoop* CompositorParent::CompositorLoop()
{ {
return CompositorThread() ? CompositorThread()->message_loop() : nullptr; return sCompositorThread ? sCompositorThread->message_loop() : nullptr;
} }
CompositorParent::CompositorParent(nsIWidget* aWidget, CompositorParent::CompositorParent(nsIWidget* aWidget,
@ -229,11 +175,9 @@ CompositorParent::CompositorParent(nsIWidget* aWidget,
, mResumeCompositionMonitor("ResumeCompositionMonitor") , mResumeCompositionMonitor("ResumeCompositionMonitor")
, mOverrideComposeReadiness(false) , mOverrideComposeReadiness(false)
, mForceCompositionTask(nullptr) , mForceCompositionTask(nullptr)
, mCompositorThreadHolder(sCompositorThreadHolder)
{ {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(sCompositorThread != nullptr,
MOZ_ASSERT(CompositorThread(), "The compositor thread must be Initialized before instanciating a CmpositorParent.");
"The compositor thread must be Initialized before instanciating a CompositorParent.");
MOZ_COUNT_CTOR(CompositorParent); MOZ_COUNT_CTOR(CompositorParent);
mCompositorID = 0; mCompositorID = 0;
// FIXME: This holds on the the fact that right now the only thing that // FIXME: This holds on the the fact that right now the only thing that
@ -248,12 +192,13 @@ CompositorParent::CompositorParent(nsIWidget* aWidget,
sIndirectLayerTrees[mRootLayerTreeID].mParent = this; sIndirectLayerTrees[mRootLayerTreeID].mParent = this;
mApzcTreeManager = new APZCTreeManager(); mApzcTreeManager = new APZCTreeManager();
++sCompositorThreadRefCount;
} }
bool bool
CompositorParent::IsInCompositorThread() CompositorParent::IsInCompositorThread()
{ {
return CompositorThread() && CompositorThread()->thread_id() == PlatformThread::CurrentId(); return sCompositorThread && sCompositorThread->thread_id() == PlatformThread::CurrentId();
} }
uint64_t uint64_t
@ -264,8 +209,9 @@ CompositorParent::RootLayerTreeId()
CompositorParent::~CompositorParent() CompositorParent::~CompositorParent()
{ {
MOZ_ASSERT(NS_IsMainThread());
MOZ_COUNT_DTOR(CompositorParent); MOZ_COUNT_DTOR(CompositorParent);
ReleaseCompositorThread();
} }
void void
@ -318,13 +264,6 @@ CompositorParent::RecvWillStop()
return true; return true;
} }
void CompositorParent::DeferredDestroy()
{
MOZ_ASSERT(!NS_IsMainThread());
mCompositorThreadHolder = nullptr;
Release();
}
bool bool
CompositorParent::RecvStop() CompositorParent::RecvStop()
{ {
@ -334,9 +273,10 @@ CompositorParent::RecvStop()
// this thread. // this thread.
// We must keep the compositor parent alive untill the code handling message // We must keep the compositor parent alive untill the code handling message
// reception is finished on this thread. // reception is finished on this thread.
this->AddRef(); // Corresponds to DeferredDestroy's Release this->AddRef(); // Corresponds to DeferredDeleteCompositorParent's Release
MessageLoop::current()->PostTask(FROM_HERE, CompositorLoop()->PostTask(FROM_HERE,
NewRunnableMethod(this,&CompositorParent::DeferredDestroy)); NewRunnableFunction(&DeferredDeleteCompositorParent,
this));
return true; return true;
} }
@ -981,6 +921,27 @@ CompositorParent::DeallocPLayerTransactionParent(PLayerTransactionParent* actor)
return true; return true;
} }
typedef map<uint64_t,CompositorParent*> CompositorMap;
static CompositorMap* sCompositorMap;
void CompositorParent::CreateCompositorMap()
{
if (sCompositorMap == nullptr) {
sCompositorMap = new CompositorMap;
}
}
void CompositorParent::DestroyCompositorMap()
{
if (sCompositorMap != nullptr) {
NS_ASSERTION(sCompositorMap->empty(),
"The Compositor map should be empty when destroyed>");
delete sCompositorMap;
sCompositorMap = nullptr;
}
}
CompositorParent* CompositorParent::GetCompositor(uint64_t id) CompositorParent* CompositorParent::GetCompositor(uint64_t id)
{ {
CompositorMap::iterator it = sCompositorMap->find(id); CompositorMap::iterator it = sCompositorMap->find(id);
@ -1116,15 +1077,12 @@ class CrossProcessCompositorParent MOZ_FINAL : public PCompositorParent,
{ {
friend class CompositorParent; friend class CompositorParent;
NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(CrossProcessCompositorParent) NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CrossProcessCompositorParent)
public: public:
CrossProcessCompositorParent(Transport* aTransport, ProcessId aOtherProcess) CrossProcessCompositorParent(Transport* aTransport, ProcessId aOtherProcess)
: mTransport(aTransport) : mTransport(aTransport)
, mChildProcessId(aOtherProcess) , mChildProcessId(aOtherProcess)
, mCompositorThreadHolder(sCompositorThreadHolder) {}
{
MOZ_ASSERT(NS_IsMainThread());
}
// IToplevelProtocol::CloneToplevel() // IToplevelProtocol::CloneToplevel()
virtual IToplevelProtocol* virtual IToplevelProtocol*
@ -1187,8 +1145,6 @@ private:
Transport* mTransport; Transport* mTransport;
// Child side's process Id. // Child side's process Id.
base::ProcessId mChildProcessId; base::ProcessId mChildProcessId;
nsRefPtr<CompositorThreadHolder> mCompositorThreadHolder;
}; };
void void
@ -1220,8 +1176,6 @@ OpenCompositor(CrossProcessCompositorParent* aCompositor,
/*static*/ PCompositorParent* /*static*/ PCompositorParent*
CompositorParent::Create(Transport* aTransport, ProcessId aOtherProcess) CompositorParent::Create(Transport* aTransport, ProcessId aOtherProcess)
{ {
gfxPlatform::InitLayersIPC();
nsRefPtr<CrossProcessCompositorParent> cpcp = nsRefPtr<CrossProcessCompositorParent> cpcp =
new CrossProcessCompositorParent(aTransport, aOtherProcess); new CrossProcessCompositorParent(aTransport, aOtherProcess);
ProcessHandle handle; ProcessHandle handle;
@ -1450,14 +1404,16 @@ CrossProcessCompositorParent::GetCompositionManager(LayerTransactionParent* aLay
void void
CrossProcessCompositorParent::DeferredDestroy() CrossProcessCompositorParent::DeferredDestroy()
{ {
mCompositorThreadHolder = nullptr; CrossProcessCompositorParent* self;
mSelfRef = nullptr; mSelfRef.forget(&self);
nsCOMPtr<nsIRunnable> runnable =
NS_NewNonOwningRunnableMethod(self, &CrossProcessCompositorParent::Release);
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(runnable)));
} }
CrossProcessCompositorParent::~CrossProcessCompositorParent() CrossProcessCompositorParent::~CrossProcessCompositorParent()
{ {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(XRE_GetIOMessageLoop());
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
new DeleteTask<Transport>(mTransport)); new DeleteTask<Transport>(mTransport));
} }

View File

@ -33,7 +33,6 @@
#include "nsAutoPtr.h" // for nsRefPtr #include "nsAutoPtr.h" // for nsRefPtr
#include "nsISupportsImpl.h" #include "nsISupportsImpl.h"
#include "nsSize.h" // for nsIntSize #include "nsSize.h" // for nsIntSize
#include "ThreadSafeRefcountingWithMainThreadDestruction.h"
class CancelableTask; class CancelableTask;
class MessageLoop; class MessageLoop;
@ -64,12 +63,10 @@ private:
uint64_t mLayersId; uint64_t mLayersId;
}; };
class CompositorThreadHolder;
class CompositorParent : public PCompositorParent, class CompositorParent : public PCompositorParent,
public ShadowLayersManager public ShadowLayersManager
{ {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(CompositorParent) NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorParent)
public: public:
CompositorParent(nsIWidget* aWidget, CompositorParent(nsIWidget* aWidget,
@ -169,10 +166,7 @@ public:
static void StartUp(); static void StartUp();
/** /**
* Waits for all [CrossProcess]CompositorParent's to be gone, * Destroys the compositor thread and the global compositor map.
* and destroys the compositor thread and global compositor map.
*
* Does not return until all of that has completed.
*/ */
static void ShutDown(); static void ShutDown();
@ -245,8 +239,6 @@ protected:
// Protected destructor, to discourage deletion outside of Release(): // Protected destructor, to discourage deletion outside of Release():
virtual ~CompositorParent(); virtual ~CompositorParent();
void DeferredDestroy();
virtual PLayerTransactionParent* virtual PLayerTransactionParent*
AllocPLayerTransactionParent(const nsTArray<LayersBackend>& aBackendHints, AllocPLayerTransactionParent(const nsTArray<LayersBackend>& aBackendHints,
const uint64_t& aId, const uint64_t& aId,
@ -267,6 +259,36 @@ protected:
void ForceComposition(); void ForceComposition();
void CancelCurrentCompositeTask(); void CancelCurrentCompositeTask();
/**
* Creates a global map referencing each compositor by ID.
*
* This map is used by the ImageBridge protocol to trigger
* compositions without having to keep references to the
* compositor
*/
static void CreateCompositorMap();
static void DestroyCompositorMap();
/**
* Creates the compositor thread.
*
* All compositors live on the same thread.
* The thread is not lazily created on first access to avoid dealing with
* thread safety. Therefore it's best to create and destroy the thread when
* we know we areb't using it (So creating/destroying along with gfxPlatform
* looks like a good place).
*/
static bool CreateThread();
/**
* Destroys the compositor thread.
*
* It is safe to call this fucntion more than once, although the second call
* will have no effect.
* This function is not thread-safe.
*/
static void DestroyThread();
/** /**
* Add a compositor to the global compositor map. * Add a compositor to the global compositor map.
*/ */
@ -314,8 +336,6 @@ protected:
nsRefPtr<APZCTreeManager> mApzcTreeManager; nsRefPtr<APZCTreeManager> mApzcTreeManager;
nsRefPtr<CompositorThreadHolder> mCompositorThreadHolder;
DISALLOW_EVIL_CONSTRUCTORS(CompositorParent); DISALLOW_EVIL_CONSTRUCTORS(CompositorParent);
}; };

View File

@ -221,6 +221,7 @@ static void ImageBridgeShutdownStep2(ReentrantMonitor *aBarrier, bool *aDone)
sImageBridgeChildSingleton->SendStop(); sImageBridgeChildSingleton->SendStop();
sImageBridgeChildSingleton = nullptr;
*aDone = true; *aDone = true;
aBarrier->NotifyAll(); aBarrier->NotifyAll();
} }
@ -247,14 +248,10 @@ static void ConnectImageBridge(ImageBridgeChild * child, ImageBridgeParent * par
ImageBridgeChild::ImageBridgeChild() ImageBridgeChild::ImageBridgeChild()
: mShuttingDown(false) : mShuttingDown(false)
{ {
MOZ_ASSERT(NS_IsMainThread());
mTxn = new CompositableTransaction(); mTxn = new CompositableTransaction();
} }
ImageBridgeChild::~ImageBridgeChild() ImageBridgeChild::~ImageBridgeChild()
{ {
MOZ_ASSERT(NS_IsMainThread());
delete mTxn; delete mTxn;
} }
@ -550,7 +547,7 @@ PImageBridgeChild*
ImageBridgeChild::StartUpInChildProcess(Transport* aTransport, ImageBridgeChild::StartUpInChildProcess(Transport* aTransport,
ProcessId aOtherProcess) ProcessId aOtherProcess)
{ {
MOZ_ASSERT(NS_IsMainThread()); NS_ASSERTION(NS_IsMainThread(), "Should be on the main Thread!");
gfxPlatform::GetPlatform(); gfxPlatform::GetPlatform();
@ -575,7 +572,7 @@ ImageBridgeChild::StartUpInChildProcess(Transport* aTransport,
void ImageBridgeChild::ShutDown() void ImageBridgeChild::ShutDown()
{ {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread(), "Should be on the main Thread!");
if (ImageBridgeChild::IsCreated()) { if (ImageBridgeChild::IsCreated()) {
MOZ_ASSERT(!sImageBridgeChildSingleton->mShuttingDown); MOZ_ASSERT(!sImageBridgeChildSingleton->mShuttingDown);
@ -603,8 +600,6 @@ void ImageBridgeChild::ShutDown()
} }
} }
sImageBridgeChildSingleton = nullptr;
delete sImageBridgeChildThread; delete sImageBridgeChildThread;
sImageBridgeChildThread = nullptr; sImageBridgeChildThread = nullptr;
} }

View File

@ -17,7 +17,6 @@
#include "mozilla/layers/PImageBridgeChild.h" #include "mozilla/layers/PImageBridgeChild.h"
#include "nsDebug.h" // for NS_RUNTIMEABORT #include "nsDebug.h" // for NS_RUNTIMEABORT
#include "nsRegion.h" // for nsIntRegion #include "nsRegion.h" // for nsIntRegion
class MessageLoop; class MessageLoop;
struct nsIntPoint; struct nsIntPoint;
struct nsIntRect; struct nsIntRect;

View File

@ -44,8 +44,6 @@ using namespace mozilla::gfx;
std::map<base::ProcessId, ImageBridgeParent*> ImageBridgeParent::sImageBridges; std::map<base::ProcessId, ImageBridgeParent*> ImageBridgeParent::sImageBridges;
MessageLoop* ImageBridgeParent::sMainLoop = nullptr;
ImageBridgeParent::ImageBridgeParent(MessageLoop* aLoop, ImageBridgeParent::ImageBridgeParent(MessageLoop* aLoop,
Transport* aTransport, Transport* aTransport,
ProcessId aChildProcessId) ProcessId aChildProcessId)
@ -53,25 +51,18 @@ ImageBridgeParent::ImageBridgeParent(MessageLoop* aLoop,
, mTransport(aTransport) , mTransport(aTransport)
, mChildProcessId(aChildProcessId) , mChildProcessId(aChildProcessId)
{ {
MOZ_ASSERT(NS_IsMainThread());
// creates the map only if it has not been created already, so it is safe // creates the map only if it has not been created already, so it is safe
// with several bridges // with several bridges
CompositableMap::Create(); CompositableMap::Create();
sImageBridges[aChildProcessId] = this; sImageBridges[aChildProcessId] = this;
sMainLoop = MessageLoop::current();
} }
ImageBridgeParent::~ImageBridgeParent() ImageBridgeParent::~ImageBridgeParent()
{ {
MOZ_ASSERT(NS_IsMainThread());
if (mTransport) { if (mTransport) {
MOZ_ASSERT(XRE_GetIOMessageLoop());
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
new DeleteTask<Transport>(mTransport)); new DeleteTask<Transport>(mTransport));
} }
sImageBridges.erase(mChildProcessId); sImageBridges.erase(mChildProcessId);
} }
@ -274,11 +265,23 @@ MessageLoop * ImageBridgeParent::GetMessageLoop() const {
return mMessageLoop; return mMessageLoop;
} }
static void class ReleaseRunnable : public nsRunnable
DeferredReleaseImageBridgeParentOnMainThread(ImageBridgeParent* aDyingImageBridgeParent)
{ {
aDyingImageBridgeParent->Release(); public:
} ReleaseRunnable(ImageBridgeParent* aRef)
: mRef(aRef)
{
}
NS_IMETHOD Run()
{
mRef->Release();
return NS_OK;
}
private:
ImageBridgeParent* mRef;
};
void void
ImageBridgeParent::DeferredDestroy() ImageBridgeParent::DeferredDestroy()
@ -286,9 +289,8 @@ ImageBridgeParent::DeferredDestroy()
ImageBridgeParent* self; ImageBridgeParent* self;
mSelfRef.forget(&self); mSelfRef.forget(&self);
sMainLoop->PostTask( nsCOMPtr<nsIRunnable> runnable = new ReleaseRunnable(self);
FROM_HERE, MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(runnable)));
NewRunnableFunction(&DeferredReleaseImageBridgeParentOnMainThread, this));
} }
ImageBridgeParent* ImageBridgeParent*

View File

@ -151,8 +151,6 @@ private:
* Map of all living ImageBridgeParent instances * Map of all living ImageBridgeParent instances
*/ */
static std::map<base::ProcessId, ImageBridgeParent*> sImageBridges; static std::map<base::ProcessId, ImageBridgeParent*> sImageBridges;
static MessageLoop* sMainLoop;
}; };
} // layers } // layers

View File

@ -1,83 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef THREADSAFEREFCOUNTINGWITHMAINTHREADDESTRUCTION_H_
#define THREADSAFEREFCOUNTINGWITHMAINTHREADDESTRUCTION_H_
#include "MainThreadUtils.h"
#include "base/message_loop.h"
#include "base/task.h"
namespace mozilla {
namespace layers {
inline MessageLoop* GetMainLoopAssertingMainThread()
{
MOZ_ASSERT(NS_IsMainThread());
return MessageLoop::current();
}
inline MessageLoop* GetMainLoop()
{
static MessageLoop* sMainLoop = GetMainLoopAssertingMainThread();
return sMainLoop;
}
struct HelperForMainThreadDestruction
{
HelperForMainThreadDestruction()
{
MOZ_ASSERT(NS_IsMainThread());
GetMainLoop();
}
~HelperForMainThreadDestruction()
{
MOZ_ASSERT(NS_IsMainThread());
}
};
} // namespace layers
} // namespace mozilla
#define NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(_class) \
public: \
NS_METHOD_(MozExternalRefCountType) AddRef(void) { \
MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(_class) \
MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt"); \
nsrefcnt count = ++mRefCnt; \
NS_LOG_ADDREF(this, count, #_class, sizeof(*this)); \
return (nsrefcnt) count; \
} \
static void DestroyToBeCalledOnMainThread(_class* ptr) { \
MOZ_ASSERT(NS_IsMainThread()); \
NS_LOG_RELEASE(ptr, 0, #_class); \
delete ptr; \
} \
NS_METHOD_(MozExternalRefCountType) Release(void) { \
MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); \
nsrefcnt count = --mRefCnt; \
if (count == 0) { \
if (NS_IsMainThread()) { \
NS_LOG_RELEASE(this, 0, #_class); \
delete this; \
} else { \
/* no NS_LOG_RELEASE here, will be in the runnable */ \
MessageLoop *l = ::mozilla::layers::GetMainLoop(); \
l->PostTask(FROM_HERE, \
NewRunnableFunction(&DestroyToBeCalledOnMainThread, \
this)); \
} \
} else { \
NS_LOG_RELEASE(this, count, #_class); \
} \
return count; \
} \
protected: \
::mozilla::ThreadSafeAutoRefCnt mRefCnt; \
private: \
::mozilla::layers::HelperForMainThreadDestruction mHelperForMainThreadDestruction; \
public:
#endif

View File

@ -27,7 +27,6 @@ EXPORTS += [
'ipc/CompositorChild.h', 'ipc/CompositorChild.h',
'ipc/CompositorParent.h', 'ipc/CompositorParent.h',
'ipc/ShadowLayersManager.h', 'ipc/ShadowLayersManager.h',
'ipc/ThreadSafeRefcountingWithMainThreadDestruction.h',
'Layers.h', 'Layers.h',
'LayerScope.h', 'LayerScope.h',
'LayersLogging.h', 'LayersLogging.h',

View File

@ -19,14 +19,11 @@ namespace ipc {
IToplevelProtocol::~IToplevelProtocol() IToplevelProtocol::~IToplevelProtocol()
{ {
MOZ_ASSERT(NS_IsMainThread());
mOpenActors.clear(); mOpenActors.clear();
} }
void IToplevelProtocol::AddOpenedActor(IToplevelProtocol* aActor) void IToplevelProtocol::AddOpenedActor(IToplevelProtocol* aActor)
{ {
MOZ_ASSERT(NS_IsMainThread());
#ifdef DEBUG #ifdef DEBUG
for (const IToplevelProtocol* actor = mOpenActors.getFirst(); for (const IToplevelProtocol* actor = mOpenActors.getFirst();
actor; actor;

View File

@ -21,7 +21,6 @@
#include "mozilla/ipc/Transport.h" #include "mozilla/ipc/Transport.h"
#include "mozilla/ipc/MessageLink.h" #include "mozilla/ipc/MessageLink.h"
#include "mozilla/LinkedList.h" #include "mozilla/LinkedList.h"
#include "MainThreadUtils.h"
#if defined(ANDROID) && defined(DEBUG) #if defined(ANDROID) && defined(DEBUG)
#include <android/log.h> #include <android/log.h>
@ -188,7 +187,6 @@ protected:
: mProtocolId(aProtoId) : mProtocolId(aProtoId)
, mTrans(nullptr) , mTrans(nullptr)
{ {
MOZ_ASSERT(NS_IsMainThread());
} }
~IToplevelProtocol(); ~IToplevelProtocol();
@ -214,12 +212,10 @@ public:
*/ */
IToplevelProtocol* GetFirstOpenedActors() IToplevelProtocol* GetFirstOpenedActors()
{ {
MOZ_ASSERT(NS_IsMainThread());
return mOpenActors.getFirst(); return mOpenActors.getFirst();
} }
const IToplevelProtocol* GetFirstOpenedActors() const const IToplevelProtocol* GetFirstOpenedActors() const
{ {
MOZ_ASSERT(NS_IsMainThread());
return mOpenActors.getFirst(); return mOpenActors.getFirst();
} }

View File

@ -18,7 +18,6 @@
#include "nsStackWalkPrivate.h" #include "nsStackWalkPrivate.h"
#include "nsStackWalk.h" #include "nsStackWalk.h"
#include "nsString.h" #include "nsString.h"
#include "nsThreadUtils.h"
#include "nsXULAppAPI.h" #include "nsXULAppAPI.h"
#ifdef XP_WIN #ifdef XP_WIN
@ -920,8 +919,6 @@ nsTraceRefcnt::DemangleSymbol(const char* aSymbol,
EXPORT_XPCOM_API(void) EXPORT_XPCOM_API(void)
NS_LogInit() NS_LogInit()
{ {
NS_SetMainThread();
// FIXME: This is called multiple times, we should probably not allow that. // FIXME: This is called multiple times, we should probably not allow that.
#ifdef STACKWALKING_AVAILABLE #ifdef STACKWALKING_AVAILABLE
StackWalkInitCriticalAddress(); StackWalkInitCriticalAddress();

View File

@ -811,17 +811,17 @@ ShutdownXPCOM(nsIServiceManager* servMgr)
} }
} }
// This must happen after the shutdown of media and widgets, which
// are triggered by the NS_XPCOM_SHUTDOWN_OBSERVER_ID notification.
NS_ProcessPendingEvents(thread); NS_ProcessPendingEvents(thread);
gfxPlatform::ShutdownLayersIPC();
mozilla::scache::StartupCache::DeleteSingleton(); mozilla::scache::StartupCache::DeleteSingleton();
if (observerService) if (observerService)
(void) observerService-> (void) observerService->
NotifyObservers(nullptr, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID, NotifyObservers(nullptr, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID,
nullptr); nullptr);
// This must happen after the shutdown of media and widgets, which
// are triggered by the NS_XPCOM_SHUTDOWN_OBSERVER_ID notification.
gfxPlatform::ShutdownLayersIPC();
gXPCOMThreadsShutDown = true; gXPCOMThreadsShutDown = true;
NS_ProcessPendingEvents(thread); NS_ProcessPendingEvents(thread);

View File

@ -28,8 +28,21 @@ extern NS_COM_GLUE NS_METHOD NS_GetMainThread(nsIThread** aResult);
extern NS_COM_GLUE nsIThread* NS_GetCurrentThread(); extern NS_COM_GLUE nsIThread* NS_GetCurrentThread();
#endif #endif
#ifdef MOZILLA_INTERNAL_API #if defined(MOZILLA_INTERNAL_API) && defined(XP_WIN)
bool NS_IsMainThread(); bool NS_IsMainThread();
#elif defined(MOZILLA_INTERNAL_API) && defined(NS_TLS)
// This is defined in nsThreadManager.cpp and initialized to `Main` for the
// main thread by nsThreadManager::Init.
extern NS_TLS mozilla::threads::ID gTLSThreadID;
#ifdef MOZ_ASAN
// Temporary workaround, see bug 895845
MOZ_ASAN_BLACKLIST bool NS_IsMainThread();
#else
inline bool NS_IsMainThread()
{
return gTLSThreadID == mozilla::threads::Main;
}
#endif
#else #else
/** /**
* Test to see if the current thread is the main thread. * Test to see if the current thread is the main thread.

View File

@ -125,7 +125,34 @@ NS_GetMainThread(nsIThread** aResult)
#endif #endif
} }
#ifndef MOZILLA_INTERNAL_API #if defined(MOZILLA_INTERNAL_API) && defined(XP_WIN)
extern DWORD gTLSThreadIDIndex;
bool
NS_IsMainThread()
{
return TlsGetValue(gTLSThreadIDIndex) == (void*)mozilla::threads::Main;
}
#elif defined(MOZILLA_INTERNAL_API) && defined(NS_TLS)
#ifdef MOZ_ASAN
// Temporary workaround, see bug 895845
bool
NS_IsMainThread()
{
return gTLSThreadID == mozilla::threads::Main;
}
#else
// NS_IsMainThread() is defined inline in MainThreadUtils.h
#endif
#else
#ifdef MOZILLA_INTERNAL_API
bool
NS_IsMainThread()
{
bool result = false;
nsThreadManager::get()->nsThreadManager::GetIsMainThread(&result);
return bool(result);
}
#else
bool bool
NS_IsMainThread() NS_IsMainThread()
{ {
@ -138,6 +165,7 @@ NS_IsMainThread()
return bool(result); return bool(result);
} }
#endif #endif
#endif
NS_METHOD NS_METHOD
NS_DispatchToCurrentThread(nsIRunnable* aEvent) NS_DispatchToCurrentThread(nsIRunnable* aEvent)
@ -328,9 +356,7 @@ nsThreadPoolNaming::SetThreadPoolName(const nsACString& aPoolName,
NS_SetThreadName(aThread, name); NS_SetThreadName(aThread, name);
} else { } else {
// Set on the current thread // Set on the current thread
#ifndef XPCOM_GLUE_AVOID_NSPR
PR_SetCurrentThreadName(name.BeginReading()); PR_SetCurrentThreadName(name.BeginReading());
#endif
} }
} }

View File

@ -565,7 +565,6 @@ private:
#endif #endif
}; };
void
NS_SetMainThread();
#endif // nsThreadUtils_h__ #endif // nsThreadUtils_h__

View File

@ -10,7 +10,6 @@
#include "nsIClassInfoImpl.h" #include "nsIClassInfoImpl.h"
#include "nsTArray.h" #include "nsTArray.h"
#include "nsAutoPtr.h" #include "nsAutoPtr.h"
#include "mozilla/ThreadLocal.h"
#ifdef MOZ_CANARY #ifdef MOZ_CANARY
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
@ -25,26 +24,6 @@ DWORD gTLSThreadIDIndex = TlsAlloc();
NS_TLS mozilla::threads::ID gTLSThreadID = mozilla::threads::Generic; NS_TLS mozilla::threads::ID gTLSThreadID = mozilla::threads::Generic;
#endif #endif
static mozilla::ThreadLocal<bool> sTLSIsMainThread;
bool
NS_IsMainThread()
{
return sTLSIsMainThread.get();
}
void
NS_SetMainThread()
{
if (!sTLSIsMainThread.initialized()) {
if (!sTLSIsMainThread.init()) {
MOZ_CRASH();
}
sTLSIsMainThread.set(true);
}
MOZ_ASSERT(NS_IsMainThread());
}
typedef nsTArray<nsRefPtr<nsThread>> nsThreadArray; typedef nsTArray<nsRefPtr<nsThread>> nsThreadArray;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------