Commit 2b730331 authored by Olivier Li's avatar Olivier Li Committed by Commit Bot

Allow tagging of thread type in HangWatcher

This is a change in preparation of logging hang count histograms per
thread type.

Bug: 1135528
Change-Id: I96dc1e114ac170f5ff9a32eedd57dd19ea97b152
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2505451
Commit-Queue: Oliver Li <olivierli@chromium.org>
Reviewed-by: default avatarAvi Drissman <avi@chromium.org>
Reviewed-by: default avatarFrançois Doray <fdoray@chromium.org>
Cr-Commit-Position: refs/heads/master@{#821988}
parent 08b5b929
...@@ -311,7 +311,8 @@ void WorkerThread::RunWorker() { ...@@ -311,7 +311,8 @@ void WorkerThread::RunWorker() {
base::ScopedClosureRunner unregister_for_hang_watching; base::ScopedClosureRunner unregister_for_hang_watching;
if (watch_for_hangs) { if (watch_for_hangs) {
unregister_for_hang_watching = unregister_for_hang_watching =
base::HangWatcher::GetInstance()->RegisterThread(); base::HangWatcher::GetInstance()->RegisterThread(
base::HangWatcher::ThreadType::kThreadPoolThread);
} }
// A WorkerThread starts out waiting for work. // A WorkerThread starts out waiting for work.
......
...@@ -399,11 +399,12 @@ void HangWatcher::RecordHang() { ...@@ -399,11 +399,12 @@ void HangWatcher::RecordHang() {
base::debug::Alias(&line_number); base::debug::Alias(&line_number);
} }
ScopedClosureRunner HangWatcher::RegisterThread() { ScopedClosureRunner HangWatcher::RegisterThread(ThreadType thread_type) {
AutoLock auto_lock(watch_state_lock_); AutoLock auto_lock(watch_state_lock_);
watch_states_.push_back( watch_states_.push_back(
internal::HangWatchState::CreateHangWatchStateForCurrentThread()); internal::HangWatchState::CreateHangWatchStateForCurrentThread(
thread_type));
return ScopedClosureRunner(BindOnce(&HangWatcher::UnregisterThread, return ScopedClosureRunner(BindOnce(&HangWatcher::UnregisterThread,
Unretained(HangWatcher::GetInstance()))); Unretained(HangWatcher::GetInstance())));
...@@ -840,7 +841,8 @@ uint64_t HangWatchDeadline::SwitchBitsForTesting() { ...@@ -840,7 +841,8 @@ uint64_t HangWatchDeadline::SwitchBitsForTesting() {
return switched_in_bits; return switched_in_bits;
} }
HangWatchState::HangWatchState() : thread_id_(PlatformThread::CurrentId()) { HangWatchState::HangWatchState(HangWatcher::ThreadType thread_type)
: thread_id_(PlatformThread::CurrentId()), thread_type_(thread_type) {
// There should not exist a state object for this thread already. // There should not exist a state object for this thread already.
DCHECK(!GetHangWatchStateForCurrentThread()->Get()); DCHECK(!GetHangWatchStateForCurrentThread()->Get());
...@@ -863,11 +865,11 @@ HangWatchState::~HangWatchState() { ...@@ -863,11 +865,11 @@ HangWatchState::~HangWatchState() {
// static // static
std::unique_ptr<HangWatchState> std::unique_ptr<HangWatchState>
HangWatchState::CreateHangWatchStateForCurrentThread() { HangWatchState::CreateHangWatchStateForCurrentThread(
HangWatcher::ThreadType thread_type) {
// Allocate a watch state object for this thread. // Allocate a watch state object for this thread.
std::unique_ptr<HangWatchState> hang_state = std::unique_ptr<HangWatchState> hang_state =
std::make_unique<HangWatchState>(); std::make_unique<HangWatchState>(thread_type);
// Setting the thread local worked. // Setting the thread local worked.
DCHECK_EQ(GetHangWatchStateForCurrentThread()->Get(), hang_state.get()); DCHECK_EQ(GetHangWatchStateForCurrentThread()->Get(), hang_state.get());
......
...@@ -136,6 +136,13 @@ class BASE_EXPORT HangWatchScopeDisabled { ...@@ -136,6 +136,13 @@ class BASE_EXPORT HangWatchScopeDisabled {
// within a single process. This instance must outlive all monitored threads. // within a single process. This instance must outlive all monitored threads.
class BASE_EXPORT HangWatcher : public DelegateSimpleThread::Delegate { class BASE_EXPORT HangWatcher : public DelegateSimpleThread::Delegate {
public: public:
// Describes the type of a thread for logging purposes.
enum class ThreadType {
kIOThread = 0,
kUIThread = 1,
kThreadPoolThread = 2,
kThreadForTesting = 3
};
// The first invocation of the constructor will set the global instance // The first invocation of the constructor will set the global instance
// accessible through GetInstance(). This means that only one instance can // accessible through GetInstance(). This means that only one instance can
...@@ -165,7 +172,7 @@ class BASE_EXPORT HangWatcher : public DelegateSimpleThread::Delegate { ...@@ -165,7 +172,7 @@ class BASE_EXPORT HangWatcher : public DelegateSimpleThread::Delegate {
// Sets up the calling thread to be monitored for threads. Returns a // Sets up the calling thread to be monitored for threads. Returns a
// ScopedClosureRunner that unregisters the thread. This closure has to be // ScopedClosureRunner that unregisters the thread. This closure has to be
// called from the registered thread before it's joined. // called from the registered thread before it's joined.
ScopedClosureRunner RegisterThread() ScopedClosureRunner RegisterThread(ThreadType thread_type)
LOCKS_EXCLUDED(watch_state_lock_) WARN_UNUSED_RESULT; LOCKS_EXCLUDED(watch_state_lock_) WARN_UNUSED_RESULT;
// Choose a closure to be run at the end of each call to Monitor(). Use only // Choose a closure to be run at the end of each call to Monitor(). Use only
...@@ -512,7 +519,10 @@ class BASE_EXPORT HangWatchDeadline { ...@@ -512,7 +519,10 @@ class BASE_EXPORT HangWatchDeadline {
// GetHangWatchStateForCurrentThread(). // GetHangWatchStateForCurrentThread().
class BASE_EXPORT HangWatchState { class BASE_EXPORT HangWatchState {
public: public:
HangWatchState(); // |thread_type| is the type of thread the watch state will
// be associated with. It's the responsibility of the creating
// code to choose the correct type.
explicit HangWatchState(HangWatcher::ThreadType thread_type);
~HangWatchState(); ~HangWatchState();
HangWatchState(const HangWatchState&) = delete; HangWatchState(const HangWatchState&) = delete;
...@@ -520,7 +530,8 @@ class BASE_EXPORT HangWatchState { ...@@ -520,7 +530,8 @@ class BASE_EXPORT HangWatchState {
// Allocates a new state object bound to the calling thread and returns an // Allocates a new state object bound to the calling thread and returns an
// owning pointer to it. // owning pointer to it.
static std::unique_ptr<HangWatchState> CreateHangWatchStateForCurrentThread(); static std::unique_ptr<HangWatchState> CreateHangWatchStateForCurrentThread(
HangWatcher::ThreadType thread_type);
// Retrieves the hang watch state associated with the calling thread. // Retrieves the hang watch state associated with the calling thread.
// Returns nullptr if no HangWatchState exists for the current thread (see // Returns nullptr if no HangWatchState exists for the current thread (see
...@@ -594,6 +605,9 @@ class BASE_EXPORT HangWatchState { ...@@ -594,6 +605,9 @@ class BASE_EXPORT HangWatchState {
// Reduce the nesting level by 1; // Reduce the nesting level by 1;
void DecrementNestingLevel(); void DecrementNestingLevel();
// Returns the type of the thread under watch.
HangWatcher::ThreadType thread_type() const { return thread_type_; }
private: private:
// The thread that creates the instance should be the class that updates // The thread that creates the instance should be the class that updates
// the deadline. // the deadline.
...@@ -608,6 +622,9 @@ class BASE_EXPORT HangWatchState { ...@@ -608,6 +622,9 @@ class BASE_EXPORT HangWatchState {
// Number of active HangWatchScopeEnables on this thread. // Number of active HangWatchScopeEnables on this thread.
int nesting_level_ = 0; int nesting_level_ = 0;
// The type of the thread under watch.
const HangWatcher::ThreadType thread_type_;
#if DCHECK_IS_ON() #if DCHECK_IS_ON()
// Used to keep track of the current HangWatchScopeEnabled and detect improper // Used to keep track of the current HangWatchScopeEnabled and detect improper
// usage. Scopes should always be destructed in reverse order from the one // usage. Scopes should always be destructed in reverse order from the one
......
...@@ -56,7 +56,8 @@ class BlockingThread : public DelegateSimpleThread::Delegate { ...@@ -56,7 +56,8 @@ class BlockingThread : public DelegateSimpleThread::Delegate {
// (Un)Register the thread here instead of in ctor/dtor so that the action // (Un)Register the thread here instead of in ctor/dtor so that the action
// happens on the right thread. // happens on the right thread.
base::ScopedClosureRunner unregister_closure = base::ScopedClosureRunner unregister_closure =
base::HangWatcher::GetInstance()->RegisterThread(); base::HangWatcher::GetInstance()->RegisterThread(
base::HangWatcher::ThreadType::kThreadForTesting);
HangWatchScopeEnabled scope(timeout_); HangWatchScopeEnabled scope(timeout_);
wait_until_entered_scope_.Signal(); wait_until_entered_scope_.Signal();
...@@ -189,7 +190,8 @@ TEST_F( ...@@ -189,7 +190,8 @@ TEST_F(
HangWatcherTest, HangWatcherTest,
ScopeDisabledCreateScopeDisabledDestroyScopeEnabledCreateScopeEnabledDestroy) { ScopeDisabledCreateScopeDisabledDestroyScopeEnabledCreateScopeEnabledDestroy) {
// Register the main test thread for hang watching. // Register the main test thread for hang watching.
auto unregister_thread_closure = hang_watcher_.RegisterThread(); auto unregister_thread_closure = hang_watcher_.RegisterThread(
base::HangWatcher::ThreadType::kThreadForTesting);
{ {
HangWatchScopeEnabled expires_instantly(base::TimeDelta{}); HangWatchScopeEnabled expires_instantly(base::TimeDelta{});
...@@ -216,7 +218,8 @@ TEST_F( ...@@ -216,7 +218,8 @@ TEST_F(
HangWatcherTest, HangWatcherTest,
ScopeEnabledCreateScopeDisabledCreateScopeEnabledDestroyScopeDisabledDestroy) { ScopeEnabledCreateScopeDisabledCreateScopeEnabledDestroyScopeDisabledDestroy) {
// Register the main test thread for hang watching. // Register the main test thread for hang watching.
auto unregister_thread_closure = hang_watcher_.RegisterThread(); auto unregister_thread_closure = hang_watcher_.RegisterThread(
base::HangWatcher::ThreadType::kThreadForTesting);
base::Optional<HangWatchScopeDisabled> disabler; base::Optional<HangWatchScopeDisabled> disabler;
...@@ -245,7 +248,8 @@ TEST_F( ...@@ -245,7 +248,8 @@ TEST_F(
HangWatcherTest, HangWatcherTest,
ScopeDisabledCreateScopeEnabledCreateScopeDisabledDestroyScopeEnabledDestroy) { ScopeDisabledCreateScopeEnabledCreateScopeDisabledDestroyScopeEnabledDestroy) {
// Register the main test thread for hang watching. // Register the main test thread for hang watching.
auto unregister_thread_closure = hang_watcher_.RegisterThread(); auto unregister_thread_closure = hang_watcher_.RegisterThread(
base::HangWatcher::ThreadType::kThreadForTesting);
base::Optional<HangWatchScopeDisabled> disabler; base::Optional<HangWatchScopeDisabled> disabler;
...@@ -274,7 +278,8 @@ TEST_F( ...@@ -274,7 +278,8 @@ TEST_F(
HangWatcherTest, HangWatcherTest,
ScopeDisabledCreateScopeEnabledCreateScopeEnabledDestroyScopeDisabledDestroy) { ScopeDisabledCreateScopeEnabledCreateScopeEnabledDestroyScopeDisabledDestroy) {
// Register the main test thread for hang watching. // Register the main test thread for hang watching.
auto unregister_thread_closure = hang_watcher_.RegisterThread(); auto unregister_thread_closure = hang_watcher_.RegisterThread(
base::HangWatcher::ThreadType::kThreadForTesting);
// De-activate hang watching, // De-activate hang watching,
HangWatchScopeDisabled disabler; HangWatchScopeDisabled disabler;
...@@ -295,7 +300,8 @@ TEST_F( ...@@ -295,7 +300,8 @@ TEST_F(
TEST_F(HangWatcherTest, ScopeCreateTempCreateTempDestroyScopeDestroy) { TEST_F(HangWatcherTest, ScopeCreateTempCreateTempDestroyScopeDestroy) {
// Register the main test thread for hang watching. // Register the main test thread for hang watching.
auto unregister_thread_closure = hang_watcher_.RegisterThread(); auto unregister_thread_closure = hang_watcher_.RegisterThread(
base::HangWatcher::ThreadType::kThreadForTesting);
{ {
// Start a HangWatchScopeEnabled that expires right away. Then advance // Start a HangWatchScopeEnabled that expires right away. Then advance
// time to make sure a hang is detected. // time to make sure a hang is detected.
...@@ -320,7 +326,8 @@ TEST_F( ...@@ -320,7 +326,8 @@ TEST_F(
HangWatcherTest, HangWatcherTest,
ScopeEnabledCreateScopeDisabledCreateScopeDisabledDestroyScopeEnabledDestroy) { ScopeEnabledCreateScopeDisabledCreateScopeDisabledDestroyScopeEnabledDestroy) {
// Register the main test thread for hang watching. // Register the main test thread for hang watching.
auto unregister_thread_closure = hang_watcher_.RegisterThread(); auto unregister_thread_closure = hang_watcher_.RegisterThread(
base::HangWatcher::ThreadType::kThreadForTesting);
{ {
// Start a HangWatchScopeEnabled that expires right away. Then advance // Start a HangWatchScopeEnabled that expires right away. Then advance
// time to make sure a hang is detected. // time to make sure a hang is detected.
...@@ -343,7 +350,8 @@ TEST_F( ...@@ -343,7 +350,8 @@ TEST_F(
// detection in outer scopes. // detection in outer scopes.
TEST_F(HangWatcherTest, ScopeDisabledObjectInnerScope) { TEST_F(HangWatcherTest, ScopeDisabledObjectInnerScope) {
// Register the main test thread for hang watching. // Register the main test thread for hang watching.
auto unregister_thread_closure = hang_watcher_.RegisterThread(); auto unregister_thread_closure = hang_watcher_.RegisterThread(
base::HangWatcher::ThreadType::kThreadForTesting);
// Start a HangWatchScopeEnabled that expires right away. Then advance // Start a HangWatchScopeEnabled that expires right away. Then advance
// time to make sure a hang is detected. // time to make sure a hang is detected.
...@@ -370,7 +378,8 @@ TEST_F(HangWatcherTest, ScopeDisabledObjectInnerScope) { ...@@ -370,7 +378,8 @@ TEST_F(HangWatcherTest, ScopeDisabledObjectInnerScope) {
TEST_F(HangWatcherTest, NewScopeAfterDisabling) { TEST_F(HangWatcherTest, NewScopeAfterDisabling) {
// Register the main test thread for hang watching. // Register the main test thread for hang watching.
auto unregister_thread_closure = hang_watcher_.RegisterThread(); auto unregister_thread_closure = hang_watcher_.RegisterThread(
base::HangWatcher::ThreadType::kThreadForTesting);
// Start a HangWatchScopeEnabled that expires right away. Then advance // Start a HangWatchScopeEnabled that expires right away. Then advance
// time to make sure a hang is detected. // time to make sure a hang is detected.
...@@ -401,7 +410,8 @@ TEST_F(HangWatcherTest, NestedScopes) { ...@@ -401,7 +410,8 @@ TEST_F(HangWatcherTest, NestedScopes) {
// Create a state object for the test thread since this test is single // Create a state object for the test thread since this test is single
// threaded. // threaded.
auto current_hang_watch_state = auto current_hang_watch_state =
base::internal::HangWatchState::CreateHangWatchStateForCurrentThread(); base::internal::HangWatchState::CreateHangWatchStateForCurrentThread(
HangWatcher::ThreadType::kThreadForTesting);
ASSERT_FALSE(current_hang_watch_state->IsOverDeadline()); ASSERT_FALSE(current_hang_watch_state->IsOverDeadline());
base::TimeTicks original_deadline = current_hang_watch_state->GetDeadline(); base::TimeTicks original_deadline = current_hang_watch_state->GetDeadline();
...@@ -540,7 +550,8 @@ TEST_F(HangWatcherSnapshotTest, NonActionableReport) { ...@@ -540,7 +550,8 @@ TEST_F(HangWatcherSnapshotTest, NonActionableReport) {
hang_watcher_.Start(); hang_watcher_.Start();
// Register the main test thread for hang watching. // Register the main test thread for hang watching.
auto unregister_thread_closure = hang_watcher_.RegisterThread(); auto unregister_thread_closure = hang_watcher_.RegisterThread(
base::HangWatcher::ThreadType::kThreadForTesting);
{ {
// Start a HangWatchScopeEnabled that expires right away. Ensures that // Start a HangWatchScopeEnabled that expires right away. Ensures that
// the first monitor will detect a hang. // the first monitor will detect a hang.
...@@ -587,7 +598,8 @@ TEST_F(HangWatcherSnapshotTest, DISABLED_HungThreadIDs) { ...@@ -587,7 +598,8 @@ TEST_F(HangWatcherSnapshotTest, DISABLED_HungThreadIDs) {
hang_watcher_.Start(); hang_watcher_.Start();
// Register the main test thread for hang watching. // Register the main test thread for hang watching.
auto unregister_thread_closure = hang_watcher_.RegisterThread(); auto unregister_thread_closure = hang_watcher_.RegisterThread(
base::HangWatcher::ThreadType::kThreadForTesting);
BlockingThread blocking_thread(&monitor_event_, base::TimeDelta{}); BlockingThread blocking_thread(&monitor_event_, base::TimeDelta{});
blocking_thread.StartAndWaitForScopeEntered(); blocking_thread.StartAndWaitForScopeEntered();
...@@ -741,7 +753,8 @@ TEST_F(HangWatcherPeriodicMonitoringTest, PeriodicCallsTakePlace) { ...@@ -741,7 +753,8 @@ TEST_F(HangWatcherPeriodicMonitoringTest, PeriodicCallsTakePlace) {
hang_watcher_.Start(); hang_watcher_.Start();
// Register a thread, // Register a thread,
unregister_thread_closure_ = hang_watcher_.RegisterThread(); unregister_thread_closure_ = hang_watcher_.RegisterThread(
base::HangWatcher::ThreadType::kThreadForTesting);
run_loop.Run(); run_loop.Run();
...@@ -769,7 +782,8 @@ TEST_F(HangWatcherPeriodicMonitoringTest, NoMonitorOnOverSleep) { ...@@ -769,7 +782,8 @@ TEST_F(HangWatcherPeriodicMonitoringTest, NoMonitorOnOverSleep) {
hang_watcher_.Start(); hang_watcher_.Start();
// Register a thread. // Register a thread.
unregister_thread_closure_ = hang_watcher_.RegisterThread(); unregister_thread_closure_ = hang_watcher_.RegisterThread(
base::HangWatcher::ThreadType::kThreadForTesting);
// Unblock the test thread. All waits were perceived as oversleeping so all // Unblock the test thread. All waits were perceived as oversleeping so all
// monitoring was inhibited. // monitoring was inhibited.
...@@ -809,7 +823,8 @@ class HangWatchScopeEnabledBlockingTest : public testing::Test { ...@@ -809,7 +823,8 @@ class HangWatchScopeEnabledBlockingTest : public testing::Test {
hang_watcher_.Start(); hang_watcher_.Start();
// Register the test main thread for hang watching. // Register the test main thread for hang watching.
unregister_thread_closure_ = hang_watcher_.RegisterThread(); unregister_thread_closure_ = hang_watcher_.RegisterThread(
base::HangWatcher::ThreadType::kThreadForTesting);
} }
HangWatchScopeEnabledBlockingTest( HangWatchScopeEnabledBlockingTest(
......
...@@ -531,7 +531,8 @@ BrowserMainLoop::BrowserMainLoop( ...@@ -531,7 +531,8 @@ BrowserMainLoop::BrowserMainLoop(
// that makes it the same as the current one. // that makes it the same as the current one.
if (base::HangWatcher::IsUIThreadHangWatchingEnabled()) { if (base::HangWatcher::IsUIThreadHangWatchingEnabled()) {
unregister_thread_closure_ = unregister_thread_closure_ =
base::HangWatcher::GetInstance()->RegisterThread(); base::HangWatcher::GetInstance()->RegisterThread(
base::HangWatcher::ThreadType::kUIThread);
} }
if (GetContentClient()->browser()->ShouldCreateThreadPool()) { if (GetContentClient()->browser()->ShouldCreateThreadPool()) {
......
...@@ -137,7 +137,8 @@ NOINLINE void BrowserProcessSubThread::IOThreadRun(base::RunLoop* run_loop) { ...@@ -137,7 +137,8 @@ NOINLINE void BrowserProcessSubThread::IOThreadRun(base::RunLoop* run_loop) {
base::ScopedClosureRunner unregister_thread_closure; base::ScopedClosureRunner unregister_thread_closure;
if (base::HangWatcher::IsIOThreadHangWatchingEnabled()) { if (base::HangWatcher::IsIOThreadHangWatchingEnabled()) {
unregister_thread_closure = unregister_thread_closure =
base::HangWatcher::GetInstance()->RegisterThread(); base::HangWatcher::GetInstance()->RegisterThread(
base::HangWatcher::ThreadType::kIOThread);
} }
Thread::Run(run_loop); Thread::Run(run_loop);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment