mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
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:
parent
3f9e56aab8
commit
6d9424856d
@ -17,7 +17,6 @@
|
||||
#include "nsCOMPtr.h" // for nsCOMPtr
|
||||
#include "nsHashKeys.h" // for nsUint64HashKey
|
||||
#include "nsISupportsImpl.h" // for NS_INLINE_DECL_REFCOUNTING
|
||||
#include "ThreadSafeRefcountingWithMainThreadDestruction.h"
|
||||
|
||||
class nsIObserver;
|
||||
|
||||
@ -30,8 +29,7 @@ struct FrameMetrics;
|
||||
|
||||
class CompositorChild MOZ_FINAL : public PCompositorChild
|
||||
{
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(CompositorChild)
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(CompositorChild)
|
||||
public:
|
||||
CompositorChild(ClientLayerManager *aLayerManager);
|
||||
|
||||
|
@ -53,7 +53,6 @@
|
||||
#include "mozilla/unused.h"
|
||||
#include "mozilla/Hal.h"
|
||||
#include "mozilla/HalTypes.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
@ -74,78 +73,64 @@ CompositorParent::LayerTreeState::LayerTreeState()
|
||||
typedef map<uint64_t, CompositorParent::LayerTreeState> LayerTreeMap;
|
||||
static LayerTreeMap sIndirectLayerTrees;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
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;
|
||||
}
|
||||
// FIXME/bug 774386: we're assuming that there's only one
|
||||
// CompositorParent, but that's not always true. This assumption only
|
||||
// affects CrossProcessCompositorParent below.
|
||||
static Thread* sCompositorThread = nullptr;
|
||||
// manual reference count of the compositor thread.
|
||||
static int sCompositorThreadRefCount = 0;
|
||||
static MessageLoop* sMainLoop = nullptr;
|
||||
|
||||
// See ImageBridgeChild.cpp
|
||||
void ReleaseImageBridgeParentSingleton();
|
||||
|
||||
class CompositorThreadHolder MOZ_FINAL
|
||||
static void DeferredDeleteCompositorParent(CompositorParent* aNowReadyToDie)
|
||||
{
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(CompositorThreadHolder)
|
||||
aNowReadyToDie->Release();
|
||||
}
|
||||
|
||||
public:
|
||||
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()
|
||||
static void DeleteCompositorThread()
|
||||
{
|
||||
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;
|
||||
/* 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). */
|
||||
options.permanent_hang_timeout = 8192; // milliseconds
|
||||
|
||||
if (!compositorThread->StartWithOptions(options)) {
|
||||
delete compositorThread;
|
||||
return nullptr;
|
||||
if (!sCompositorThread->StartWithOptions(options)) {
|
||||
delete sCompositorThread;
|
||||
sCompositorThread = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
CreateCompositorMap();
|
||||
|
||||
return compositorThread;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
CompositorThreadHolder::DestroyCompositorThread(Thread* aCompositorThread)
|
||||
void CompositorParent::DestroyThread()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
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);
|
||||
}
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on the main Thread!");
|
||||
ReleaseCompositorThread();
|
||||
}
|
||||
|
||||
MessageLoop* CompositorParent::CompositorLoop()
|
||||
{
|
||||
return CompositorThread() ? CompositorThread()->message_loop() : nullptr;
|
||||
return sCompositorThread ? sCompositorThread->message_loop() : nullptr;
|
||||
}
|
||||
|
||||
CompositorParent::CompositorParent(nsIWidget* aWidget,
|
||||
@ -229,11 +175,9 @@ CompositorParent::CompositorParent(nsIWidget* aWidget,
|
||||
, mResumeCompositionMonitor("ResumeCompositionMonitor")
|
||||
, mOverrideComposeReadiness(false)
|
||||
, mForceCompositionTask(nullptr)
|
||||
, mCompositorThreadHolder(sCompositorThreadHolder)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(CompositorThread(),
|
||||
"The compositor thread must be Initialized before instanciating a CompositorParent.");
|
||||
MOZ_ASSERT(sCompositorThread != nullptr,
|
||||
"The compositor thread must be Initialized before instanciating a CmpositorParent.");
|
||||
MOZ_COUNT_CTOR(CompositorParent);
|
||||
mCompositorID = 0;
|
||||
// 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;
|
||||
|
||||
mApzcTreeManager = new APZCTreeManager();
|
||||
++sCompositorThreadRefCount;
|
||||
}
|
||||
|
||||
bool
|
||||
CompositorParent::IsInCompositorThread()
|
||||
{
|
||||
return CompositorThread() && CompositorThread()->thread_id() == PlatformThread::CurrentId();
|
||||
return sCompositorThread && sCompositorThread->thread_id() == PlatformThread::CurrentId();
|
||||
}
|
||||
|
||||
uint64_t
|
||||
@ -264,8 +209,9 @@ CompositorParent::RootLayerTreeId()
|
||||
|
||||
CompositorParent::~CompositorParent()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_COUNT_DTOR(CompositorParent);
|
||||
|
||||
ReleaseCompositorThread();
|
||||
}
|
||||
|
||||
void
|
||||
@ -318,13 +264,6 @@ CompositorParent::RecvWillStop()
|
||||
return true;
|
||||
}
|
||||
|
||||
void CompositorParent::DeferredDestroy()
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
mCompositorThreadHolder = nullptr;
|
||||
Release();
|
||||
}
|
||||
|
||||
bool
|
||||
CompositorParent::RecvStop()
|
||||
{
|
||||
@ -334,9 +273,10 @@ CompositorParent::RecvStop()
|
||||
// this thread.
|
||||
// We must keep the compositor parent alive untill the code handling message
|
||||
// reception is finished on this thread.
|
||||
this->AddRef(); // Corresponds to DeferredDestroy's Release
|
||||
MessageLoop::current()->PostTask(FROM_HERE,
|
||||
NewRunnableMethod(this,&CompositorParent::DeferredDestroy));
|
||||
this->AddRef(); // Corresponds to DeferredDeleteCompositorParent's Release
|
||||
CompositorLoop()->PostTask(FROM_HERE,
|
||||
NewRunnableFunction(&DeferredDeleteCompositorParent,
|
||||
this));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -981,6 +921,27 @@ CompositorParent::DeallocPLayerTransactionParent(PLayerTransactionParent* actor)
|
||||
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)
|
||||
{
|
||||
CompositorMap::iterator it = sCompositorMap->find(id);
|
||||
@ -1116,15 +1077,12 @@ class CrossProcessCompositorParent MOZ_FINAL : public PCompositorParent,
|
||||
{
|
||||
friend class CompositorParent;
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(CrossProcessCompositorParent)
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CrossProcessCompositorParent)
|
||||
public:
|
||||
CrossProcessCompositorParent(Transport* aTransport, ProcessId aOtherProcess)
|
||||
: mTransport(aTransport)
|
||||
, mChildProcessId(aOtherProcess)
|
||||
, mCompositorThreadHolder(sCompositorThreadHolder)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
{}
|
||||
|
||||
// IToplevelProtocol::CloneToplevel()
|
||||
virtual IToplevelProtocol*
|
||||
@ -1187,8 +1145,6 @@ private:
|
||||
Transport* mTransport;
|
||||
// Child side's process Id.
|
||||
base::ProcessId mChildProcessId;
|
||||
|
||||
nsRefPtr<CompositorThreadHolder> mCompositorThreadHolder;
|
||||
};
|
||||
|
||||
void
|
||||
@ -1220,8 +1176,6 @@ OpenCompositor(CrossProcessCompositorParent* aCompositor,
|
||||
/*static*/ PCompositorParent*
|
||||
CompositorParent::Create(Transport* aTransport, ProcessId aOtherProcess)
|
||||
{
|
||||
gfxPlatform::InitLayersIPC();
|
||||
|
||||
nsRefPtr<CrossProcessCompositorParent> cpcp =
|
||||
new CrossProcessCompositorParent(aTransport, aOtherProcess);
|
||||
ProcessHandle handle;
|
||||
@ -1450,14 +1404,16 @@ CrossProcessCompositorParent::GetCompositionManager(LayerTransactionParent* aLay
|
||||
void
|
||||
CrossProcessCompositorParent::DeferredDestroy()
|
||||
{
|
||||
mCompositorThreadHolder = nullptr;
|
||||
mSelfRef = nullptr;
|
||||
CrossProcessCompositorParent* self;
|
||||
mSelfRef.forget(&self);
|
||||
|
||||
nsCOMPtr<nsIRunnable> runnable =
|
||||
NS_NewNonOwningRunnableMethod(self, &CrossProcessCompositorParent::Release);
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(runnable)));
|
||||
}
|
||||
|
||||
CrossProcessCompositorParent::~CrossProcessCompositorParent()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(XRE_GetIOMessageLoop());
|
||||
XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
|
||||
new DeleteTask<Transport>(mTransport));
|
||||
}
|
||||
|
@ -33,7 +33,6 @@
|
||||
#include "nsAutoPtr.h" // for nsRefPtr
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsSize.h" // for nsIntSize
|
||||
#include "ThreadSafeRefcountingWithMainThreadDestruction.h"
|
||||
|
||||
class CancelableTask;
|
||||
class MessageLoop;
|
||||
@ -64,12 +63,10 @@ private:
|
||||
uint64_t mLayersId;
|
||||
};
|
||||
|
||||
class CompositorThreadHolder;
|
||||
|
||||
class CompositorParent : public PCompositorParent,
|
||||
public ShadowLayersManager
|
||||
{
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(CompositorParent)
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorParent)
|
||||
|
||||
public:
|
||||
CompositorParent(nsIWidget* aWidget,
|
||||
@ -169,10 +166,7 @@ public:
|
||||
static void StartUp();
|
||||
|
||||
/**
|
||||
* Waits for all [CrossProcess]CompositorParent's to be gone,
|
||||
* and destroys the compositor thread and global compositor map.
|
||||
*
|
||||
* Does not return until all of that has completed.
|
||||
* Destroys the compositor thread and the global compositor map.
|
||||
*/
|
||||
static void ShutDown();
|
||||
|
||||
@ -245,8 +239,6 @@ protected:
|
||||
// Protected destructor, to discourage deletion outside of Release():
|
||||
virtual ~CompositorParent();
|
||||
|
||||
void DeferredDestroy();
|
||||
|
||||
virtual PLayerTransactionParent*
|
||||
AllocPLayerTransactionParent(const nsTArray<LayersBackend>& aBackendHints,
|
||||
const uint64_t& aId,
|
||||
@ -267,6 +259,36 @@ protected:
|
||||
void ForceComposition();
|
||||
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.
|
||||
*/
|
||||
@ -314,8 +336,6 @@ protected:
|
||||
|
||||
nsRefPtr<APZCTreeManager> mApzcTreeManager;
|
||||
|
||||
nsRefPtr<CompositorThreadHolder> mCompositorThreadHolder;
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(CompositorParent);
|
||||
};
|
||||
|
||||
|
@ -221,6 +221,7 @@ static void ImageBridgeShutdownStep2(ReentrantMonitor *aBarrier, bool *aDone)
|
||||
|
||||
sImageBridgeChildSingleton->SendStop();
|
||||
|
||||
sImageBridgeChildSingleton = nullptr;
|
||||
*aDone = true;
|
||||
aBarrier->NotifyAll();
|
||||
}
|
||||
@ -247,14 +248,10 @@ static void ConnectImageBridge(ImageBridgeChild * child, ImageBridgeParent * par
|
||||
ImageBridgeChild::ImageBridgeChild()
|
||||
: mShuttingDown(false)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
mTxn = new CompositableTransaction();
|
||||
}
|
||||
ImageBridgeChild::~ImageBridgeChild()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
delete mTxn;
|
||||
}
|
||||
|
||||
@ -550,7 +547,7 @@ PImageBridgeChild*
|
||||
ImageBridgeChild::StartUpInChildProcess(Transport* aTransport,
|
||||
ProcessId aOtherProcess)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on the main Thread!");
|
||||
|
||||
gfxPlatform::GetPlatform();
|
||||
|
||||
@ -575,7 +572,7 @@ ImageBridgeChild::StartUpInChildProcess(Transport* aTransport,
|
||||
|
||||
void ImageBridgeChild::ShutDown()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Should be on the main Thread!");
|
||||
if (ImageBridgeChild::IsCreated()) {
|
||||
MOZ_ASSERT(!sImageBridgeChildSingleton->mShuttingDown);
|
||||
|
||||
@ -603,8 +600,6 @@ void ImageBridgeChild::ShutDown()
|
||||
}
|
||||
}
|
||||
|
||||
sImageBridgeChildSingleton = nullptr;
|
||||
|
||||
delete sImageBridgeChildThread;
|
||||
sImageBridgeChildThread = nullptr;
|
||||
}
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include "mozilla/layers/PImageBridgeChild.h"
|
||||
#include "nsDebug.h" // for NS_RUNTIMEABORT
|
||||
#include "nsRegion.h" // for nsIntRegion
|
||||
|
||||
class MessageLoop;
|
||||
struct nsIntPoint;
|
||||
struct nsIntRect;
|
||||
|
@ -44,8 +44,6 @@ using namespace mozilla::gfx;
|
||||
|
||||
std::map<base::ProcessId, ImageBridgeParent*> ImageBridgeParent::sImageBridges;
|
||||
|
||||
MessageLoop* ImageBridgeParent::sMainLoop = nullptr;
|
||||
|
||||
ImageBridgeParent::ImageBridgeParent(MessageLoop* aLoop,
|
||||
Transport* aTransport,
|
||||
ProcessId aChildProcessId)
|
||||
@ -53,25 +51,18 @@ ImageBridgeParent::ImageBridgeParent(MessageLoop* aLoop,
|
||||
, mTransport(aTransport)
|
||||
, mChildProcessId(aChildProcessId)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// creates the map only if it has not been created already, so it is safe
|
||||
// with several bridges
|
||||
CompositableMap::Create();
|
||||
sImageBridges[aChildProcessId] = this;
|
||||
sMainLoop = MessageLoop::current();
|
||||
}
|
||||
|
||||
ImageBridgeParent::~ImageBridgeParent()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (mTransport) {
|
||||
MOZ_ASSERT(XRE_GetIOMessageLoop());
|
||||
XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
|
||||
new DeleteTask<Transport>(mTransport));
|
||||
}
|
||||
|
||||
sImageBridges.erase(mChildProcessId);
|
||||
}
|
||||
|
||||
@ -274,11 +265,23 @@ MessageLoop * ImageBridgeParent::GetMessageLoop() const {
|
||||
return mMessageLoop;
|
||||
}
|
||||
|
||||
static void
|
||||
DeferredReleaseImageBridgeParentOnMainThread(ImageBridgeParent* aDyingImageBridgeParent)
|
||||
class ReleaseRunnable : public nsRunnable
|
||||
{
|
||||
aDyingImageBridgeParent->Release();
|
||||
}
|
||||
public:
|
||||
ReleaseRunnable(ImageBridgeParent* aRef)
|
||||
: mRef(aRef)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
mRef->Release();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
ImageBridgeParent* mRef;
|
||||
};
|
||||
|
||||
void
|
||||
ImageBridgeParent::DeferredDestroy()
|
||||
@ -286,9 +289,8 @@ ImageBridgeParent::DeferredDestroy()
|
||||
ImageBridgeParent* self;
|
||||
mSelfRef.forget(&self);
|
||||
|
||||
sMainLoop->PostTask(
|
||||
FROM_HERE,
|
||||
NewRunnableFunction(&DeferredReleaseImageBridgeParentOnMainThread, this));
|
||||
nsCOMPtr<nsIRunnable> runnable = new ReleaseRunnable(self);
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(runnable)));
|
||||
}
|
||||
|
||||
ImageBridgeParent*
|
||||
|
@ -151,8 +151,6 @@ private:
|
||||
* Map of all living ImageBridgeParent instances
|
||||
*/
|
||||
static std::map<base::ProcessId, ImageBridgeParent*> sImageBridges;
|
||||
|
||||
static MessageLoop* sMainLoop;
|
||||
};
|
||||
|
||||
} // layers
|
||||
|
@ -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
|
@ -27,7 +27,6 @@ EXPORTS += [
|
||||
'ipc/CompositorChild.h',
|
||||
'ipc/CompositorParent.h',
|
||||
'ipc/ShadowLayersManager.h',
|
||||
'ipc/ThreadSafeRefcountingWithMainThreadDestruction.h',
|
||||
'Layers.h',
|
||||
'LayerScope.h',
|
||||
'LayersLogging.h',
|
||||
|
@ -19,14 +19,11 @@ namespace ipc {
|
||||
|
||||
IToplevelProtocol::~IToplevelProtocol()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mOpenActors.clear();
|
||||
}
|
||||
|
||||
void IToplevelProtocol::AddOpenedActor(IToplevelProtocol* aActor)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
#ifdef DEBUG
|
||||
for (const IToplevelProtocol* actor = mOpenActors.getFirst();
|
||||
actor;
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include "mozilla/ipc/Transport.h"
|
||||
#include "mozilla/ipc/MessageLink.h"
|
||||
#include "mozilla/LinkedList.h"
|
||||
#include "MainThreadUtils.h"
|
||||
|
||||
#if defined(ANDROID) && defined(DEBUG)
|
||||
#include <android/log.h>
|
||||
@ -188,7 +187,6 @@ protected:
|
||||
: mProtocolId(aProtoId)
|
||||
, mTrans(nullptr)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
~IToplevelProtocol();
|
||||
@ -214,12 +212,10 @@ public:
|
||||
*/
|
||||
IToplevelProtocol* GetFirstOpenedActors()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
return mOpenActors.getFirst();
|
||||
}
|
||||
const IToplevelProtocol* GetFirstOpenedActors() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
return mOpenActors.getFirst();
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include "nsStackWalkPrivate.h"
|
||||
#include "nsStackWalk.h"
|
||||
#include "nsString.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#include "nsXULAppAPI.h"
|
||||
#ifdef XP_WIN
|
||||
@ -920,8 +919,6 @@ nsTraceRefcnt::DemangleSymbol(const char* aSymbol,
|
||||
EXPORT_XPCOM_API(void)
|
||||
NS_LogInit()
|
||||
{
|
||||
NS_SetMainThread();
|
||||
|
||||
// FIXME: This is called multiple times, we should probably not allow that.
|
||||
#ifdef STACKWALKING_AVAILABLE
|
||||
StackWalkInitCriticalAddress();
|
||||
|
@ -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);
|
||||
gfxPlatform::ShutdownLayersIPC();
|
||||
|
||||
mozilla::scache::StartupCache::DeleteSingleton();
|
||||
if (observerService)
|
||||
(void) observerService->
|
||||
NotifyObservers(nullptr, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID,
|
||||
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;
|
||||
NS_ProcessPendingEvents(thread);
|
||||
|
||||
|
@ -28,8 +28,21 @@ extern NS_COM_GLUE NS_METHOD NS_GetMainThread(nsIThread** aResult);
|
||||
extern NS_COM_GLUE nsIThread* NS_GetCurrentThread();
|
||||
#endif
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
#if defined(MOZILLA_INTERNAL_API) && defined(XP_WIN)
|
||||
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
|
||||
/**
|
||||
* Test to see if the current thread is the main thread.
|
||||
|
@ -125,7 +125,34 @@ NS_GetMainThread(nsIThread** aResult)
|
||||
#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
|
||||
NS_IsMainThread()
|
||||
{
|
||||
@ -138,6 +165,7 @@ NS_IsMainThread()
|
||||
return bool(result);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
NS_METHOD
|
||||
NS_DispatchToCurrentThread(nsIRunnable* aEvent)
|
||||
@ -328,9 +356,7 @@ nsThreadPoolNaming::SetThreadPoolName(const nsACString& aPoolName,
|
||||
NS_SetThreadName(aThread, name);
|
||||
} else {
|
||||
// Set on the current thread
|
||||
#ifndef XPCOM_GLUE_AVOID_NSPR
|
||||
PR_SetCurrentThreadName(name.BeginReading());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -565,7 +565,6 @@ private:
|
||||
#endif
|
||||
};
|
||||
|
||||
void
|
||||
NS_SetMainThread();
|
||||
|
||||
|
||||
#endif // nsThreadUtils_h__
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include "nsIClassInfoImpl.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "mozilla/ThreadLocal.h"
|
||||
#ifdef MOZ_CANARY
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
@ -25,26 +24,6 @@ DWORD gTLSThreadIDIndex = TlsAlloc();
|
||||
NS_TLS mozilla::threads::ID gTLSThreadID = mozilla::threads::Generic;
|
||||
#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;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user