diff options
author | deanm@chromium.org <deanm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-11-25 22:46:59 +0000 |
---|---|---|
committer | deanm@chromium.org <deanm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-11-25 22:46:59 +0000 |
commit | 95ab1553ce02175cf23278d80b8440b27740159c (patch) | |
tree | 56fc9eb4c803368b24b191c108f143c8009eb03c /base | |
parent | d8375fdbe8d32ad3562152ecd53378383e393971 (diff) | |
download | chromium_src-95ab1553ce02175cf23278d80b8440b27740159c.zip chromium_src-95ab1553ce02175cf23278d80b8440b27740159c.tar.gz chromium_src-95ab1553ce02175cf23278d80b8440b27740159c.tar.bz2 |
Port base/watchdog to Linux.
BUG=4632
Review URL: http://codereview.chromium.org/11326
Patch from Pawel Hajdan Jr.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@6004 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r-- | base/base_lib.scons | 7 | ||||
-rw-r--r-- | base/base_unittests.scons | 1 | ||||
-rw-r--r-- | base/watchdog.cc | 77 | ||||
-rw-r--r-- | base/watchdog.h | 36 | ||||
-rw-r--r-- | base/watchdog_unittest.cc | 42 |
5 files changed, 68 insertions, 95 deletions
diff --git a/base/base_lib.scons b/base/base_lib.scons index b2caa8b..b84d1c1 100644 --- a/base/base_lib.scons +++ b/base/base_lib.scons @@ -21,8 +21,8 @@ if env['PLATFORM'] == 'win32': ], ) -# These base files work on *all* platforms; files that don't work -# cross-platform live below. +# Some files from this list are not yet ported. They are removed from +# the list, see code below. input_files = [ 'at_exit.cc', 'base_paths.cc', @@ -109,14 +109,11 @@ if env['PLATFORM'] in ('posix', 'darwin'): 'event_recorder.cc', 'file_version_info.cc', - # This group all depends on MessageLoop. - # We have an implementation of idle_timer, but it's unclear if we want it # yet, so it's commented out for now. Leave this 'unported'. 'idle_timer.cc', 'object_watcher.cc', - 'watchdog.cc', 'resource_util.cc', # Uses HMODULE, but may be abstractable. ] diff --git a/base/base_unittests.scons b/base/base_unittests.scons index 37f98ca..833339e 100644 --- a/base/base_unittests.scons +++ b/base/base_unittests.scons @@ -114,7 +114,6 @@ if env['PLATFORM'] in ('posix', 'darwin'): # yet, so it's commented out for now. Leave this 'unported'. 'idletimer_unittest.cc', - 'watchdog_unittest.cc', 'gfx/native_theme_unittest.cc', ] for remove in to_be_ported_files: diff --git a/base/watchdog.cc b/base/watchdog.cc index b1db70b..0049fec 100644 --- a/base/watchdog.cc +++ b/base/watchdog.cc @@ -4,8 +4,8 @@ #include "base/watchdog.h" +#include "base/compiler_specific.h" #include "base/platform_thread.h" -#include "base/string_util.h" using base::TimeDelta; using base::TimeTicks; @@ -15,42 +15,32 @@ using base::TimeTicks; // Start thread running in a Disarmed state. Watchdog::Watchdog(const TimeDelta& duration, - const std::wstring& thread_watched_name, + const std::string& thread_watched_name, bool enabled) - : lock_(), + : init_successful_(false), + lock_(), condition_variable_(&lock_), state_(DISARMED), - duration_(duration), thread_watched_name_(thread_watched_name), - handle_(NULL), - thread_id_(0) { + ALLOW_THIS_IN_INITIALIZER_LIST(delegate_(this, duration)) { if (!enabled) return; // Don't start thread, or doing anything really. - handle_ = CreateThread(NULL, // security - 0, // Default stack size. - Watchdog::ThreadStart, - reinterpret_cast<void*>(this), - CREATE_SUSPENDED, - &thread_id_); - DCHECK(NULL != handle_); - if (NULL == handle_) - return ; - ResumeThread(handle_); // WINAPI call. + init_successful_ = PlatformThread::Create(0, // Default stack size. + &delegate_, + &handle_); + DCHECK(init_successful_); } // Notify watchdog thread, and wait for it to finish up. Watchdog::~Watchdog() { - if (NULL == handle_) + if (!init_successful_) return; { AutoLock lock(lock_); state_ = SHUTDOWN; } condition_variable_.Signal(); - DWORD results = WaitForSingleObject(handle_, INFINITE); - DCHECK(WAIT_OBJECT_0 == results); - CloseHandle(handle_); - handle_ = NULL; + PlatformThread::Join(handle_); } void Watchdog::Arm() { @@ -75,8 +65,6 @@ void Watchdog::ArmAtStartTime(const TimeTicks start_time) { // Disable watchdog so that it won't do anything when time expires. void Watchdog::Disarm() { - if (NULL == handle_) - return; AutoLock lock(lock_); state_ = DISARMED; // We don't need to signal, as the watchdog will eventually wake up, and it @@ -86,43 +74,39 @@ void Watchdog::Disarm() { //------------------------------------------------------------------------------ // Internal private methods that the watchdog thread uses. -// static -DWORD __stdcall Watchdog::ThreadStart(void* pThis) { - Watchdog* watchdog = reinterpret_cast<Watchdog*>(pThis); - return watchdog->Run(); -} - -unsigned Watchdog::Run() { +void Watchdog::ThreadDelegate::ThreadMain() { SetThreadName(); TimeDelta remaining_duration; while (1) { - AutoLock lock(lock_); - while (DISARMED == state_) - condition_variable_.Wait(); - if (SHUTDOWN == state_) - return 0; - DCHECK(ARMED == state_); - remaining_duration = duration_ - (TimeTicks::Now() - start_time_); + AutoLock lock(watchdog_->lock_); + while (DISARMED == watchdog_->state_) + watchdog_->condition_variable_.Wait(); + if (SHUTDOWN == watchdog_->state_) + return; + DCHECK(ARMED == watchdog_->state_); + remaining_duration = duration_ - + (TimeTicks::Now() - watchdog_->start_time_); if (remaining_duration.InMilliseconds() > 0) { // Spurios wake? Timer drifts? Go back to sleep for remaining time. - condition_variable_.TimedWait(remaining_duration); + watchdog_->condition_variable_.TimedWait(remaining_duration); } else { // We overslept, so this seems like a real alarm. // Watch out for a user that stopped the debugger on a different alarm! { AutoLock static_lock(static_lock_); - if (last_debugged_alarm_time_ > start_time_) { + if (last_debugged_alarm_time_ > watchdog_->start_time_) { // False alarm: we started our clock before the debugger break (last // alarm time). - start_time_ += last_debugged_alarm_delay_; - if (last_debugged_alarm_time_ > start_time_) - state_ = DISARMED; // Too many alarms must have taken place. + watchdog_->start_time_ += last_debugged_alarm_delay_; + if (last_debugged_alarm_time_ > watchdog_->start_time_) + // Too many alarms must have taken place. + watchdog_->state_ = DISARMED; continue; } } - state_ = DISARMED; // Only alarm at most once. + watchdog_->state_ = DISARMED; // Only alarm at most once. TimeTicks last_alarm_time = TimeTicks::Now(); - Alarm(); // Set a break point here to debug on alarms. + watchdog_->Alarm(); // Set a break point here to debug on alarms. TimeDelta last_alarm_delay = TimeTicks::Now() - last_alarm_time; if (last_alarm_delay > TimeDelta::FromMilliseconds(2)) { // Ignore race of two alarms/breaks going off at roughly the same time. @@ -135,9 +119,8 @@ unsigned Watchdog::Run() { } } -void Watchdog::SetThreadName() const { - std::string name = StringPrintf("%s Watchdog", - WideToASCII(thread_watched_name_).c_str()); +void Watchdog::ThreadDelegate::SetThreadName() const { + std::string name = watchdog_->thread_watched_name_ + " Watchdog"; PlatformThread::SetName(name.c_str()); DLOG(INFO) << "Watchdog active: " << name; } diff --git a/base/watchdog.h b/base/watchdog.h index c7e967f..63c0612 100644 --- a/base/watchdog.h +++ b/base/watchdog.h @@ -22,15 +22,15 @@ #include "base/condition_variable.h" #include "base/lock.h" +#include "base/platform_thread.h" #include "base/time.h" class Watchdog { public: - // TODO(JAR)change default arg to required arg after all users have migrated. // Constructor specifies how long the Watchdog will wait before alarming. Watchdog(const base::TimeDelta& duration, - const std::wstring& thread_watched_name, - bool enabled = true); + const std::string& thread_watched_name, + bool enabled); virtual ~Watchdog(); // Start timing, and alarm when time expires (unless we're disarm()ed.) @@ -48,22 +48,29 @@ class Watchdog { } private: - enum State {ARMED, DISARMED, SHUTDOWN }; + class ThreadDelegate : public PlatformThread::Delegate { + public: + explicit ThreadDelegate(Watchdog* watchdog, const base::TimeDelta& duration) + : watchdog_(watchdog), duration_(duration) { + } + virtual void ThreadMain(); + private: + Watchdog* watchdog_; + const base::TimeDelta duration_; // How long after start_time_ do we alarm? + + void SetThreadName() const; + }; - // Windows thread start callback - static DWORD WINAPI ThreadStart(void* pThis); + enum State {ARMED, DISARMED, SHUTDOWN }; - // Loop and test function for our watchdog thread. - unsigned Run(); - void Watchdog::SetThreadName() const; + bool init_successful_; Lock lock_; // Mutex for state_. ConditionVariable condition_variable_; State state_; - const base::TimeDelta duration_; // How long after start_time_ do we alarm? - const std::wstring thread_watched_name_; - HANDLE handle_; // Handle for watchdog thread. - DWORD thread_id_; // Also for watchdog thread. + const std::string thread_watched_name_; + PlatformThreadHandle handle_; + ThreadDelegate delegate_; // Store it, because it must outlive the thread. base::TimeTicks start_time_; // Start of epoch, and alarm after duration_. @@ -79,8 +86,7 @@ class Watchdog { // How long did we sit on a break in the debugger? static base::TimeDelta last_debugged_alarm_delay_; - - DISALLOW_EVIL_CONSTRUCTORS(Watchdog); + DISALLOW_COPY_AND_ASSIGN(Watchdog); }; #endif // BASE_WATCHDOG_H__ diff --git a/base/watchdog_unittest.cc b/base/watchdog_unittest.cc index c4a664f..887311a 100644 --- a/base/watchdog_unittest.cc +++ b/base/watchdog_unittest.cc @@ -5,9 +5,10 @@ // Tests for Watchdog class. #include "base/logging.h" -#include "base/watchdog.h" +#include "base/platform_thread.h" #include "base/spin_wait.h" #include "base/time.h" +#include "base/watchdog.h" #include "testing/gtest/include/gtest/gtest.h" using base::TimeDelta; @@ -17,12 +18,11 @@ namespace { //------------------------------------------------------------------------------ // Provide a derived class to facilitate testing. -// TODO(JAR): Remove default argument from constructor, and make mandatory. class WatchdogCounter : public Watchdog { public: WatchdogCounter(const TimeDelta& duration, - const std::wstring& thread_watched_name, - bool enabled = true) + const std::string& thread_watched_name, + bool enabled) : Watchdog(duration, thread_watched_name, enabled), alarm_counter_(0) { } @@ -38,7 +38,7 @@ class WatchdogCounter : public Watchdog { private: int alarm_counter_; - DISALLOW_EVIL_CONSTRUCTORS(WatchdogCounter); + DISALLOW_COPY_AND_ASSIGN(WatchdogCounter); }; class WatchdogTest : public testing::Test { @@ -50,40 +50,28 @@ class WatchdogTest : public testing::Test { // Minimal constructor/destructor test. TEST(WatchdogTest, StartupShutdownTest) { - Watchdog watchdog1(TimeDelta::FromMilliseconds(300), L"Disabled", false); - Watchdog watchdog2(TimeDelta::FromMilliseconds(300), L"Enabled", true); - - // The following test is depricated, and should be removed when the - // default argument constructor is no longer accepted. - Watchdog watchdog3(TimeDelta::FromMilliseconds(300), L"Default"); + Watchdog watchdog1(TimeDelta::FromMilliseconds(300), "Disabled", false); + Watchdog watchdog2(TimeDelta::FromMilliseconds(300), "Enabled", true); } // Test ability to call Arm and Disarm repeatedly. TEST(WatchdogTest, ArmDisarmTest) { - Watchdog watchdog1(TimeDelta::FromMilliseconds(300), L"Disabled", false); + Watchdog watchdog1(TimeDelta::FromMilliseconds(300), "Disabled", false); watchdog1.Arm(); watchdog1.Disarm(); watchdog1.Arm(); watchdog1.Disarm(); - Watchdog watchdog2(TimeDelta::FromMilliseconds(300), L"Enabled", true); + Watchdog watchdog2(TimeDelta::FromMilliseconds(300), "Enabled", true); watchdog2.Arm(); watchdog2.Disarm(); watchdog2.Arm(); watchdog2.Disarm(); - - // The following test is depricated, and should be removed when the - // default argument constructor is no longer accepted. - Watchdog watchdog3(TimeDelta::FromMilliseconds(300), L"Default"); - watchdog3.Arm(); - watchdog3.Disarm(); - watchdog3.Arm(); - watchdog3.Disarm(); } // Make sure a basic alarm fires when the time has expired. TEST(WatchdogTest, AlarmTest) { - WatchdogCounter watchdog(TimeDelta::FromMilliseconds(10), L"Enabled", true); + WatchdogCounter watchdog(TimeDelta::FromMilliseconds(10), "Enabled", true); watchdog.Arm(); SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(TimeDelta::FromSeconds(1), watchdog.alarm_counter() > 0); @@ -100,21 +88,21 @@ TEST(WatchdogTest, AlarmTest) { // Make sure a disable alarm does nothing, even if we arm it. TEST(WatchdogTest, ConstructorDisabledTest) { - WatchdogCounter watchdog(TimeDelta::FromMilliseconds(10), L"Disabled", false); + WatchdogCounter watchdog(TimeDelta::FromMilliseconds(10), "Disabled", false); watchdog.Arm(); // Alarm should not fire, as it was disabled. - Sleep(500); + PlatformThread::Sleep(500); EXPECT_EQ(0, watchdog.alarm_counter()); } // Make sure Disarming will prevent firing, even after Arming. TEST(WatchdogTest, DisarmTest) { - WatchdogCounter watchdog(TimeDelta::FromSeconds(1), L"Enabled", true); + WatchdogCounter watchdog(TimeDelta::FromSeconds(1), "Enabled", true); watchdog.Arm(); - Sleep(100); // Don't sleep too long + PlatformThread::Sleep(100); // Don't sleep too long watchdog.Disarm(); // Alarm should not fire. - Sleep(1500); + PlatformThread::Sleep(1500); EXPECT_EQ(0, watchdog.alarm_counter()); // ...but even after disarming, we can still use the alarm... |