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 |