зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 2 changesets (bug 1479035) for build bustages bustages netwerk/cache2/target on CLOSED TREE
Backed out changeset 5f8706213610 (bug 1479035) Backed out changeset a03a61d6d724 (bug 1479035)
This commit is contained in:
Родитель
5e0fc81391
Коммит
36cc0e5fa7
|
@ -25,12 +25,8 @@
|
|||
#include "mozilla/BasePrincipal.h"
|
||||
#include "mozilla/ipc/BackgroundParent.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsThread.h"
|
||||
#include "nsThreadManager.h"
|
||||
#include "nsVariant.h"
|
||||
#include "mozilla/EventQueue.h"
|
||||
#include "mozilla/IOInterposer.h"
|
||||
#include "mozilla/ThreadEventQueue.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/Tokenizer.h"
|
||||
#include "GeckoProfiler.h"
|
||||
|
@ -492,12 +488,6 @@ StorageDBThread::SetDefaultPriority()
|
|||
void
|
||||
StorageDBThread::ThreadFunc(void* aArg)
|
||||
{
|
||||
{
|
||||
auto queue = MakeRefPtr<ThreadEventQueue<EventQueue>>(MakeUnique<EventQueue>());
|
||||
Unused <<
|
||||
nsThreadManager::get().CreateCurrentThread(queue, nsThread::NOT_MAIN_THREAD);
|
||||
}
|
||||
|
||||
AUTO_PROFILER_REGISTER_THREAD("localStorage DB");
|
||||
NS_SetCurrentThreadName("localStorage DB");
|
||||
mozilla::IOInterposer::RegisterCurrentThread();
|
||||
|
|
|
@ -5354,13 +5354,22 @@ WorkerPrivate::CreateDebuggerGlobalScope(JSContext* aCx)
|
|||
bool
|
||||
WorkerPrivate::IsOnWorkerThread() const
|
||||
{
|
||||
// We can't use mThread because it must be protected by mMutex and sometimes
|
||||
// this method is called when mMutex is already locked. This method should
|
||||
// always work.
|
||||
// This is much more complicated than it needs to be but we can't use mThread
|
||||
// because it must be protected by mMutex and sometimes this method is called
|
||||
// when mMutex is already locked. This method should always work.
|
||||
MOZ_ASSERT(mPRThread,
|
||||
"AssertIsOnWorkerThread() called before a thread was assigned!");
|
||||
|
||||
return mPRThread == PR_GetCurrentThread();
|
||||
nsCOMPtr<nsIThread> thread;
|
||||
nsresult rv =
|
||||
nsThreadManager::get().GetThreadFromPRThread(mPRThread,
|
||||
getter_AddRefs(thread));
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
MOZ_ASSERT(thread);
|
||||
|
||||
bool current;
|
||||
rv = thread->IsOnCurrentThread(¤t);
|
||||
return NS_SUCCEEDED(rv) && current;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
|
|
@ -35,6 +35,10 @@ void InitThreading();
|
|||
#endif
|
||||
|
||||
static void* ThreadFunc(void* closure) {
|
||||
// Create a nsThread wrapper for the current platform thread, and register it
|
||||
// with the thread manager.
|
||||
(void) NS_GetCurrentThread();
|
||||
|
||||
PlatformThread::Delegate* delegate =
|
||||
static_cast<PlatformThread::Delegate*>(closure);
|
||||
delegate->ThreadMain();
|
||||
|
|
|
@ -25,6 +25,10 @@ typedef struct tagTHREADNAME_INFO {
|
|||
} THREADNAME_INFO;
|
||||
|
||||
DWORD __stdcall ThreadFunc(void* closure) {
|
||||
// Create a nsThread wrapper for the current platform thread, and register it
|
||||
// with the thread manager.
|
||||
(void) NS_GetCurrentThread();
|
||||
|
||||
PlatformThread::Delegate* delegate =
|
||||
static_cast<PlatformThread::Delegate*>(closure);
|
||||
delegate->ThreadMain();
|
||||
|
|
|
@ -10,11 +10,8 @@
|
|||
#include "base/thread_local.h"
|
||||
#include "base/waitable_event.h"
|
||||
#include "GeckoProfiler.h"
|
||||
#include "mozilla/EventQueue.h"
|
||||
#include "mozilla/IOInterposer.h"
|
||||
#include "mozilla/ThreadEventQueue.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsThreadManager.h"
|
||||
|
||||
#ifdef MOZ_TASK_TRACER
|
||||
#include "GeckoTaskTracer.h"
|
||||
|
@ -157,24 +154,12 @@ void Thread::StopSoon() {
|
|||
}
|
||||
|
||||
void Thread::ThreadMain() {
|
||||
nsCOMPtr<nsIThread> xpcomThread;
|
||||
if (startup_data_->options.message_loop_type == MessageLoop::TYPE_MOZILLA_NONMAINTHREAD) {
|
||||
auto queue = mozilla::MakeRefPtr<mozilla::ThreadEventQueue<mozilla::EventQueue>>(
|
||||
mozilla::MakeUnique<mozilla::EventQueue>());
|
||||
xpcomThread =
|
||||
nsThreadManager::get().CreateCurrentThread(queue, nsThread::NOT_MAIN_THREAD);
|
||||
} else {
|
||||
xpcomThread = NS_GetCurrentThread();
|
||||
}
|
||||
|
||||
AUTO_PROFILER_REGISTER_THREAD(name_.c_str());
|
||||
mozilla::IOInterposer::RegisterCurrentThread();
|
||||
|
||||
// The message loop for this thread.
|
||||
MessageLoop message_loop(startup_data_->options.message_loop_type,
|
||||
xpcomThread);
|
||||
|
||||
xpcomThread = nullptr;
|
||||
NS_GetCurrentThread());
|
||||
|
||||
// Complete the initialization of our Thread object.
|
||||
thread_id_ = PlatformThread::CurrentId();
|
||||
|
|
|
@ -8,12 +8,8 @@
|
|||
#include "nsIRunnable.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "nsThread.h"
|
||||
#include "nsThreadManager.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "mozilla/EventQueue.h"
|
||||
#include "mozilla/IOInterposer.h"
|
||||
#include "mozilla/ThreadEventQueue.h"
|
||||
#include "GeckoProfiler.h"
|
||||
|
||||
#ifdef XP_WIN
|
||||
|
@ -465,10 +461,8 @@ void CacheIOThread::ThreadFunc()
|
|||
MOZ_ASSERT(mBlockingIOWatcher);
|
||||
mBlockingIOWatcher->InitThread();
|
||||
|
||||
auto queue = MakeRefPtr<ThreadEventQueue<mozilla::EventQueue>>(
|
||||
MakeUnique<mozilla::EventQueue>());
|
||||
nsCOMPtr<nsIThread> xpcomThread =
|
||||
nsThreadManager::get().CreateCurrentThread(queue, nsThread::NOT_MAIN_THREAD);
|
||||
// This creates nsThread for this PRThread
|
||||
nsCOMPtr<nsIThread> xpcomThread = NS_GetCurrentThread();
|
||||
|
||||
threadInternal = do_QueryInterface(xpcomThread);
|
||||
if (threadInternal)
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
#include "mozilla/ipc/FileDescriptor.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsAppDirectoryServiceDefs.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "SpecialSystemDirectory.h"
|
||||
#include "sandbox/linux/system_headers/linux_syscalls.h"
|
||||
|
||||
|
@ -664,10 +663,6 @@ SandboxBroker::SymlinkPermissions(const char* aPath, const size_t aPathLen)
|
|||
void
|
||||
SandboxBroker::ThreadMain(void)
|
||||
{
|
||||
// Create a nsThread wrapper for the current platform thread, and register it
|
||||
// with the thread manager.
|
||||
(void) NS_GetCurrentThread();
|
||||
|
||||
char threadName[16];
|
||||
SprintfLiteral(threadName, "FS Broker %d", mChildPid);
|
||||
PlatformThread::SetName(threadName);
|
||||
|
|
|
@ -237,10 +237,6 @@ SandboxReporter::AddOne(const SandboxReport& aReport)
|
|||
void
|
||||
SandboxReporter::ThreadMain(void)
|
||||
{
|
||||
// Create a nsThread wrapper for the current platform thread, and register it
|
||||
// with the thread manager.
|
||||
(void) NS_GetCurrentThread();
|
||||
|
||||
for (;;) {
|
||||
SandboxReport rep;
|
||||
struct iovec iov;
|
||||
|
|
|
@ -225,7 +225,7 @@ PRThread *watched_thread = nullptr;
|
|||
* When the thread a mutex is invoked on isn't watched_thread we save it to this
|
||||
* variable.
|
||||
*/
|
||||
nsIThread* last_non_watched_thread = nullptr;
|
||||
PRThread *last_non_watched_thread = nullptr;
|
||||
|
||||
/**
|
||||
* Set a flag if the mutex is used on the thread we are watching, but always
|
||||
|
@ -233,10 +233,11 @@ nsIThread* last_non_watched_thread = nullptr;
|
|||
*/
|
||||
extern "C" void wrapped_MutexEnter(sqlite3_mutex *mutex)
|
||||
{
|
||||
if (PR_GetCurrentThread() == watched_thread)
|
||||
PRThread *curThread = ::PR_GetCurrentThread();
|
||||
if (curThread == watched_thread)
|
||||
mutex_used_on_watched_thread = true;
|
||||
else
|
||||
last_non_watched_thread = NS_GetCurrentThread();
|
||||
last_non_watched_thread = curThread;
|
||||
orig_mutex_methods.xMutexEnter(mutex);
|
||||
}
|
||||
|
||||
|
@ -350,13 +351,19 @@ get_conn_async_thread(mozIStorageConnection *db)
|
|||
blocking_async_execute(stmt);
|
||||
stmt->Finalize();
|
||||
|
||||
nsCOMPtr<nsIThread> asyncThread = last_non_watched_thread;
|
||||
nsCOMPtr<nsIThreadManager> threadMan =
|
||||
do_GetService("@mozilla.org/thread-manager;1");
|
||||
nsCOMPtr<nsIThread> asyncThread;
|
||||
threadMan->GetThreadFromPRThread(last_non_watched_thread,
|
||||
getter_AddRefs(asyncThread));
|
||||
|
||||
// Additionally, check that the thread we get as the background thread is the
|
||||
// same one as the one we report from getInterface.
|
||||
nsCOMPtr<nsIEventTarget> target = do_GetInterface(db);
|
||||
nsCOMPtr<nsIThread> allegedAsyncThread = do_QueryInterface(target);
|
||||
do_check_eq(allegedAsyncThread, asyncThread);
|
||||
PRThread *allegedPRThread;
|
||||
(void)allegedAsyncThread->GetPRThread(&allegedPRThread);
|
||||
do_check_eq(allegedPRThread, last_non_watched_thread);
|
||||
return asyncThread.forget();
|
||||
}
|
||||
|
||||
|
|
|
@ -84,6 +84,19 @@ interface nsIThreadManager : nsISupports
|
|||
*/
|
||||
[noscript] nsIThread newNamedThread(in ACString name, [optional] in unsigned long stackSize);
|
||||
|
||||
/**
|
||||
* Get the nsIThread object (if any) corresponding to the given PRThread.
|
||||
* This method returns null if there is no corresponding nsIThread.
|
||||
*
|
||||
* @param prthread
|
||||
* The PRThread of the nsIThread being requested.
|
||||
*
|
||||
* @returns
|
||||
* The nsIThread object corresponding to the given PRThread or null if no
|
||||
* such nsIThread exists.
|
||||
*/
|
||||
[noscript] nsIThread getThreadFromPRThread(in PRThread prthread);
|
||||
|
||||
/**
|
||||
* Get the main thread.
|
||||
*/
|
||||
|
|
|
@ -115,9 +115,6 @@ NS_DECL_CI_INTERFACE_GETTER(nsThread)
|
|||
|
||||
Array<char, nsThread::kRunnableNameBufSize> nsThread::sMainThreadRunnableName;
|
||||
|
||||
uint32_t nsThread::sActiveThreads;
|
||||
uint32_t nsThread::sMaxActiveThreads;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Because we do not have our own nsIFactory, we have to implement nsIClassInfo
|
||||
// somewhat manually.
|
||||
|
@ -419,40 +416,6 @@ nsThread::Enumerate()
|
|||
return {};
|
||||
}
|
||||
|
||||
/* static */ uint32_t
|
||||
nsThread::MaxActiveThreads()
|
||||
{
|
||||
OffTheBooksMutexAutoLock mal(ThreadListMutex());
|
||||
return sMaxActiveThreads;
|
||||
}
|
||||
|
||||
void
|
||||
nsThread::AddToThreadList()
|
||||
{
|
||||
OffTheBooksMutexAutoLock mal(ThreadListMutex());
|
||||
MOZ_ASSERT(!isInList());
|
||||
|
||||
sActiveThreads++;
|
||||
sMaxActiveThreads = std::max(sActiveThreads, sMaxActiveThreads);
|
||||
|
||||
ThreadList().insertBack(this);
|
||||
}
|
||||
|
||||
void
|
||||
nsThread::MaybeRemoveFromThreadList()
|
||||
{
|
||||
// We shouldn't need to lock before checking isInList at this point. We're
|
||||
// destroying the last reference to this object, so there's no way for anyone
|
||||
// else to remove it in the middle of our check. And the not-in-list state is
|
||||
// determined the element's next and previous members pointing to itself, so a
|
||||
// non-atomic update to an adjacent member won't affect the outcome either.
|
||||
if (isInList()) {
|
||||
OffTheBooksMutexAutoLock mal(ThreadListMutex());
|
||||
sActiveThreads--;
|
||||
removeFrom(ThreadList());
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/ void
|
||||
nsThread::ThreadFunc(void* aArg)
|
||||
{
|
||||
|
@ -461,9 +424,6 @@ nsThread::ThreadFunc(void* aArg)
|
|||
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->mVirtualThread = GetCurrentVirtualThread();
|
||||
self->mEventTarget->SetCurrentThread();
|
||||
|
@ -625,7 +585,8 @@ nsThread::InitCommon()
|
|||
#endif
|
||||
}
|
||||
|
||||
AddToThreadList();
|
||||
OffTheBooksMutexAutoLock mal(ThreadListMutex());
|
||||
ThreadList().insertBack(this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -655,33 +616,20 @@ nsThread::nsThread(NotNull<SynchronizedEventQueue*> aQueue,
|
|||
{
|
||||
}
|
||||
|
||||
|
||||
nsThread::nsThread()
|
||||
: mEvents(nullptr)
|
||||
, mEventTarget(nullptr)
|
||||
, mShutdownContext(nullptr)
|
||||
, mScriptObserver(nullptr)
|
||||
, mThread(nullptr)
|
||||
, mStackSize(0)
|
||||
, mNestedEventLoopDepth(0)
|
||||
, mCurrentEventLoopDepth(-1)
|
||||
, mShutdownRequired(false)
|
||||
, mPriority(PRIORITY_NORMAL)
|
||||
, mIsMainThread(NOT_MAIN_THREAD)
|
||||
, mCanInvokeJS(false)
|
||||
, mCurrentEvent(nullptr)
|
||||
, mCurrentEventStart(TimeStamp::Now())
|
||||
, mCurrentPerformanceCounter(nullptr)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
}
|
||||
|
||||
nsThread::~nsThread()
|
||||
{
|
||||
NS_ASSERTION(mRequestedShutdownContexts.IsEmpty(),
|
||||
"shouldn't be waiting on other threads to shutdown");
|
||||
|
||||
MaybeRemoveFromThreadList();
|
||||
// We shouldn't need to lock before checking isInList at this point. We're
|
||||
// destroying the last reference to this object, so there's no way for anyone
|
||||
// else to remove it in the middle of our check. And the not-in-list state is
|
||||
// determined the element's next and previous members pointing to itself, so a
|
||||
// non-atomic update to an adjacent member won't affect the outcome either.
|
||||
if (isInList()) {
|
||||
OffTheBooksMutexAutoLock mal(ThreadListMutex());
|
||||
removeFrom(ThreadList());
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
// We deliberately leak these so they can be tracked by the leak checker.
|
||||
|
@ -699,9 +647,6 @@ 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();
|
||||
|
||||
|
@ -750,9 +695,6 @@ nsThread::InitCurrentThread()
|
|||
NS_IMETHODIMP
|
||||
nsThread::DispatchFromScript(nsIRunnable* aEvent, uint32_t aFlags)
|
||||
{
|
||||
MOZ_ASSERT(mEventTarget);
|
||||
NS_ENSURE_TRUE(mEventTarget, NS_ERROR_NOT_IMPLEMENTED);
|
||||
|
||||
nsCOMPtr<nsIRunnable> event(aEvent);
|
||||
return mEventTarget->Dispatch(event.forget(), aFlags);
|
||||
}
|
||||
|
@ -760,9 +702,6 @@ nsThread::DispatchFromScript(nsIRunnable* aEvent, uint32_t aFlags)
|
|||
NS_IMETHODIMP
|
||||
nsThread::Dispatch(already_AddRefed<nsIRunnable> aEvent, uint32_t aFlags)
|
||||
{
|
||||
MOZ_ASSERT(mEventTarget);
|
||||
NS_ENSURE_TRUE(mEventTarget, NS_ERROR_NOT_IMPLEMENTED);
|
||||
|
||||
LOG(("THRD(%p) Dispatch [%p %x]\n", this, /* XXX aEvent */nullptr, aFlags));
|
||||
|
||||
return mEventTarget->Dispatch(std::move(aEvent), aFlags);
|
||||
|
@ -771,20 +710,13 @@ nsThread::Dispatch(already_AddRefed<nsIRunnable> aEvent, uint32_t aFlags)
|
|||
NS_IMETHODIMP
|
||||
nsThread::DelayedDispatch(already_AddRefed<nsIRunnable> aEvent, uint32_t aDelayMs)
|
||||
{
|
||||
MOZ_ASSERT(mEventTarget);
|
||||
NS_ENSURE_TRUE(mEventTarget, NS_ERROR_NOT_IMPLEMENTED);
|
||||
|
||||
return mEventTarget->DelayedDispatch(std::move(aEvent), aDelayMs);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsThread::IsOnCurrentThread(bool* aResult)
|
||||
{
|
||||
if (mEventTarget) {
|
||||
return mEventTarget->IsOnCurrentThread(aResult);
|
||||
}
|
||||
*aResult = GetCurrentVirtualThread() == mVirtualThread;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(bool)
|
||||
|
@ -836,8 +768,6 @@ nsThread::AsyncShutdown()
|
|||
nsThreadShutdownContext*
|
||||
nsThread::ShutdownInternal(bool aSync)
|
||||
{
|
||||
MOZ_ASSERT(mEvents);
|
||||
MOZ_ASSERT(mEventTarget);
|
||||
MOZ_ASSERT(mThread);
|
||||
MOZ_ASSERT(mThread != PR_GetCurrentThread());
|
||||
if (NS_WARN_IF(mThread == PR_GetCurrentThread())) {
|
||||
|
@ -849,7 +779,12 @@ nsThread::ShutdownInternal(bool aSync)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
MaybeRemoveFromThreadList();
|
||||
{
|
||||
OffTheBooksMutexAutoLock mal(ThreadListMutex());
|
||||
if (isInList()) {
|
||||
removeFrom(ThreadList());
|
||||
}
|
||||
}
|
||||
|
||||
NotNull<nsThread*> currentThread =
|
||||
WrapNotNull(nsThreadManager::get().GetCurrentThread());
|
||||
|
@ -874,12 +809,15 @@ nsThread::ShutdownInternal(bool aSync)
|
|||
void
|
||||
nsThread::ShutdownComplete(NotNull<nsThreadShutdownContext*> aContext)
|
||||
{
|
||||
MOZ_ASSERT(mEvents);
|
||||
MOZ_ASSERT(mEventTarget);
|
||||
MOZ_ASSERT(mThread);
|
||||
MOZ_ASSERT(aContext->mTerminatingThread == this);
|
||||
|
||||
MaybeRemoveFromThreadList();
|
||||
{
|
||||
OffTheBooksMutexAutoLock mal(ThreadListMutex());
|
||||
if (isInList()) {
|
||||
removeFrom(ThreadList());
|
||||
}
|
||||
}
|
||||
|
||||
if (aContext->mAwaitingShutdownAck) {
|
||||
// We're in a synchronous shutdown, so tell whatever is up the stack that
|
||||
|
@ -1094,9 +1032,6 @@ nsThread::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
|
|||
NS_IMETHODIMP
|
||||
nsThread::ProcessNextEvent(bool aMayWait, bool* aResult)
|
||||
{
|
||||
MOZ_ASSERT(mEvents);
|
||||
NS_ENSURE_TRUE(mEvents, NS_ERROR_NOT_IMPLEMENTED);
|
||||
|
||||
LOG(("THRD(%p) ProcessNextEvent [%u %u]\n", this, aMayWait,
|
||||
mNestedEventLoopDepth));
|
||||
|
||||
|
@ -1329,9 +1264,6 @@ nsThread::AdjustPriority(int32_t aDelta)
|
|||
NS_IMETHODIMP
|
||||
nsThread::GetObserver(nsIThreadObserver** aObs)
|
||||
{
|
||||
MOZ_ASSERT(mEvents);
|
||||
NS_ENSURE_TRUE(mEvents, NS_ERROR_NOT_IMPLEMENTED);
|
||||
|
||||
nsCOMPtr<nsIThreadObserver> obs = mEvents->GetObserver();
|
||||
obs.forget(aObs);
|
||||
return NS_OK;
|
||||
|
@ -1340,9 +1272,6 @@ nsThread::GetObserver(nsIThreadObserver** aObs)
|
|||
NS_IMETHODIMP
|
||||
nsThread::SetObserver(nsIThreadObserver* aObs)
|
||||
{
|
||||
MOZ_ASSERT(mEvents);
|
||||
NS_ENSURE_TRUE(mEvents, NS_ERROR_NOT_IMPLEMENTED);
|
||||
|
||||
if (NS_WARN_IF(PR_GetCurrentThread() != mThread)) {
|
||||
return NS_ERROR_NOT_SAME_THREAD;
|
||||
}
|
||||
|
@ -1361,9 +1290,6 @@ nsThread::RecursionDepth() const
|
|||
NS_IMETHODIMP
|
||||
nsThread::AddObserver(nsIThreadObserver* aObserver)
|
||||
{
|
||||
MOZ_ASSERT(mEvents);
|
||||
NS_ENSURE_TRUE(mEvents, NS_ERROR_NOT_IMPLEMENTED);
|
||||
|
||||
if (NS_WARN_IF(!aObserver)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
@ -1379,9 +1305,6 @@ nsThread::AddObserver(nsIThreadObserver* aObserver)
|
|||
NS_IMETHODIMP
|
||||
nsThread::RemoveObserver(nsIThreadObserver* aObserver)
|
||||
{
|
||||
MOZ_ASSERT(mEvents);
|
||||
NS_ENSURE_TRUE(mEvents, NS_ERROR_NOT_IMPLEMENTED);
|
||||
|
||||
if (NS_WARN_IF(PR_GetCurrentThread() != mThread)) {
|
||||
return NS_ERROR_NOT_SAME_THREAD;
|
||||
}
|
||||
|
|
|
@ -60,10 +60,6 @@ public:
|
|||
MainThreadFlag aMainThread,
|
||||
uint32_t aStackSize);
|
||||
|
||||
private:
|
||||
nsThread();
|
||||
|
||||
public:
|
||||
// Initialize this as a wrapper for a new PRThread, and optionally give it a name.
|
||||
nsresult Init(const nsACString& aName = NS_LITERAL_CSTRING(""));
|
||||
|
||||
|
@ -150,8 +146,6 @@ public:
|
|||
|
||||
static nsThreadEnumerator Enumerate();
|
||||
|
||||
static uint32_t MaxActiveThreads();
|
||||
|
||||
private:
|
||||
void DoMainThreadSpecificProcessing(bool aReallyWait);
|
||||
|
||||
|
@ -180,21 +174,6 @@ protected:
|
|||
static mozilla::LinkedList<nsThread>& ThreadList();
|
||||
static void ClearThreadList();
|
||||
|
||||
// The current number of active threads.
|
||||
static uint32_t sActiveThreads;
|
||||
// The maximum current number of active threads we've had in this session.
|
||||
static uint32_t sMaxActiveThreads;
|
||||
|
||||
void AddToThreadList();
|
||||
void MaybeRemoveFromThreadList();
|
||||
|
||||
|
||||
// Whether or not these members have a value determines whether the nsThread
|
||||
// is treated as a full XPCOM thread or as a thin wrapper.
|
||||
//
|
||||
// For full nsThreads, they will always contain valid pointers. For thin
|
||||
// wrappers around non-XPCOM threads, they will be null, and event dispatch
|
||||
// methods which rely on them will fail (and assert) if called.
|
||||
RefPtr<mozilla::SynchronizedEventQueue> mEvents;
|
||||
RefPtr<mozilla::ThreadEventTarget> mEventTarget;
|
||||
|
||||
|
|
|
@ -109,6 +109,8 @@ nsThreadManager::ReleaseThread(void* aData)
|
|||
|
||||
auto* thread = static_cast<nsThread*>(aData);
|
||||
|
||||
get().UnregisterCurrentThread(*thread, true);
|
||||
|
||||
if (thread->mHasTLSEntry) {
|
||||
thread->mHasTLSEntry = false;
|
||||
thread->Release();
|
||||
|
@ -319,11 +321,14 @@ nsThreadManager::Shutdown()
|
|||
|
||||
{
|
||||
// We gather the threads from the hashtable into a list, so that we avoid
|
||||
// holding the enumerator lock while calling nsIThread::Shutdown.
|
||||
nsTArray<RefPtr<nsThread>> threadsToShutdown;
|
||||
for (auto* thread : nsThread::Enumerate()) {
|
||||
if (thread->ShutdownRequired()) {
|
||||
threadsToShutdown.AppendElement(thread);
|
||||
// holding the hashtable lock while calling nsIThread::Shutdown.
|
||||
nsThreadArray threads;
|
||||
{
|
||||
OffTheBooksMutexAutoLock lock(mLock);
|
||||
for (auto iter = mThreadsByPRThread.Iter(); !iter.Done(); iter.Next()) {
|
||||
RefPtr<nsThread>& thread = iter.Data();
|
||||
threads.AppendElement(WrapNotNull(thread));
|
||||
iter.Remove();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -337,10 +342,13 @@ nsThreadManager::Shutdown()
|
|||
// world until such time as the threads exit.
|
||||
|
||||
// Shutdown all threads that require it (join with threads that we created).
|
||||
for (auto& thread : threadsToShutdown) {
|
||||
for (uint32_t i = 0; i < threads.Length(); ++i) {
|
||||
NotNull<nsThread*> thread = threads[i];
|
||||
if (thread->ShutdownRequired()) {
|
||||
thread->Shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NB: It's possible that there are events in the queue that want to *start*
|
||||
// an asynchronous shutdown. But we have already shutdown the threads above,
|
||||
|
@ -353,6 +361,12 @@ nsThreadManager::Shutdown()
|
|||
|
||||
// There are no more background threads at this point.
|
||||
|
||||
// Clear the table of threads.
|
||||
{
|
||||
OffTheBooksMutexAutoLock lock(mLock);
|
||||
mThreadsByPRThread.Clear();
|
||||
}
|
||||
|
||||
// Normally thread shutdown clears the observer for the thread, but since the
|
||||
// main thread is special we do it manually here after we're sure all events
|
||||
// have been processed.
|
||||
|
@ -388,16 +402,36 @@ nsThreadManager::RegisterCurrentThread(nsThread& aThread)
|
|||
{
|
||||
MOZ_ASSERT(aThread.GetPRThread() == PR_GetCurrentThread(), "bad aThread");
|
||||
|
||||
OffTheBooksMutexAutoLock lock(mLock);
|
||||
|
||||
++mCurrentNumberOfThreads;
|
||||
if (mCurrentNumberOfThreads > mHighestNumberOfThreads) {
|
||||
mHighestNumberOfThreads = mCurrentNumberOfThreads;
|
||||
}
|
||||
|
||||
mThreadsByPRThread.Put(aThread.GetPRThread(), &aThread); // XXX check OOM?
|
||||
|
||||
aThread.AddRef(); // for TLS entry
|
||||
aThread.mHasTLSEntry = true;
|
||||
PR_SetThreadPrivate(mCurThreadIndex, &aThread);
|
||||
}
|
||||
|
||||
void
|
||||
nsThreadManager::UnregisterCurrentThread(nsThread& aThread)
|
||||
nsThreadManager::UnregisterCurrentThread(nsThread& aThread, bool aIfExists)
|
||||
{
|
||||
{
|
||||
OffTheBooksMutexAutoLock lock(mLock);
|
||||
|
||||
if (aIfExists && !mThreadsByPRThread.GetWeak(aThread.GetPRThread())) {
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(aThread.GetPRThread() == PR_GetCurrentThread(), "bad aThread");
|
||||
|
||||
--mCurrentNumberOfThreads;
|
||||
mThreadsByPRThread.Remove(aThread.GetPRThread());
|
||||
}
|
||||
|
||||
PR_SetThreadPrivate(mCurThreadIndex, nullptr);
|
||||
// Ref-count balanced via ReleaseThread
|
||||
}
|
||||
|
@ -413,6 +447,7 @@ nsThreadManager::CreateCurrentThread(SynchronizedEventQueue* aQueue,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
// OK, that's fine. We'll dynamically create one :-)
|
||||
RefPtr<nsThread> thread = new nsThread(WrapNotNull(aQueue), aMainThread, 0);
|
||||
if (!thread || NS_FAILED(thread->InitCurrentThread())) {
|
||||
return nullptr;
|
||||
|
@ -435,11 +470,9 @@ nsThreadManager::GetCurrentThread()
|
|||
}
|
||||
|
||||
// OK, that's fine. We'll dynamically create one :-)
|
||||
//
|
||||
// We assume that if we're implicitly creating a thread here that it doesn't
|
||||
// want an event queue. Any thread which wants an event queue should
|
||||
// explicitly create its nsThread wrapper.
|
||||
RefPtr<nsThread> thread = new nsThread();
|
||||
RefPtr<ThreadEventQueue<EventQueue>> queue =
|
||||
new ThreadEventQueue<EventQueue>(MakeUnique<EventQueue>());
|
||||
RefPtr<nsThread> thread = new nsThread(WrapNotNull(queue), nsThread::NOT_MAIN_THREAD, 0);
|
||||
if (!thread || NS_FAILED(thread->InitCurrentThread())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -454,7 +487,7 @@ nsThreadManager::IsNSThread() const
|
|||
return false;
|
||||
}
|
||||
if (auto* thread = (nsThread*)PR_GetThreadPrivate(mCurThreadIndex)) {
|
||||
return thread->EventQueue();
|
||||
return thread->mShutdownRequired;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -503,6 +536,27 @@ nsThreadManager::NewNamedThread(const nsACString& aName,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsThreadManager::GetThreadFromPRThread(PRThread* aThread, nsIThread** aResult)
|
||||
{
|
||||
// Keep this functioning during Shutdown
|
||||
if (NS_WARN_IF(!mMainThread)) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
if (NS_WARN_IF(!aThread)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
RefPtr<nsThread> temp;
|
||||
{
|
||||
OffTheBooksMutexAutoLock lock(mLock);
|
||||
mThreadsByPRThread.Get(aThread, getter_AddRefs(temp));
|
||||
}
|
||||
|
||||
NS_IF_ADDREF(*aResult = temp);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsThreadManager::GetMainThread(nsIThread** aResult)
|
||||
{
|
||||
|
@ -605,7 +659,8 @@ nsThreadManager::GetSystemGroupEventTarget(nsIEventTarget** aTarget)
|
|||
uint32_t
|
||||
nsThreadManager::GetHighestNumberOfThreads()
|
||||
{
|
||||
return nsThread::MaxActiveThreads();
|
||||
OffTheBooksMutexAutoLock lock(mLock);
|
||||
return mHighestNumberOfThreads;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "nsIThreadManager.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "nsThread.h"
|
||||
|
||||
class nsIRunnable;
|
||||
|
@ -35,7 +36,7 @@ public:
|
|||
|
||||
// Called by nsThread to inform the ThreadManager it is going away. This
|
||||
// method must be called when the given thread is the current thread.
|
||||
void UnregisterCurrentThread(nsThread& aThread);
|
||||
void UnregisterCurrentThread(nsThread& aThread, bool aIfExists = false);
|
||||
|
||||
// Returns the current thread. Returns null if OOM or if ThreadManager isn't
|
||||
// initialized. Creates the nsThread if one does not exist yet.
|
||||
|
@ -73,7 +74,10 @@ private:
|
|||
nsThreadManager()
|
||||
: mCurThreadIndex(0)
|
||||
, mMainPRThread(nullptr)
|
||||
, mLock("nsThreadManager.mLock")
|
||||
, mInitialized(false)
|
||||
, mCurrentNumberOfThreads(1)
|
||||
, mHighestNumberOfThreads(1)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -83,12 +87,19 @@ private:
|
|||
|
||||
static void ReleaseThread(void* aData);
|
||||
|
||||
nsRefPtrHashtable<nsPtrHashKey<PRThread>, nsThread> mThreadsByPRThread;
|
||||
unsigned mCurThreadIndex; // thread-local-storage index
|
||||
RefPtr<nsThread> mMainThread;
|
||||
PRThread* mMainPRThread;
|
||||
mozilla::OffTheBooksMutex mLock; // protects tables
|
||||
mozilla::Atomic<bool,
|
||||
mozilla::SequentiallyConsistent,
|
||||
mozilla::recordreplay::Behavior::DontPreserve> mInitialized;
|
||||
|
||||
// The current number of threads
|
||||
uint32_t mCurrentNumberOfThreads;
|
||||
// The highest number of threads encountered so far during the session
|
||||
uint32_t mHighestNumberOfThreads;
|
||||
};
|
||||
|
||||
#define NS_THREADMANAGER_CID \
|
||||
|
|
Загрузка…
Ссылка в новой задаче