From 6d9424856daf9822eb9f2f5dcf74ad83a48bfc7b Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Thu, 3 Jul 2014 20:37:05 -0400 Subject: [PATCH] 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) --- gfx/layers/ipc/CompositorChild.h | 4 +- gfx/layers/ipc/CompositorParent.cpp | 238 +++++++----------- gfx/layers/ipc/CompositorParent.h | 44 +++- gfx/layers/ipc/ImageBridgeChild.cpp | 11 +- gfx/layers/ipc/ImageBridgeChild.h | 1 - gfx/layers/ipc/ImageBridgeParent.cpp | 34 +-- gfx/layers/ipc/ImageBridgeParent.h | 2 - ...SafeRefcountingWithMainThreadDestruction.h | 83 ------ gfx/layers/moz.build | 1 - ipc/glue/ProtocolUtils.cpp | 3 - ipc/glue/ProtocolUtils.h | 4 - xpcom/base/nsTraceRefcnt.cpp | 3 - xpcom/build/nsXPComInit.cpp | 8 +- xpcom/glue/MainThreadUtils.h | 15 +- xpcom/glue/nsThreadUtils.cpp | 32 ++- xpcom/glue/nsThreadUtils.h | 3 +- xpcom/threads/nsThreadManager.cpp | 21 -- 17 files changed, 199 insertions(+), 308 deletions(-) delete mode 100644 gfx/layers/ipc/ThreadSafeRefcountingWithMainThreadDestruction.h diff --git a/gfx/layers/ipc/CompositorChild.h b/gfx/layers/ipc/CompositorChild.h index 50af4d4f071e..f59e21a316c1 100644 --- a/gfx/layers/ipc/CompositorChild.h +++ b/gfx/layers/ipc/CompositorChild.h @@ -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); diff --git a/gfx/layers/ipc/CompositorParent.cpp b/gfx/layers/ipc/CompositorParent.cpp index eaf960d03aff..11b8435c4065 100644 --- a/gfx/layers/ipc/CompositorParent.cpp +++ b/gfx/layers/ipc/CompositorParent.cpp @@ -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 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 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 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 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 mCompositorThreadHolder; }; void @@ -1220,8 +1176,6 @@ OpenCompositor(CrossProcessCompositorParent* aCompositor, /*static*/ PCompositorParent* CompositorParent::Create(Transport* aTransport, ProcessId aOtherProcess) { - gfxPlatform::InitLayersIPC(); - nsRefPtr 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 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(mTransport)); } diff --git a/gfx/layers/ipc/CompositorParent.h b/gfx/layers/ipc/CompositorParent.h index 728cc2423875..de41299ef887 100644 --- a/gfx/layers/ipc/CompositorParent.h +++ b/gfx/layers/ipc/CompositorParent.h @@ -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& 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 mApzcTreeManager; - nsRefPtr mCompositorThreadHolder; - DISALLOW_EVIL_CONSTRUCTORS(CompositorParent); }; diff --git a/gfx/layers/ipc/ImageBridgeChild.cpp b/gfx/layers/ipc/ImageBridgeChild.cpp index f8cbe127d116..c8abcff401ad 100644 --- a/gfx/layers/ipc/ImageBridgeChild.cpp +++ b/gfx/layers/ipc/ImageBridgeChild.cpp @@ -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; } diff --git a/gfx/layers/ipc/ImageBridgeChild.h b/gfx/layers/ipc/ImageBridgeChild.h index 214bd19dfa0d..124c9f773c4f 100644 --- a/gfx/layers/ipc/ImageBridgeChild.h +++ b/gfx/layers/ipc/ImageBridgeChild.h @@ -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; diff --git a/gfx/layers/ipc/ImageBridgeParent.cpp b/gfx/layers/ipc/ImageBridgeParent.cpp index 6228b99d2471..40920d559c23 100644 --- a/gfx/layers/ipc/ImageBridgeParent.cpp +++ b/gfx/layers/ipc/ImageBridgeParent.cpp @@ -44,8 +44,6 @@ using namespace mozilla::gfx; std::map 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(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 runnable = new ReleaseRunnable(self); + MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(runnable))); } ImageBridgeParent* diff --git a/gfx/layers/ipc/ImageBridgeParent.h b/gfx/layers/ipc/ImageBridgeParent.h index bcd513e44ff6..a356d9096cb4 100644 --- a/gfx/layers/ipc/ImageBridgeParent.h +++ b/gfx/layers/ipc/ImageBridgeParent.h @@ -151,8 +151,6 @@ private: * Map of all living ImageBridgeParent instances */ static std::map sImageBridges; - - static MessageLoop* sMainLoop; }; } // layers diff --git a/gfx/layers/ipc/ThreadSafeRefcountingWithMainThreadDestruction.h b/gfx/layers/ipc/ThreadSafeRefcountingWithMainThreadDestruction.h deleted file mode 100644 index 0d5f39235d22..000000000000 --- a/gfx/layers/ipc/ThreadSafeRefcountingWithMainThreadDestruction.h +++ /dev/null @@ -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 \ No newline at end of file diff --git a/gfx/layers/moz.build b/gfx/layers/moz.build index 8d021197ad2c..eb7123dea675 100644 --- a/gfx/layers/moz.build +++ b/gfx/layers/moz.build @@ -27,7 +27,6 @@ EXPORTS += [ 'ipc/CompositorChild.h', 'ipc/CompositorParent.h', 'ipc/ShadowLayersManager.h', - 'ipc/ThreadSafeRefcountingWithMainThreadDestruction.h', 'Layers.h', 'LayerScope.h', 'LayersLogging.h', diff --git a/ipc/glue/ProtocolUtils.cpp b/ipc/glue/ProtocolUtils.cpp index 70374428394d..ff059ae84fbb 100644 --- a/ipc/glue/ProtocolUtils.cpp +++ b/ipc/glue/ProtocolUtils.cpp @@ -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; diff --git a/ipc/glue/ProtocolUtils.h b/ipc/glue/ProtocolUtils.h index 1d37a2cb59e9..48c2b75c545b 100644 --- a/ipc/glue/ProtocolUtils.h +++ b/ipc/glue/ProtocolUtils.h @@ -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 @@ -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(); } diff --git a/xpcom/base/nsTraceRefcnt.cpp b/xpcom/base/nsTraceRefcnt.cpp index 6bc5f3efe4e9..fd8019ca0be6 100644 --- a/xpcom/base/nsTraceRefcnt.cpp +++ b/xpcom/base/nsTraceRefcnt.cpp @@ -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(); diff --git a/xpcom/build/nsXPComInit.cpp b/xpcom/build/nsXPComInit.cpp index c53bb94a7499..efab931019f3 100644 --- a/xpcom/build/nsXPComInit.cpp +++ b/xpcom/build/nsXPComInit.cpp @@ -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); diff --git a/xpcom/glue/MainThreadUtils.h b/xpcom/glue/MainThreadUtils.h index 26ad68ec078b..f98746f3ac25 100644 --- a/xpcom/glue/MainThreadUtils.h +++ b/xpcom/glue/MainThreadUtils.h @@ -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. diff --git a/xpcom/glue/nsThreadUtils.cpp b/xpcom/glue/nsThreadUtils.cpp index 71837470c870..6a97463392a2 100644 --- a/xpcom/glue/nsThreadUtils.cpp +++ b/xpcom/glue/nsThreadUtils.cpp @@ -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 } } diff --git a/xpcom/glue/nsThreadUtils.h b/xpcom/glue/nsThreadUtils.h index d47359ba8fc5..cf68e911afa5 100644 --- a/xpcom/glue/nsThreadUtils.h +++ b/xpcom/glue/nsThreadUtils.h @@ -565,7 +565,6 @@ private: #endif }; -void -NS_SetMainThread(); + #endif // nsThreadUtils_h__ diff --git a/xpcom/threads/nsThreadManager.cpp b/xpcom/threads/nsThreadManager.cpp index 9ba0ee7d3f11..b061d67341ba 100644 --- a/xpcom/threads/nsThreadManager.cpp +++ b/xpcom/threads/nsThreadManager.cpp @@ -10,7 +10,6 @@ #include "nsIClassInfoImpl.h" #include "nsTArray.h" #include "nsAutoPtr.h" -#include "mozilla/ThreadLocal.h" #ifdef MOZ_CANARY #include #include @@ -25,26 +24,6 @@ DWORD gTLSThreadIDIndex = TlsAlloc(); NS_TLS mozilla::threads::ID gTLSThreadID = mozilla::threads::Generic; #endif -static mozilla::ThreadLocal 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> nsThreadArray; //-----------------------------------------------------------------------------