Bug 932865 - Add way for telemetry to iterate over active threads; r=froydnj

This commit is contained in:
Jim Chen 2013-11-22 14:17:31 -05:00
parent 8a6972b958
commit 4b4ea979e2
2 changed files with 68 additions and 3 deletions

View File

@ -7,6 +7,7 @@
#include "mozilla/LinkedList.h" #include "mozilla/LinkedList.h"
#include "mozilla/Monitor.h" #include "mozilla/Monitor.h"
#include "mozilla/StaticPtr.h" #include "mozilla/StaticPtr.h"
#include "mozilla/ThreadHangStats.h"
#include "mozilla/ThreadLocal.h" #include "mozilla/ThreadLocal.h"
#include "prinrval.h" #include "prinrval.h"
@ -103,8 +104,6 @@ public:
if (!sTlsKey.init()) {} if (!sTlsKey.init()) {}
} }
// Name of the thread
const nsAutoCString mThreadName;
// Hang timeout in ticks // Hang timeout in ticks
const PRIntervalTime mTimeout; const PRIntervalTime mTimeout;
// PermaHang timeout in ticks // PermaHang timeout in ticks
@ -117,6 +116,8 @@ public:
bool mHanging; bool mHanging;
// Is the thread in a waiting state // Is the thread in a waiting state
bool mWaiting; bool mWaiting;
// Statistics for telemetry
Telemetry::ThreadHangStats mStats;
BackgroundHangThread(const char* aName, BackgroundHangThread(const char* aName,
uint32_t aTimeoutMs, uint32_t aTimeoutMs,
@ -292,13 +293,13 @@ BackgroundHangThread::BackgroundHangThread(const char* aName,
uint32_t aMaxTimeoutMs) uint32_t aMaxTimeoutMs)
: mManager(BackgroundHangManager::sInstance) : mManager(BackgroundHangManager::sInstance)
, mThreadID(PR_GetCurrentThread()) , mThreadID(PR_GetCurrentThread())
, mThreadName(aName)
, mTimeout(PR_MillisecondsToInterval(aTimeoutMs)) , mTimeout(PR_MillisecondsToInterval(aTimeoutMs))
, mMaxTimeout(PR_MillisecondsToInterval(aMaxTimeoutMs)) , mMaxTimeout(PR_MillisecondsToInterval(aMaxTimeoutMs))
, mInterval(mManager->mIntervalNow) , mInterval(mManager->mIntervalNow)
, mHangStart(mInterval) , mHangStart(mInterval)
, mHanging(false) , mHanging(false)
, mWaiting(true) , mWaiting(true)
, mStats(aName)
{ {
if (sTlsKey.initialized()) { if (sTlsKey.initialized()) {
sTlsKey.set(this); sTlsKey.set(this);
@ -440,4 +441,25 @@ BackgroundHangMonitor::NotifyWait()
mThread->NotifyWait(); mThread->NotifyWait();
} }
/* Because we are iterating through the BackgroundHangThread linked list,
we need to take a lock. Using MonitorAutoLock as a base class makes
sure all of that is taken care of for us. */
BackgroundHangMonitor::ThreadHangStatsIterator::ThreadHangStatsIterator()
: MonitorAutoLock(BackgroundHangManager::sInstance->mLock)
, mThread(BackgroundHangManager::sInstance->mHangThreads.getFirst())
{
}
Telemetry::ThreadHangStats*
BackgroundHangMonitor::ThreadHangStatsIterator::GetNext()
{
if (!mThread) {
return nullptr;
}
Telemetry::ThreadHangStats* stats = &mThread->mStats;
mThread = mThread->getNext();
return stats;
}
} // namespace mozilla } // namespace mozilla

View File

@ -7,11 +7,16 @@
#define mozilla_BackgroundHangMonitor_h #define mozilla_BackgroundHangMonitor_h
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"
#include "mozilla/Monitor.h"
#include <stdint.h> #include <stdint.h>
namespace mozilla { namespace mozilla {
namespace Telemetry {
class ThreadHangStats;
};
class BackgroundHangThread; class BackgroundHangThread;
/** /**
@ -101,6 +106,44 @@ private:
RefPtr<BackgroundHangThread> mThread; RefPtr<BackgroundHangThread> mThread;
public: public:
/**
* ThreadHangStatsIterator is used to iterate through the ThreadHangStats
* associated with each active monitored thread. Because of an internal
* lock while this object is alive, a thread must use only one instance
* of this class at a time and must iterate through the list as fast as
* possible. The following example shows using the iterator:
*
* {
* // Scope the iter variable so it's destroyed as soon as we're done
* BackgroundHangMonitor::ThreadHangStatsIterator iter;
* for (ThreadHangStats* histogram = iter.GetNext();
* histogram; histogram = iter.GetNext()) {
* // Process histogram
* }
* }
*/
class ThreadHangStatsIterator : public MonitorAutoLock
{
private:
BackgroundHangThread* mThread;
ThreadHangStatsIterator(const ThreadHangStatsIterator&);
ThreadHangStatsIterator& operator=(const ThreadHangStatsIterator&);
public:
/**
* Create an ThreadHangStatsIterator instance and take the internal lock.
* Internal lock is released on destruction.
*/
ThreadHangStatsIterator();
/**
* Get the next item in the list; the first call returns the first item.
* Returns nullptr at the end of the list.
*/
Telemetry::ThreadHangStats* GetNext();
};
/** /**
* Enable hang monitoring. * Enable hang monitoring.
* Must return before using BackgroundHangMonitor. * Must return before using BackgroundHangMonitor.