Bug 1323100 - Add nsThreadManager::NewNamedThread API. r=froydnj

The point of this exercise is to make the thread name available in the thread
func of the thread, so that we can register the thread with the profiler from
the very start of its lifetime, and so that registration and unregistration
can be inside the same function.

MozReview-Commit-ID: DiiMKUQVr55

--HG--
extra : rebase_source : 24b15d56315ad49e72b3e9b76db7fb634f3bfe01
This commit is contained in:
Markus Stange 2016-12-20 15:10:20 +01:00
Родитель 45941e71bc
Коммит 8924022f9d
4 изменённых файлов: 48 добавлений и 6 удалений

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

@ -35,6 +35,20 @@ interface nsIThreadManager : nsISupports
*/
nsIThread newThread(in unsigned long creationFlags, [optional] in unsigned long stackSize);
/**
* Create a new thread (a global, user PRThread) with the specified name.
*
* @param name
* The name of the thread. Passing an empty name is equivalent to
* calling newThread(0, stackSize), i.e. the thread will not be named.
* @param stackSize
* Number of bytes to reserve for the thread's stack.
*
* @returns
* The newly created nsIThread object.
*/
[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.

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

@ -432,15 +432,30 @@ SetupCurrentThreadForChaosMode()
}
}
namespace {
struct ThreadInitData {
nsThread* thread;
const nsACString& name;
};
}
/*static*/ void
nsThread::ThreadFunc(void* aArg)
{
using mozilla::ipc::BackgroundChild;
nsThread* self = static_cast<nsThread*>(aArg); // strong reference
ThreadInitData* initData = static_cast<ThreadInitData*>(aArg);
nsThread* self = initData->thread; // strong reference
self->mThread = PR_GetCurrentThread();
SetupCurrentThreadForChaosMode();
if (initData->name.Length() > 0) {
PR_SetCurrentThreadName(initData->name.BeginReading());
}
// Inform the ThreadManager
nsThreadManager::get().RegisterCurrentThread(*self);
@ -455,6 +470,9 @@ nsThread::ThreadFunc(void* aArg)
return;
}
}
initData = nullptr; // clear before unblocking nsThread::Init
event->Run(); // unblocks nsThread::Init
event = nullptr;
@ -628,7 +646,7 @@ nsThread::~nsThread()
}
nsresult
nsThread::Init()
nsThread::Init(const nsACString& aName)
{
// spawn thread and wait until it is fully setup
RefPtr<nsThreadStartupEvent> startup = new nsThreadStartupEvent();
@ -639,8 +657,10 @@ nsThread::Init()
mShutdownRequired = true;
ThreadInitData initData = { this, aName };
// ThreadFunc is responsible for setting mThread
if (!PR_CreateThread(PR_USER_THREAD, ThreadFunc, this,
if (!PR_CreateThread(PR_USER_THREAD, ThreadFunc, &initData,
PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
PR_JOINABLE_THREAD, mStackSize)) {
NS_RELEASE_THIS();

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

@ -48,8 +48,8 @@ public:
nsThread(MainThreadFlag aMainThread, uint32_t aStackSize);
// Initialize this as a wrapper for a new PRThread.
nsresult Init();
// Initialize this as a wrapper for a new PRThread, and optionally give it a name.
nsresult Init(const nsACString& aName = NS_LITERAL_CSTRING(""));
// Initialize this as a wrapper for the current PRThread.
nsresult InitCurrentThread();

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

@ -248,6 +248,14 @@ NS_IMETHODIMP
nsThreadManager::NewThread(uint32_t aCreationFlags,
uint32_t aStackSize,
nsIThread** aResult)
{
return NewNamedThread(NS_LITERAL_CSTRING(""), aStackSize, aResult);
}
NS_IMETHODIMP
nsThreadManager::NewNamedThread(const nsACString& aName,
uint32_t aStackSize,
nsIThread** aResult)
{
// Note: can be called from arbitrary threads
@ -257,7 +265,7 @@ nsThreadManager::NewThread(uint32_t aCreationFlags,
}
RefPtr<nsThread> thr = new nsThread(nsThread::NOT_MAIN_THREAD, aStackSize);
nsresult rv = thr->Init(); // Note: blocks until the new thread has been set up
nsresult rv = thr->Init(aName); // Note: blocks until the new thread has been set up
if (NS_FAILED(rv)) {
return rv;
}