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() {
base::ScopedClosureRunner unregister_for_hang_watching;
if (watch_for_hangs) {
unregister_for_hang_watching =
base::HangWatcher::GetInstance()->RegisterThread();
base::HangWatcher::GetInstance()->RegisterThread(
base::HangWatcher::ThreadType::kThreadPoolThread);
}
// A WorkerThread starts out waiting for work.
......
......@@ -399,11 +399,12 @@ void HangWatcher::RecordHang() {
base::debug::Alias(&line_number);
}
ScopedClosureRunner HangWatcher::RegisterThread() {
ScopedClosureRunner HangWatcher::RegisterThread(ThreadType thread_type) {
AutoLock auto_lock(watch_state_lock_);
watch_states_.push_back(
internal::HangWatchState::CreateHangWatchStateForCurrentThread());
internal::HangWatchState::CreateHangWatchStateForCurrentThread(
thread_type));
return ScopedClosureRunner(BindOnce(&HangWatcher::UnregisterThread,
Unretained(HangWatcher::GetInstance())));
......@@ -840,7 +841,8 @@ uint64_t HangWatchDeadline::SwitchBitsForTesting() {
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.
DCHECK(!GetHangWatchStateForCurrentThread()->Get());
......@@ -863,11 +865,11 @@ HangWatchState::~HangWatchState() {
// static
std::unique_ptr<HangWatchState>
HangWatchState::CreateHangWatchStateForCurrentThread() {
HangWatchState::CreateHangWatchStateForCurrentThread(
HangWatcher::ThreadType thread_type) {
// Allocate a watch state object for this thread.
std::unique_ptr<HangWatchState> hang_state =
std::make_unique<HangWatchState>();
std::make_unique<HangWatchState>(thread_type);
// Setting the thread local worked.
DCHECK_EQ(GetHangWatchStateForCurrentThread()->Get(), hang_state.get());
......
......@@ -136,6 +136,13 @@ class BASE_EXPORT HangWatchScopeDisabled {
// within a single process. This instance must outlive all monitored threads.
class BASE_EXPORT HangWatcher : public DelegateSimpleThread::Delegate {
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
// accessible through GetInstance(). This means that only one instance can
......@@ -165,7 +172,7 @@ class BASE_EXPORT HangWatcher : public DelegateSimpleThread::Delegate {
// Sets up the calling thread to be monitored for threads. Returns a
// ScopedClosureRunner that unregisters the thread. This closure has to be
// called from the registered thread before it's joined.
ScopedClosureRunner RegisterThread()
ScopedClosureRunner RegisterThread(ThreadType thread_type)
LOCKS_EXCLUDED(watch_state_lock_) WARN_UNUSED_RESULT;
// Choose a closure to be run at the end of each call to Monitor(). Use only
......@@ -512,7 +519,10 @@ class BASE_EXPORT HangWatchDeadline {
// GetHangWatchStateForCurrentThread().
class BASE_EXPORT HangWatchState {
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(const HangWatchState&) = delete;
......@@ -520,7 +530,8 @@ class BASE_EXPORT HangWatchState {
// Allocates a new state object bound to the calling thread and returns an
// 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.
// Returns nullptr if no HangWatchState exists for the current thread (see
......@@ -594,6 +605,9 @@ class BASE_EXPORT HangWatchState {
// Reduce the nesting level by 1;
void DecrementNestingLevel();
// Returns the type of the thread under watch.
HangWatcher::ThreadType thread_type() const { return thread_type_; }
private:
// The thread that creates the instance should be the class that updates
// the deadline.
......@@ -608,6 +622,9 @@ class BASE_EXPORT HangWatchState {
// Number of active HangWatchScopeEnables on this thread.
int nesting_level_ = 0;
// The type of the thread under watch.
const HangWatcher::ThreadType thread_type_;
#if DCHECK_IS_ON()
// Used to keep track of the current HangWatchScopeEnabled and detect improper
// usage. Scopes should always be destructed in reverse order from the one
......
......@@ -56,7 +56,8 @@ class BlockingThread : public DelegateSimpleThread::Delegate {
// (Un)Register the thread here instead of in ctor/dtor so that the action
// happens on the right thread.
base::ScopedClosureRunner unregister_closure =
base::HangWatcher::GetInstance()->RegisterThread();
base::HangWatcher::GetInstance()->RegisterThread(
base::HangWatcher::ThreadType::kThreadForTesting);
HangWatchScopeEnabled scope(timeout_);
wait_until_entered_scope_.Signal();
......@@ -189,7 +190,8 @@ TEST_F(
HangWatcherTest,
ScopeDisabledCreateScopeDisabledDestroyScopeEnabledCreateScopeEnabledDestroy) {
// 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{});
......@@ -216,7 +218,8 @@ TEST_F(
HangWatcherTest,
ScopeEnabledCreateScopeDisabledCreateScopeEnabledDestroyScopeDisabledDestroy) {
// 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;
......@@ -245,7 +248,8 @@ TEST_F(
HangWatcherTest,
ScopeDisabledCreateScopeEnabledCreateScopeDisabledDestroyScopeEnabledDestroy) {
// 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;
......@@ -274,7 +278,8 @@ TEST_F(
HangWatcherTest,
ScopeDisabledCreateScopeEnabledCreateScopeEnabledDestroyScopeDisabledDestroy) {
// 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,
HangWatchScopeDisabled disabler;
......@@ -295,7 +300,8 @@ TEST_F(
TEST_F(HangWatcherTest, ScopeCreateTempCreateTempDestroyScopeDestroy) {
// 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
// time to make sure a hang is detected.
......@@ -320,7 +326,8 @@ TEST_F(
HangWatcherTest,
ScopeEnabledCreateScopeDisabledCreateScopeDisabledDestroyScopeEnabledDestroy) {
// 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
// time to make sure a hang is detected.
......@@ -343,7 +350,8 @@ TEST_F(
// detection in outer scopes.
TEST_F(HangWatcherTest, ScopeDisabledObjectInnerScope) {
// 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
// time to make sure a hang is detected.
......@@ -370,7 +378,8 @@ TEST_F(HangWatcherTest, ScopeDisabledObjectInnerScope) {
TEST_F(HangWatcherTest, NewScopeAfterDisabling) {
// 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
// time to make sure a hang is detected.
......@@ -401,7 +410,8 @@ TEST_F(HangWatcherTest, NestedScopes) {
// Create a state object for the test thread since this test is single
// threaded.
auto current_hang_watch_state =
base::internal::HangWatchState::CreateHangWatchStateForCurrentThread();
base::internal::HangWatchState::CreateHangWatchStateForCurrentThread(
HangWatcher::ThreadType::kThreadForTesting);
ASSERT_FALSE(current_hang_watch_state->IsOverDeadline());
base::TimeTicks original_deadline = current_hang_watch_state->GetDeadline();
......@@ -540,7 +550,8 @@ TEST_F(HangWatcherSnapshotTest, NonActionableReport) {
hang_watcher_.Start();
// 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
// the first monitor will detect a hang.
......@@ -587,7 +598,8 @@ TEST_F(HangWatcherSnapshotTest, DISABLED_HungThreadIDs) {
hang_watcher_.Start();
// 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{});
blocking_thread.StartAndWaitForScopeEntered();
......@@ -741,7 +753,8 @@ TEST_F(HangWatcherPeriodicMonitoringTest, PeriodicCallsTakePlace) {
hang_watcher_.Start();
// Register a thread,
unregister_thread_closure_ = hang_watcher_.RegisterThread();
unregister_thread_closure_ = hang_watcher_.RegisterThread(
base::HangWatcher::ThreadType::kThreadForTesting);
run_loop.Run();
......@@ -769,7 +782,8 @@ TEST_F(HangWatcherPeriodicMonitoringTest, NoMonitorOnOverSleep) {
hang_watcher_.Start();
// 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
// monitoring was inhibited.
......@@ -809,7 +823,8 @@ class HangWatchScopeEnabledBlockingTest : public testing::Test {
hang_watcher_.Start();
// 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(
......
......@@ -531,7 +531,8 @@ BrowserMainLoop::BrowserMainLoop(
// that makes it the same as the current one.
if (base::HangWatcher::IsUIThreadHangWatchingEnabled()) {
unregister_thread_closure_ =
base::HangWatcher::GetInstance()->RegisterThread();
base::HangWatcher::GetInstance()->RegisterThread(
base::HangWatcher::ThreadType::kUIThread);
}
if (GetContentClient()->browser()->ShouldCreateThreadPool()) {
......
......@@ -137,7 +137,8 @@ NOINLINE void BrowserProcessSubThread::IOThreadRun(base::RunLoop* run_loop) {
base::ScopedClosureRunner unregister_thread_closure;
if (base::HangWatcher::IsIOThreadHangWatchingEnabled()) {
unregister_thread_closure =
base::HangWatcher::GetInstance()->RegisterThread();
base::HangWatcher::GetInstance()->RegisterThread(
base::HangWatcher::ThreadType::kIOThread);
}
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