summaryrefslogtreecommitdiffstats
path: root/chrome/browser/metrics/thread_watcher.cc
diff options
context:
space:
mode:
authorrtenneti@chromium.org <rtenneti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-28 07:46:56 +0000
committerrtenneti@chromium.org <rtenneti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-28 07:46:56 +0000
commit7024e3fc02ae1b26d47c2235b1b34bdf1f084894 (patch)
tree258928b48c24643b66955552b61b2a9ce9822f1a /chrome/browser/metrics/thread_watcher.cc
parent32e56e56e65ebe54ab437c008f0722c2fb0fd875 (diff)
downloadchromium_src-7024e3fc02ae1b26d47c2235b1b34bdf1f084894.zip
chromium_src-7024e3fc02ae1b26d47c2235b1b34bdf1f084894.tar.gz
chromium_src-7024e3fc02ae1b26d47c2235b1b34bdf1f084894.tar.bz2
Trying changes to see the perfomance impact on Mac.
This change list is same as CL 6588039. Will back out immediately. BUG=73915 Review URL: http://codereview.chromium.org/6602004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@76199 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/metrics/thread_watcher.cc')
-rw-r--r--chrome/browser/metrics/thread_watcher.cc176
1 files changed, 113 insertions, 63 deletions
diff --git a/chrome/browser/metrics/thread_watcher.cc b/chrome/browser/metrics/thread_watcher.cc
index ececcac..54f8bf9 100644
--- a/chrome/browser/metrics/thread_watcher.cc
+++ b/chrome/browser/metrics/thread_watcher.cc
@@ -2,14 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#if 0
-
#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
#include "chrome/browser/metrics/metrics_service.h"
#include "chrome/browser/metrics/thread_watcher.h"
#include "chrome/common/notification_service.h"
+#if defined(OS_WIN)
+#include <Objbase.h>
+#endif
+
// static
const int ThreadWatcher::kPingCount = 3;
@@ -42,19 +44,20 @@ void ThreadWatcher::StartWatching(const BrowserThread::ID thread_id,
DCHECK_GE(sleep_time.InMilliseconds(), 0);
DCHECK_GE(unresponsive_time.InMilliseconds(), sleep_time.InMilliseconds());
- // If we are not on WATCHDOG thread, then post a task to call StartWatching on
- // WATCHDOG thread.
- if (!BrowserThread::CurrentlyOn(BrowserThread::WATCHDOG)) {
- BrowserThread::PostTask(
- BrowserThread::WATCHDOG,
- FROM_HERE,
- NewRunnableFunction(
- &ThreadWatcher::StartWatching,
- thread_id, thread_name, sleep_time, unresponsive_time));
+ // If we are not on WatchDogThread, then post a task to call StartWatching on
+ // WatchDogThread.
+ if (!WatchDogThread::CurrentlyOnWatchDogThread()) {
+ MessageLoop* message_loop = WatchDogThread::CurrentMessageLoop();
+ if (message_loop)
+ message_loop->PostTask(
+ FROM_HERE,
+ NewRunnableFunction(
+ &ThreadWatcher::StartWatching,
+ thread_id, thread_name, sleep_time, unresponsive_time));
return;
}
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WATCHDOG));
+ DCHECK(WatchDogThread::CurrentlyOnWatchDogThread());
// Create a new thread watcher object for the given thread and activate it.
ThreadWatcher* watcher =
@@ -64,7 +67,7 @@ void ThreadWatcher::StartWatching(const BrowserThread::ID thread_id,
}
void ThreadWatcher::ActivateThreadWatching() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WATCHDOG));
+ DCHECK(WatchDogThread::CurrentlyOnWatchDogThread());
if (active_) return;
active_ = true;
ping_count_ = kPingCount;
@@ -74,14 +77,14 @@ void ThreadWatcher::ActivateThreadWatching() {
}
void ThreadWatcher::DeActivateThreadWatching() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WATCHDOG));
+ DCHECK(WatchDogThread::CurrentlyOnWatchDogThread());
active_ = false;
ping_count_ = 0;
method_factory_.RevokeAll();
}
void ThreadWatcher::WakeUp() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WATCHDOG));
+ DCHECK(WatchDogThread::CurrentlyOnWatchDogThread());
// There is some user activity, PostPingMessage task of thread watcher if
// needed.
if (!active_) return;
@@ -95,7 +98,7 @@ void ThreadWatcher::WakeUp() {
}
void ThreadWatcher::PostPingMessage() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WATCHDOG));
+ DCHECK(WatchDogThread::CurrentlyOnWatchDogThread());
// If we have stopped watching or if the user is idle, then stop sending
// ping messages.
if (!active_ || ping_count_ <= 0)
@@ -126,7 +129,7 @@ void ThreadWatcher::PostPingMessage() {
}
void ThreadWatcher::OnPongMessage(uint64 ping_sequence_number) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WATCHDOG));
+ DCHECK(WatchDogThread::CurrentlyOnWatchDogThread());
// Record watched thread's response time.
base::TimeDelta response_time = base::TimeTicks::Now() - ping_time_;
histogram_->AddTime(response_time);
@@ -152,7 +155,7 @@ void ThreadWatcher::OnPongMessage(uint64 ping_sequence_number) {
}
bool ThreadWatcher::OnCheckResponsiveness(uint64 ping_sequence_number) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WATCHDOG));
+ DCHECK(WatchDogThread::CurrentlyOnWatchDogThread());
// If we have stopped watching then consider thread as responding.
if (!active_)
return true;
@@ -178,7 +181,11 @@ void ThreadWatcher::OnPingMessage(const BrowserThread::ID thread_id,
Task* callback_task) {
// This method is called on watched thread.
DCHECK(BrowserThread::CurrentlyOn(thread_id));
- BrowserThread::PostTask(BrowserThread::WATCHDOG, FROM_HERE, callback_task);
+ MessageLoop* message_loop = WatchDogThread::CurrentMessageLoop();
+ if (message_loop)
+ message_loop->PostTask(FROM_HERE, callback_task);
+ else
+ delete callback_task;
}
//------------------------------------------------------------------------------
@@ -191,22 +198,15 @@ ThreadWatcherList::ThreadWatcherList()
: last_wakeup_time_(base::TimeTicks::Now()) {
// Assert we are not running on WATCHDOG thread. Would be ideal to assert we
// are on UI thread, but Unit tests are not running on UI thread.
- DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::WATCHDOG));
- DCHECK(!global_);
+ DCHECK(!WatchDogThread::CurrentlyOnWatchDogThread());
+ CHECK(!global_);
global_ = this;
// Register Notifications observer.
-#if defined(OS_WIN)
MetricsService::SetupNotifications(&registrar_, this);
-#endif
}
ThreadWatcherList::~ThreadWatcherList() {
base::AutoLock auto_lock(lock_);
- while (!registered_.empty()) {
- RegistrationList::iterator it = registered_.begin();
- delete it->second;
- registered_.erase(it->first);
- }
DCHECK(this == global_);
global_ = NULL;
}
@@ -224,15 +224,16 @@ void ThreadWatcherList::StopWatchingAll() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (!global_)
return;
- base::AutoLock auto_lock(global_->lock_);
- for (RegistrationList::iterator it = global_->registered_.begin();
- global_->registered_.end() != it;
- ++it)
- BrowserThread::PostTask(
- BrowserThread::WATCHDOG,
+
+ // Remove all notifications for all watched threads.
+ RemoveNotifications();
+
+ // Delete all thread watcher objects on WatchDogThread.
+ MessageLoop* message_loop = WatchDogThread::CurrentMessageLoop();
+ if (message_loop)
+ message_loop->PostTask(
FROM_HERE,
- NewRunnableMethod(
- it->second, &ThreadWatcher::DeActivateThreadWatching));
+ NewRunnableMethod(global_, &ThreadWatcherList::DeleteAll));
}
// static
@@ -240,10 +241,18 @@ void ThreadWatcherList::RemoveNotifications() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (!global_)
return;
-#if defined(OS_WIN)
base::AutoLock auto_lock(global_->lock_);
global_->registrar_.RemoveAll();
-#endif
+}
+
+void ThreadWatcherList::DeleteAll() {
+ DCHECK(WatchDogThread::CurrentlyOnWatchDogThread());
+ base::AutoLock auto_lock(lock_);
+ while (!registered_.empty()) {
+ RegistrationList::iterator it = registered_.begin();
+ delete it->second;
+ registered_.erase(it->first);
+ }
}
void ThreadWatcherList::Observe(NotificationType type,
@@ -260,15 +269,17 @@ void ThreadWatcherList::Observe(NotificationType type,
last_wakeup_time_ = now;
}
}
- if (need_to_awaken)
- BrowserThread::PostTask(
- BrowserThread::WATCHDOG,
- FROM_HERE,
- NewRunnableMethod(this, &ThreadWatcherList::WakeUpAll));
+ if (need_to_awaken) {
+ MessageLoop* message_loop = WatchDogThread::CurrentMessageLoop();
+ if (message_loop)
+ message_loop->PostTask(
+ FROM_HERE,
+ NewRunnableMethod(this, &ThreadWatcherList::WakeUpAll));
+ }
}
void ThreadWatcherList::WakeUpAll() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WATCHDOG));
+ DCHECK(WatchDogThread::CurrentlyOnWatchDogThread());
base::AutoLock auto_lock(lock_);
for (RegistrationList::iterator it = global_->registered_.begin();
global_->registered_.end() != it;
@@ -294,42 +305,81 @@ ThreadWatcher* ThreadWatcherList::PreLockedFind(
//------------------------------------------------------------------------------
// WatchDogThread methods and members.
+// static
+base::Lock WatchDogThread::lock_;
+// static
+WatchDogThread* WatchDogThread::watchdog_thread_ = NULL;
+
// The WatchDogThread object must outlive any tasks posted to the IO thread
// before the Quit task.
DISABLE_RUNNABLE_METHOD_REFCOUNT(WatchDogThread);
-WatchDogThread::WatchDogThread()
- : BrowserProcessSubThread(BrowserThread::WATCHDOG) {
+WatchDogThread::WatchDogThread() : Thread("WATCHDOG") {
}
WatchDogThread::~WatchDogThread() {
- // Remove all notifications for all watched threads.
- ThreadWatcherList::RemoveNotifications();
// We cannot rely on our base class to stop the thread since we want our
// CleanUp function to run.
Stop();
}
+void WatchDogThread::StartWatchingAll() {
+ const base::TimeDelta kSleepTime = base::TimeDelta::FromSeconds(5);
+ const base::TimeDelta kUnresponsiveTime = base::TimeDelta::FromSeconds(10);
+ if (BrowserThread::IsMessageLoopValid(BrowserThread::UI))
+ ThreadWatcher::StartWatching(BrowserThread::UI, "UI", kSleepTime,
+ kUnresponsiveTime);
+ if (BrowserThread::IsMessageLoopValid(BrowserThread::IO))
+ ThreadWatcher::StartWatching(BrowserThread::IO, "IO", kSleepTime,
+ kUnresponsiveTime);
+ if (BrowserThread::IsMessageLoopValid(BrowserThread::DB))
+ ThreadWatcher::StartWatching(BrowserThread::DB, "DB", kSleepTime,
+ kUnresponsiveTime);
+ if (BrowserThread::IsMessageLoopValid(BrowserThread::FILE))
+ ThreadWatcher::StartWatching(BrowserThread::FILE, "FILE", kSleepTime,
+ kUnresponsiveTime);
+ if (BrowserThread::IsMessageLoopValid(BrowserThread::CACHE))
+ ThreadWatcher::StartWatching(BrowserThread::CACHE, "CACHE", kSleepTime,
+ kUnresponsiveTime);
+}
+
+// static
+MessageLoop* WatchDogThread::CurrentMessageLoop() {
+ base::AutoLock lock(lock_);
+ MessageLoop* message_loop = watchdog_thread_ ?
+ watchdog_thread_->message_loop() : NULL;
+ return message_loop;
+}
+
+// static
+bool WatchDogThread::CurrentlyOnWatchDogThread() {
+ base::AutoLock lock(lock_);
+ return watchdog_thread_ &&
+ watchdog_thread_->message_loop() == MessageLoop::current();
+}
+
void WatchDogThread::Init() {
// This thread shouldn't be allowed to perform any blocking disk I/O.
base::ThreadRestrictions::SetIOAllowed(false);
- BrowserProcessSubThread::Init();
-
#if defined(OS_WIN)
- const base::TimeDelta kSleepTime = base::TimeDelta::FromSeconds(5);
- const base::TimeDelta kUnresponsiveTime = base::TimeDelta::FromSeconds(10);
- ThreadWatcher::StartWatching(BrowserThread::UI, "UI", kSleepTime,
- kUnresponsiveTime);
- ThreadWatcher::StartWatching(BrowserThread::IO, "IO", kSleepTime,
- kUnresponsiveTime);
- ThreadWatcher::StartWatching(BrowserThread::DB, "DB", kSleepTime,
- kUnresponsiveTime);
- ThreadWatcher::StartWatching(BrowserThread::FILE, "FILE", kSleepTime,
- kUnresponsiveTime);
- ThreadWatcher::StartWatching(BrowserThread::CACHE, "CACHE", kSleepTime,
- kUnresponsiveTime);
+ // Initializes the COM library on the current thread.
+ CoInitialize(NULL);
#endif
+
+ base::AutoLock lock(lock_);
+ watchdog_thread_ = this;
+}
+
+void WatchDogThread::CleanUp() {
+ base::AutoLock lock(lock_);
+ watchdog_thread_ = NULL;
}
-#endif // 0
+void WatchDogThread::CleanUpAfterMessageLoopDestruction() {
+#if defined(OS_WIN)
+ // Closes the COM library on the current thread. CoInitialize must
+ // be balanced by a corresponding call to CoUninitialize.
+ CoUninitialize();
+#endif
+}