Loading xpcom/threads/ThreadEventTarget.cpp +3 −1 Original line number Diff line number Diff line Loading @@ -32,7 +32,9 @@ ThreadEventTarget::ThreadEventTarget(ThreadTargetSink* aSink, mThread = PR_GetCurrentThread(); } void ThreadEventTarget::SetCurrentThread() { mThread = PR_GetCurrentThread(); } void ThreadEventTarget::SetCurrentThread(PRThread* aThread) { mThread = aThread; } void ThreadEventTarget::ClearCurrentThread() { mThread = nullptr; } Loading xpcom/threads/ThreadEventTarget.h +1 −1 Original line number Diff line number Diff line Loading @@ -30,7 +30,7 @@ class ThreadEventTarget final : public nsISerialEventTarget { // Sets the thread for which IsOnCurrentThread returns true to the current // thread. void SetCurrentThread(); void SetCurrentThread(PRThread* aThread); // Call ClearCurrentThread() before the PRThread is deleted on thread join. void ClearCurrentThread(); Loading xpcom/threads/nsThread.cpp +25 −62 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include "pratom.h" #include "mozilla/BackgroundHangMonitor.h" #include "mozilla/CycleCollectedJSContext.h" #include "mozilla/DebugOnly.h" #include "mozilla/Logging.h" #include "nsIObserverService.h" #include "mozilla/IOInterposer.h" Loading Loading @@ -201,37 +202,6 @@ NS_IMPL_CI_INTERFACE_GETTER(nsThread, nsIThread, nsIThreadInternal, //----------------------------------------------------------------------------- class nsThreadStartupEvent final : public Runnable { public: nsThreadStartupEvent() : Runnable("nsThreadStartupEvent"), mMon("nsThreadStartupEvent.mMon"), mInitialized(false) {} // This method does not return until the thread startup object is in the // completion state. void Wait() { ReentrantMonitorAutoEnter mon(mMon); while (!mInitialized) { mon.Wait(); } } private: ~nsThreadStartupEvent() = default; NS_IMETHOD Run() override { ReentrantMonitorAutoEnter mon(mMon); mInitialized = true; mon.Notify(); return NS_OK; } ReentrantMonitor mMon; bool mInitialized; }; //----------------------------------------------------------------------------- bool nsThread::ShutdownContextsComp::Equals( const ShutdownContexts::elem_type& a, const ShutdownContexts::elem_type::Pointer b) const { Loading Loading @@ -340,7 +310,7 @@ namespace { struct ThreadInitData { nsThread* thread; const nsACString& name; nsCString name; }; } // namespace Loading Loading @@ -393,14 +363,16 @@ void nsThread::MaybeRemoveFromThreadList() { void nsThread::ThreadFunc(void* aArg) { using mozilla::ipc::BackgroundChild; ThreadInitData* initData = static_cast<ThreadInitData*>(aArg); UniquePtr<ThreadInitData> initData(static_cast<ThreadInitData*>(aArg)); nsThread* self = initData->thread; // strong reference MOZ_ASSERT(self->mEventTarget); MOZ_ASSERT(self->mEvents); self->mThread = PR_GetCurrentThread(); self->mEventTarget->SetCurrentThread(); // Note: see the comment in nsThread::Init, where we set these same values. DebugOnly<PRThread*> prev = self->mThread.exchange(PR_GetCurrentThread()); MOZ_ASSERT(!prev || prev == PR_GetCurrentThread()); self->mEventTarget->SetCurrentThread(self->mThread); SetupCurrentThreadForChaosMode(); if (!initData->name.IsEmpty()) { Loading @@ -424,15 +396,6 @@ void nsThread::ThreadFunc(void* aArg) { } #endif // MOZ_GECKO_PROFILER // Wait for and process startup event nsCOMPtr<nsIRunnable> event = self->mEvents->GetEvent(true, nullptr); MOZ_ASSERT(event); initData = nullptr; // clear before unblocking nsThread::Init event->Run(); // unblocks nsThread::Init event = nullptr; { // Scope for MessageLoop. MessageLoop loop(MessageLoop::TYPE_MOZILLA_NONMAINTHREAD, self); Loading Loading @@ -478,7 +441,8 @@ void nsThread::ThreadFunc(void* aArg) { NotNull<nsThreadShutdownContext*> context = WrapNotNull(self->mShutdownContext); MOZ_ASSERT(context->mTerminatingThread == self); event = do_QueryObject(new nsThreadShutdownAckEvent(context)); nsCOMPtr<nsIRunnable> event = do_QueryObject(new nsThreadShutdownAckEvent(context)); if (context->mIsMainThreadJoining) { SchedulerGroup::Dispatch(TaskCategory::Other, event.forget()); } else { Loading Loading @@ -644,35 +608,34 @@ nsThread::~nsThread() { nsresult nsThread::Init(const nsACString& aName) { MOZ_ASSERT(mEvents); MOZ_ASSERT(mEventTarget); // spawn thread and wait until it is fully setup RefPtr<nsThreadStartupEvent> startup = new nsThreadStartupEvent(); MOZ_ASSERT(!mThread); NS_ADDREF_THIS(); mShutdownRequired = true; ThreadInitData initData = {this, aName}; UniquePtr<ThreadInitData> initData( new ThreadInitData{this, nsCString(aName)}); PRThread* thread = nullptr; // ThreadFunc is responsible for setting mThread if (!PR_CreateThread(PR_USER_THREAD, ThreadFunc, &initData, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, mStackSize)) { if (!(thread = PR_CreateThread(PR_USER_THREAD, ThreadFunc, initData.get(), PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, mStackSize))) { NS_RELEASE_THIS(); return NS_ERROR_OUT_OF_MEMORY; } // ThreadFunc will wait for this event to be run before it tries to access // mThread. By delaying insertion of this event into the queue, we ensure // that mThread is set properly. { mEvents->PutEvent(do_AddRef(startup), EventQueuePriority::Normal); // retain a reference } // The created thread now owns initData, so release our ownership of it. Unused << initData.release(); // Note: we set these both here and inside ThreadFunc, to what should be // the same value. This is because calls within ThreadFunc need these values // to be set, and our callers need these values to be set. DebugOnly<PRThread*> prev = mThread.exchange(thread); MOZ_ASSERT(!prev || prev == thread); // Wait for thread to call ThreadManager::SetupCurrentThread, which completes // initialization of ThreadFunc. startup->Wait(); mEventTarget->SetCurrentThread(thread); return NS_OK; } Loading Loading
xpcom/threads/ThreadEventTarget.cpp +3 −1 Original line number Diff line number Diff line Loading @@ -32,7 +32,9 @@ ThreadEventTarget::ThreadEventTarget(ThreadTargetSink* aSink, mThread = PR_GetCurrentThread(); } void ThreadEventTarget::SetCurrentThread() { mThread = PR_GetCurrentThread(); } void ThreadEventTarget::SetCurrentThread(PRThread* aThread) { mThread = aThread; } void ThreadEventTarget::ClearCurrentThread() { mThread = nullptr; } Loading
xpcom/threads/ThreadEventTarget.h +1 −1 Original line number Diff line number Diff line Loading @@ -30,7 +30,7 @@ class ThreadEventTarget final : public nsISerialEventTarget { // Sets the thread for which IsOnCurrentThread returns true to the current // thread. void SetCurrentThread(); void SetCurrentThread(PRThread* aThread); // Call ClearCurrentThread() before the PRThread is deleted on thread join. void ClearCurrentThread(); Loading
xpcom/threads/nsThread.cpp +25 −62 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include "pratom.h" #include "mozilla/BackgroundHangMonitor.h" #include "mozilla/CycleCollectedJSContext.h" #include "mozilla/DebugOnly.h" #include "mozilla/Logging.h" #include "nsIObserverService.h" #include "mozilla/IOInterposer.h" Loading Loading @@ -201,37 +202,6 @@ NS_IMPL_CI_INTERFACE_GETTER(nsThread, nsIThread, nsIThreadInternal, //----------------------------------------------------------------------------- class nsThreadStartupEvent final : public Runnable { public: nsThreadStartupEvent() : Runnable("nsThreadStartupEvent"), mMon("nsThreadStartupEvent.mMon"), mInitialized(false) {} // This method does not return until the thread startup object is in the // completion state. void Wait() { ReentrantMonitorAutoEnter mon(mMon); while (!mInitialized) { mon.Wait(); } } private: ~nsThreadStartupEvent() = default; NS_IMETHOD Run() override { ReentrantMonitorAutoEnter mon(mMon); mInitialized = true; mon.Notify(); return NS_OK; } ReentrantMonitor mMon; bool mInitialized; }; //----------------------------------------------------------------------------- bool nsThread::ShutdownContextsComp::Equals( const ShutdownContexts::elem_type& a, const ShutdownContexts::elem_type::Pointer b) const { Loading Loading @@ -340,7 +310,7 @@ namespace { struct ThreadInitData { nsThread* thread; const nsACString& name; nsCString name; }; } // namespace Loading Loading @@ -393,14 +363,16 @@ void nsThread::MaybeRemoveFromThreadList() { void nsThread::ThreadFunc(void* aArg) { using mozilla::ipc::BackgroundChild; ThreadInitData* initData = static_cast<ThreadInitData*>(aArg); UniquePtr<ThreadInitData> initData(static_cast<ThreadInitData*>(aArg)); nsThread* self = initData->thread; // strong reference MOZ_ASSERT(self->mEventTarget); MOZ_ASSERT(self->mEvents); self->mThread = PR_GetCurrentThread(); self->mEventTarget->SetCurrentThread(); // Note: see the comment in nsThread::Init, where we set these same values. DebugOnly<PRThread*> prev = self->mThread.exchange(PR_GetCurrentThread()); MOZ_ASSERT(!prev || prev == PR_GetCurrentThread()); self->mEventTarget->SetCurrentThread(self->mThread); SetupCurrentThreadForChaosMode(); if (!initData->name.IsEmpty()) { Loading @@ -424,15 +396,6 @@ void nsThread::ThreadFunc(void* aArg) { } #endif // MOZ_GECKO_PROFILER // Wait for and process startup event nsCOMPtr<nsIRunnable> event = self->mEvents->GetEvent(true, nullptr); MOZ_ASSERT(event); initData = nullptr; // clear before unblocking nsThread::Init event->Run(); // unblocks nsThread::Init event = nullptr; { // Scope for MessageLoop. MessageLoop loop(MessageLoop::TYPE_MOZILLA_NONMAINTHREAD, self); Loading Loading @@ -478,7 +441,8 @@ void nsThread::ThreadFunc(void* aArg) { NotNull<nsThreadShutdownContext*> context = WrapNotNull(self->mShutdownContext); MOZ_ASSERT(context->mTerminatingThread == self); event = do_QueryObject(new nsThreadShutdownAckEvent(context)); nsCOMPtr<nsIRunnable> event = do_QueryObject(new nsThreadShutdownAckEvent(context)); if (context->mIsMainThreadJoining) { SchedulerGroup::Dispatch(TaskCategory::Other, event.forget()); } else { Loading Loading @@ -644,35 +608,34 @@ nsThread::~nsThread() { nsresult nsThread::Init(const nsACString& aName) { MOZ_ASSERT(mEvents); MOZ_ASSERT(mEventTarget); // spawn thread and wait until it is fully setup RefPtr<nsThreadStartupEvent> startup = new nsThreadStartupEvent(); MOZ_ASSERT(!mThread); NS_ADDREF_THIS(); mShutdownRequired = true; ThreadInitData initData = {this, aName}; UniquePtr<ThreadInitData> initData( new ThreadInitData{this, nsCString(aName)}); PRThread* thread = nullptr; // ThreadFunc is responsible for setting mThread if (!PR_CreateThread(PR_USER_THREAD, ThreadFunc, &initData, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, mStackSize)) { if (!(thread = PR_CreateThread(PR_USER_THREAD, ThreadFunc, initData.get(), PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, mStackSize))) { NS_RELEASE_THIS(); return NS_ERROR_OUT_OF_MEMORY; } // ThreadFunc will wait for this event to be run before it tries to access // mThread. By delaying insertion of this event into the queue, we ensure // that mThread is set properly. { mEvents->PutEvent(do_AddRef(startup), EventQueuePriority::Normal); // retain a reference } // The created thread now owns initData, so release our ownership of it. Unused << initData.release(); // Note: we set these both here and inside ThreadFunc, to what should be // the same value. This is because calls within ThreadFunc need these values // to be set, and our callers need these values to be set. DebugOnly<PRThread*> prev = mThread.exchange(thread); MOZ_ASSERT(!prev || prev == thread); // Wait for thread to call ThreadManager::SetupCurrentThread, which completes // initialization of ThreadFunc. startup->Wait(); mEventTarget->SetCurrentThread(thread); return NS_OK; } Loading