Bug 1310880 - Allow a BackgroundHangMonitor to have its own private BackgroundHangThread. r=jchen

MozReview-Commit-ID: L32E19FVhv

--HG--
extra : rebase_source : ad279f8a04e2e33a8b37e15674263aa7a1a0efbf
extra : histedit_source : 9f085995ec8d39014a45ab06fb366fb52eb57c6c
This commit is contained in:
Mike Conley 2016-10-19 14:32:43 -04:00
Родитель 7481809d32
Коммит f2fa591912
2 изменённых файлов: 55 добавлений и 13 удалений

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

@ -141,14 +141,24 @@ private:
// Unique thread ID for identification // Unique thread ID for identification
const PRThread* mThreadID; const PRThread* mThreadID;
void Update();
public: public:
NS_INLINE_DECL_REFCOUNTING(BackgroundHangThread) NS_INLINE_DECL_REFCOUNTING(BackgroundHangThread)
/**
* Returns the BackgroundHangThread associated with the
* running thread. Note that this will not find private
* BackgroundHangThread threads.
*
* @return BackgroundHangThread*, or nullptr if no thread
* is found.
*/
static BackgroundHangThread* FindThread(); static BackgroundHangThread* FindThread();
static void Startup() static void Startup()
{ {
/* We can tolerate init() failing. */ /* We can tolerate init() failing. */
(void)!sTlsKey.init(); sTlsKeyInitialized = sTlsKey.init();
} }
// Hang timeout in ticks // Hang timeout in ticks
@ -163,6 +173,8 @@ public:
bool mHanging; bool mHanging;
// Is the thread in a waiting state // Is the thread in a waiting state
bool mWaiting; bool mWaiting;
// Is the thread dedicated to a single BackgroundHangMonitor
BackgroundHangMonitor::ThreadType mThreadType;
// Platform-specific helper to get hang stacks // Platform-specific helper to get hang stacks
ThreadStackHelper mStackHelper; ThreadStackHelper mStackHelper;
// Stack of current hang // Stack of current hang
@ -176,20 +188,32 @@ public:
BackgroundHangThread(const char* aName, BackgroundHangThread(const char* aName,
uint32_t aTimeoutMs, uint32_t aTimeoutMs,
uint32_t aMaxTimeoutMs); uint32_t aMaxTimeoutMs,
BackgroundHangMonitor::ThreadType aThreadType = BackgroundHangMonitor::THREAD_SHARED);
// Report a hang; aManager->mLock IS locked // Report a hang; aManager->mLock IS locked
Telemetry::HangHistogram& ReportHang(PRIntervalTime aHangTime); Telemetry::HangHistogram& ReportHang(PRIntervalTime aHangTime);
// Report a permanent hang; aManager->mLock IS locked // Report a permanent hang; aManager->mLock IS locked
void ReportPermaHang(); void ReportPermaHang();
// Called by BackgroundHangMonitor::NotifyActivity // Called by BackgroundHangMonitor::NotifyActivity
void NotifyActivity(); void NotifyActivity()
{
MonitorAutoLock autoLock(mManager->mLock);
Update();
}
// Called by BackgroundHangMonitor::NotifyWait // Called by BackgroundHangMonitor::NotifyWait
void NotifyWait() void NotifyWait()
{ {
NotifyActivity(); MonitorAutoLock autoLock(mManager->mLock);
Update();
mWaiting = true; mWaiting = true;
} }
// Returns true if this thread is (or might be) shared between other
// BackgroundHangMonitors for the monitored thread.
bool IsShared() {
return mThreadType == BackgroundHangMonitor::THREAD_SHARED;
}
}; };
@ -347,7 +371,8 @@ BackgroundHangManager::RunMonitorThread()
BackgroundHangThread::BackgroundHangThread(const char* aName, BackgroundHangThread::BackgroundHangThread(const char* aName,
uint32_t aTimeoutMs, uint32_t aTimeoutMs,
uint32_t aMaxTimeoutMs) uint32_t aMaxTimeoutMs,
BackgroundHangMonitor::ThreadType aThreadType)
: mManager(BackgroundHangManager::sInstance) : mManager(BackgroundHangManager::sInstance)
, mThreadID(PR_GetCurrentThread()) , mThreadID(PR_GetCurrentThread())
, mTimeout(aTimeoutMs == BackgroundHangMonitor::kNoTimeout , mTimeout(aTimeoutMs == BackgroundHangMonitor::kNoTimeout
@ -360,9 +385,10 @@ BackgroundHangThread::BackgroundHangThread(const char* aName,
, mHangStart(mInterval) , mHangStart(mInterval)
, mHanging(false) , mHanging(false)
, mWaiting(true) , mWaiting(true)
, mThreadType(aThreadType)
, mStats(aName) , mStats(aName)
{ {
if (sTlsKeyInitialized) { if (sTlsKeyInitialized && IsShared()) {
sTlsKey.set(this); sTlsKey.set(this);
} }
// Lock here because LinkedList is not thread-safe // Lock here because LinkedList is not thread-safe
@ -383,7 +409,7 @@ BackgroundHangThread::~BackgroundHangThread()
autoLock.Notify(); autoLock.Notify();
// We no longer have a thread // We no longer have a thread
if (sTlsKeyInitialized) { if (sTlsKeyInitialized && IsShared()) {
sTlsKey.set(nullptr); sTlsKey.set(nullptr);
} }
@ -452,7 +478,7 @@ BackgroundHangThread::ReportPermaHang()
} }
MOZ_ALWAYS_INLINE void MOZ_ALWAYS_INLINE void
BackgroundHangThread::NotifyActivity() BackgroundHangThread::Update()
{ {
PRIntervalTime intervalNow = mManager->mIntervalNow; PRIntervalTime intervalNow = mManager->mIntervalNow;
if (mWaiting) { if (mWaiting) {
@ -495,7 +521,7 @@ BackgroundHangThread::FindThread()
MonitorAutoLock autoLock(manager->mLock); MonitorAutoLock autoLock(manager->mLock);
for (BackgroundHangThread* thread = manager->mHangThreads.getFirst(); for (BackgroundHangThread* thread = manager->mHangThreads.getFirst();
thread; thread = thread->getNext()) { thread; thread = thread->getNext()) {
if (thread->mThreadID == threadID) { if (thread->mThreadID == threadID && thread->IsShared()) {
return thread; return thread;
} }
} }
@ -587,12 +613,14 @@ BackgroundHangMonitor::Shutdown()
BackgroundHangMonitor::BackgroundHangMonitor(const char* aName, BackgroundHangMonitor::BackgroundHangMonitor(const char* aName,
uint32_t aTimeoutMs, uint32_t aTimeoutMs,
uint32_t aMaxTimeoutMs) uint32_t aMaxTimeoutMs,
: mThread(BackgroundHangThread::FindThread()) ThreadType aThreadType)
: mThread(aThreadType == THREAD_SHARED ? BackgroundHangThread::FindThread() : nullptr)
{ {
#ifdef MOZ_ENABLE_BACKGROUND_HANG_MONITOR #ifdef MOZ_ENABLE_BACKGROUND_HANG_MONITOR
if (!BackgroundHangManager::sDisabled && !mThread) { if (!BackgroundHangManager::sDisabled && !mThread) {
mThread = new BackgroundHangThread(aName, aTimeoutMs, aMaxTimeoutMs); mThread = new BackgroundHangThread(aName, aTimeoutMs, aMaxTimeoutMs,
aThreadType);
} }
#endif #endif
} }

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

@ -116,6 +116,16 @@ private:
public: public:
static const uint32_t kNoTimeout = 0; static const uint32_t kNoTimeout = 0;
enum ThreadType {
// For a new BackgroundHangMonitor for thread T, only create a new
// monitoring thread for T if one doesn't already exist. If one does,
// share that pre-existing monitoring thread.
THREAD_SHARED,
// For a new BackgroundHangMonitor for thread T, create a new
// monitoring thread for T even if there are other, pre-existing
// monitoring threads for T.
THREAD_PRIVATE
};
/** /**
* ThreadHangStatsIterator is used to iterate through the ThreadHangStats * ThreadHangStatsIterator is used to iterate through the ThreadHangStats
@ -180,10 +190,14 @@ public:
* activity before registering a hang * activity before registering a hang
* @param aMaxTimeoutMs Amount of time in milliseconds without * @param aMaxTimeoutMs Amount of time in milliseconds without
* activity before registering a permanent hang * activity before registering a permanent hang
* @param aThreadType
* The ThreadType type of monitoring thread that should be created
* for this monitor. See the documentation for ThreadType.
*/ */
BackgroundHangMonitor(const char* aName, BackgroundHangMonitor(const char* aName,
uint32_t aTimeoutMs, uint32_t aTimeoutMs,
uint32_t aMaxTimeoutMs); uint32_t aMaxTimeoutMs,
ThreadType aThreadType = THREAD_SHARED);
/** /**
* Monitor hangs using an existing monitor * Monitor hangs using an existing monitor