Index: mojo/edk/util/waitable_event.cc |
diff --git a/mojo/edk/system/waitable_event.cc b/mojo/edk/util/waitable_event.cc |
similarity index 59% |
rename from mojo/edk/system/waitable_event.cc |
rename to mojo/edk/util/waitable_event.cc |
index c05d038e0e45e49d1980da91a41fabf17388a614..c4b345355a0c334803187b3da1d0c38d9d36361a 100644 |
--- a/mojo/edk/system/waitable_event.cc |
+++ b/mojo/edk/util/waitable_event.cc |
@@ -2,20 +2,71 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
-#include "mojo/edk/system/waitable_event.h" |
+#include "mojo/edk/util/waitable_event.h" |
-#include "base/logging.h" |
-#include "base/time/time.h" |
+#include "build/build_config.h" |
+#include "mojo/edk/util/logging_internal.h" |
-using mojo::util::CondVar; |
-using mojo::util::Mutex; |
-using mojo::util::MutexLocker; |
+#if defined(OS_MACOSX) || defined(OS_IOS) |
+#include <mach/kern_return.h> |
+#include <mach/mach_time.h> |
+#else |
+#include <errno.h> |
+#include <time.h> |
+#endif // defined(OS_MACOSX) || defined(OS_IOS) |
namespace mojo { |
-namespace system { |
+namespace util { |
namespace { |
+// Mac OS X/iOS don't have a (useful) |clock_gettime()|. |
+// Note: Chromium's |base::TimeTicks::Now()| uses boot time (obtained via |
+// |sysctl()| with |CTL_KERN|/|KERN_BOOTTIME|). For our current purposes, |
+// monotonic time (which pauses during sleeps) is sufficient. TODO(vtl): If/when |
+// we use this for other purposes, maybe we should use boot time (maybe also on |
+// POSIX). |
+#if defined(OS_MACOSX) || defined(OS_IOS) |
+mach_timebase_info_data_t GetMachTimebaseInfo() { |
+ mach_timebase_info_data_t timebase_info = {}; |
+ kern_return_t error = mach_timebase_info(&timebase_info); |
+ INTERNAL_DCHECK(error == KERN_SUCCESS); |
+ return timebase_info; |
+} |
+ |
+// Returns the number of microseconds elapsed since epoch start (according to a |
+// monotonic clock). |
+uint64_t Now() { |
+ const uint64_t kNanosecondsPerMicrosecond = 1000ULL; |
+ |
+ // TODO(vtl): Without magic statics, this is not thread-safe, at least the |
+ // first time around (neither is Mac Chromium's |base::TimeTicks::Now()|)! |
+ static mach_timebase_info_data_t timebase_info = GetMachTimebaseInfo(); |
+ |
+ // |timebase_info| converts absolute time tick units into nanoseconds. By |
+ // dividing by 1000 first, we reduce the risk of overflowing (at the cost of a |
+ // risk of a slight loss in precision). |
+ return mach_absolute_time() / kNanosecondsPerMicrosecond * |
+ timebase_info.numer / timebase_info.denom; |
+} |
+#else |
+// Returns the number of microseconds elapsed since epoch start (according to a |
+// monotonic clock). |
+uint64_t Now() { |
+ const uint64_t kMicrosecondsPerSecond = 1000000ULL; |
+ const uint64_t kNanosecondsPerMicrosecond = 1000ULL; |
+ |
+ struct timespec now; |
+ int error = clock_gettime(CLOCK_MONOTONIC, &now); |
+ INTERNAL_DCHECK_WITH_ERRNO(!error, "clock_gettime", errno); |
+ INTERNAL_DCHECK(now.tv_sec >= 0); |
+ INTERNAL_DCHECK(now.tv_nsec >= 0); |
+ |
+ return static_cast<uint64_t>(now.tv_sec) * kMicrosecondsPerSecond + |
+ static_cast<uint64_t>(now.tv_nsec) / kNanosecondsPerMicrosecond; |
+} |
+#endif // defined(OS_MACOSX) || defined(OS_IOS) |
+ |
// Waits with a timeout on |condition()|. Returns true on timeout, or false if |
// |condition()| ever returns true. |condition()| should have no side effects |
// (and will always be called with |*mutex| held). |
@@ -32,7 +83,7 @@ bool WaitWithTimeoutImpl(Mutex* mutex, |
// We may get spurious wakeups. |
uint64_t wait_remaining = timeout_microseconds; |
- auto start = base::TimeTicks::Now(); |
+ uint64_t start = Now(); |
while (true) { |
if (cv->WaitWithTimeout(mutex, wait_remaining)) |
return true; // Definitely timed out. |
@@ -42,9 +93,9 @@ bool WaitWithTimeoutImpl(Mutex* mutex, |
return false; |
// Or the wakeup may have been spurious. |
- auto now = base::TimeTicks::Now(); |
- DCHECK_GE(now, start); |
- uint64_t elapsed = static_cast<uint64_t>((now - start).InMicroseconds()); |
+ uint64_t now = Now(); |
+ INTERNAL_DCHECK(now >= start); |
+ uint64_t elapsed = now - start; |
// It's possible that we may have timed out anyway. |
if (elapsed >= timeout_microseconds) |
return true; |
@@ -86,7 +137,7 @@ bool AutoResetWaitableEvent::WaitWithTimeout(uint64_t timeout_microseconds) { |
// We may get spurious wakeups. |
uint64_t wait_remaining = timeout_microseconds; |
- auto start = base::TimeTicks::Now(); |
+ uint64_t start = Now(); |
while (true) { |
if (cv_.WaitWithTimeout(&mutex_, wait_remaining)) |
return true; // Definitely timed out. |
@@ -96,9 +147,9 @@ bool AutoResetWaitableEvent::WaitWithTimeout(uint64_t timeout_microseconds) { |
break; |
// Or the wakeup may have been spurious. |
- auto now = base::TimeTicks::Now(); |
- DCHECK_GE(now, start); |
- uint64_t elapsed = static_cast<uint64_t>((now - start).InMicroseconds()); |
+ uint64_t now = Now(); |
+ INTERNAL_DCHECK(now >= start); |
+ uint64_t elapsed = now - start; |
// It's possible that we may have timed out anyway. |
if (elapsed >= timeout_microseconds) |
return true; |
@@ -155,7 +206,7 @@ bool ManualResetWaitableEvent::WaitWithTimeout(uint64_t timeout_microseconds) { |
// Also check |signaled_| in case we're already signaled. |
return signaled_ || signal_id_ != last_signal_id; |
}, timeout_microseconds); |
- DCHECK(rv || signaled_ || signal_id_ != last_signal_id); |
+ INTERNAL_DCHECK(rv || signaled_ || signal_id_ != last_signal_id); |
return rv; |
} |
@@ -164,5 +215,5 @@ bool ManualResetWaitableEvent::IsSignaledForTest() { |
return signaled_; |
} |
-} // namespace system |
+} // namespace util |
} // namespace mojo |