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:
Noemi Erli 2018-09-26 08:54:03 +03:00
Родитель 5e0fc81391
Коммит 36cc0e5fa7
14 изменённых файлов: 156 добавлений и 191 удалений

Просмотреть файл

@ -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(&current);
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 \