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