| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/metrics/thread_watcher.h" | 5 #include "chrome/browser/metrics/thread_watcher.h" |
| 6 | 6 |
| 7 #include <math.h> // ceil | 7 #include <math.h> // ceil |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
| 11 #include "base/debug/alias.h" | 11 #include "base/debug/alias.h" |
| 12 #include "base/lazy_instance.h" | |
| 13 #include "base/string_tokenizer.h" | 12 #include "base/string_tokenizer.h" |
| 14 #include "base/threading/thread_restrictions.h" | 13 #include "base/threading/thread_restrictions.h" |
| 15 #include "build/build_config.h" | 14 #include "build/build_config.h" |
| 16 #include "chrome/browser/metrics/metrics_service.h" | 15 #include "chrome/browser/metrics/metrics_service.h" |
| 17 #include "chrome/common/chrome_switches.h" | 16 #include "chrome/common/chrome_switches.h" |
| 18 #include "chrome/common/chrome_version_info.h" | 17 #include "chrome/common/chrome_version_info.h" |
| 19 #include "chrome/common/logging_chrome.h" | 18 #include "chrome/common/logging_chrome.h" |
| 20 | 19 |
| 21 #if defined(OS_WIN) | 20 #if defined(OS_WIN) |
| 22 #include "base/win/windows_version.h" | 21 #include "base/win/windows_version.h" |
| (...skipping 673 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 696 base::TimeTicks now = base::TimeTicks::Now(); | 695 base::TimeTicks now = base::TimeTicks::Now(); |
| 697 if ((now - last_wakeup_time_) < wakeup_interval_) | 696 if ((now - last_wakeup_time_) < wakeup_interval_) |
| 698 return; | 697 return; |
| 699 last_wakeup_time_ = now; | 698 last_wakeup_time_ = now; |
| 700 WatchDogThread::PostTask( | 699 WatchDogThread::PostTask( |
| 701 FROM_HERE, | 700 FROM_HERE, |
| 702 base::Bind(&ThreadWatcherList::WakeUpAll)); | 701 base::Bind(&ThreadWatcherList::WakeUpAll)); |
| 703 } | 702 } |
| 704 | 703 |
| 705 // WatchDogThread methods and members. | 704 // WatchDogThread methods and members. |
| 706 | 705 // |
| 707 // This lock protects g_watchdog_thread. | 706 // static |
| 708 static base::LazyInstance<base::Lock, | 707 base::Lock WatchDogThread::lock_; |
| 709 base::LeakyLazyInstanceTraits<base::Lock> > | 708 // static |
| 710 g_watchdog_lock = LAZY_INSTANCE_INITIALIZER; | 709 WatchDogThread* WatchDogThread::watchdog_thread_ = NULL; |
| 711 | |
| 712 // The singleton of this class. | |
| 713 static WatchDogThread* g_watchdog_thread = NULL; | |
| 714 | |
| 715 | 710 |
| 716 // The WatchDogThread object must outlive any tasks posted to the IO thread | 711 // The WatchDogThread object must outlive any tasks posted to the IO thread |
| 717 // before the Quit task. | 712 // before the Quit task. |
| 718 DISABLE_RUNNABLE_METHOD_REFCOUNT(WatchDogThread); | 713 DISABLE_RUNNABLE_METHOD_REFCOUNT(WatchDogThread); |
| 719 | 714 |
| 720 WatchDogThread::WatchDogThread() : Thread("BrowserWatchdog") { | 715 WatchDogThread::WatchDogThread() : Thread("BrowserWatchdog") { |
| 721 } | 716 } |
| 722 | 717 |
| 723 WatchDogThread::~WatchDogThread() { | 718 WatchDogThread::~WatchDogThread() { |
| 724 Stop(); | 719 Stop(); |
| 725 } | 720 } |
| 726 | 721 |
| 727 // static | 722 // static |
| 728 bool WatchDogThread::CurrentlyOnWatchDogThread() { | 723 bool WatchDogThread::CurrentlyOnWatchDogThread() { |
| 729 base::AutoLock lock(g_watchdog_lock.Get()); | 724 base::AutoLock lock(lock_); |
| 730 return g_watchdog_thread && | 725 return watchdog_thread_ && |
| 731 g_watchdog_thread->message_loop() == MessageLoop::current(); | 726 watchdog_thread_->message_loop() == MessageLoop::current(); |
| 732 } | 727 } |
| 733 | 728 |
| 734 // static | 729 // static |
| 735 bool WatchDogThread::PostTask(const tracked_objects::Location& from_here, | 730 bool WatchDogThread::PostTask(const tracked_objects::Location& from_here, |
| 736 const base::Closure& task) { | 731 const base::Closure& task) { |
| 737 return PostTaskHelper(from_here, task, 0); | 732 return PostTaskHelper(from_here, task, 0); |
| 738 } | 733 } |
| 739 | 734 |
| 740 // static | 735 // static |
| 741 bool WatchDogThread::PostDelayedTask(const tracked_objects::Location& from_here, | 736 bool WatchDogThread::PostDelayedTask(const tracked_objects::Location& from_here, |
| 742 const base::Closure& task, | 737 const base::Closure& task, |
| 743 int64 delay_ms) { | 738 int64 delay_ms) { |
| 744 return PostTaskHelper(from_here, task, delay_ms); | 739 return PostTaskHelper(from_here, task, delay_ms); |
| 745 } | 740 } |
| 746 | 741 |
| 747 // static | 742 // static |
| 748 bool WatchDogThread::PostTaskHelper( | 743 bool WatchDogThread::PostTaskHelper( |
| 749 const tracked_objects::Location& from_here, | 744 const tracked_objects::Location& from_here, |
| 750 const base::Closure& task, | 745 const base::Closure& task, |
| 751 int64 delay_ms) { | 746 int64 delay_ms) { |
| 752 { | 747 { |
| 753 base::AutoLock lock(g_watchdog_lock.Get()); | 748 base::AutoLock lock(lock_); |
| 754 | 749 |
| 755 MessageLoop* message_loop = g_watchdog_thread ? | 750 MessageLoop* message_loop = watchdog_thread_ ? |
| 756 g_watchdog_thread->message_loop() : NULL; | 751 watchdog_thread_->message_loop() : NULL; |
| 757 if (message_loop) { | 752 if (message_loop) { |
| 758 message_loop->PostDelayedTask(from_here, task, delay_ms); | 753 message_loop->PostDelayedTask(from_here, task, delay_ms); |
| 759 return true; | 754 return true; |
| 760 } | 755 } |
| 761 } | 756 } |
| 762 | 757 |
| 763 return false; | 758 return false; |
| 764 } | 759 } |
| 765 | 760 |
| 766 void WatchDogThread::Init() { | 761 void WatchDogThread::Init() { |
| 767 // This thread shouldn't be allowed to perform any blocking disk I/O. | 762 // This thread shouldn't be allowed to perform any blocking disk I/O. |
| 768 base::ThreadRestrictions::SetIOAllowed(false); | 763 base::ThreadRestrictions::SetIOAllowed(false); |
| 769 | 764 |
| 770 base::AutoLock lock(g_watchdog_lock.Get()); | 765 base::AutoLock lock(lock_); |
| 771 CHECK(!g_watchdog_thread); | 766 CHECK(!watchdog_thread_); |
| 772 g_watchdog_thread = this; | 767 watchdog_thread_ = this; |
| 773 } | 768 } |
| 774 | 769 |
| 775 void WatchDogThread::CleanUp() { | 770 void WatchDogThread::CleanUp() { |
| 776 base::AutoLock lock(g_watchdog_lock.Get()); | 771 base::AutoLock lock(lock_); |
| 777 g_watchdog_thread = NULL; | 772 watchdog_thread_ = NULL; |
| 778 } | 773 } |
| 779 | 774 |
| 780 namespace { | 775 namespace { |
| 781 | 776 |
| 782 // StartupWatchDogThread methods and members. | 777 // StartupWatchDogThread methods and members. |
| 783 // | 778 // |
| 784 // Class for detecting hangs during startup. | 779 // Class for detecting hangs during startup. |
| 785 class StartupWatchDogThread : public base::Watchdog { | 780 class StartupWatchDogThread : public base::Watchdog { |
| 786 public: | 781 public: |
| 787 // Constructor specifies how long the StartupWatchDogThread will wait before | 782 // Constructor specifies how long the StartupWatchDogThread will wait before |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 880 | 875 |
| 881 #if defined(OS_WIN) | 876 #if defined(OS_WIN) |
| 882 // On Windows XP, give twice the time for shutdown. | 877 // On Windows XP, give twice the time for shutdown. |
| 883 if (base::win::GetVersion() <= base::win::VERSION_XP) | 878 if (base::win::GetVersion() <= base::win::VERSION_XP) |
| 884 actual_duration *= 2; | 879 actual_duration *= 2; |
| 885 #endif | 880 #endif |
| 886 | 881 |
| 887 shutdown_watchdog_ = new ShutdownWatchDogThread(actual_duration); | 882 shutdown_watchdog_ = new ShutdownWatchDogThread(actual_duration); |
| 888 shutdown_watchdog_->Arm(); | 883 shutdown_watchdog_->Arm(); |
| 889 } | 884 } |
| OLD | NEW |