Removed Common
Change-Id: I01ea8f07220375c2ad9bc0092281d4f27c642303
diff --git a/aos/time/time.cc b/aos/time/time.cc
new file mode 100644
index 0000000..a72b121
--- /dev/null
+++ b/aos/time/time.cc
@@ -0,0 +1,145 @@
+#include "aos/time/time.h"
+
+#include <inttypes.h>
+#include <string.h>
+
+#include <atomic>
+#include <chrono>
+
+// We only use global_core from here, which is weak, so we don't really have a
+// dependency on it.
+#include "aos/linux_code/ipc_lib/shared_mem.h"
+
+#include "aos/logging/logging.h"
+#include "aos/mutex/mutex.h"
+
+namespace chrono = ::std::chrono;
+
+namespace std {
+namespace this_thread {
+template <>
+void sleep_until(const ::aos::monotonic_clock::time_point &end_time) {
+ struct timespec end_time_timespec;
+ ::std::chrono::seconds sec =
+ ::std::chrono::duration_cast<::std::chrono::seconds>(
+ end_time.time_since_epoch());
+ ::std::chrono::nanoseconds nsec =
+ ::std::chrono::duration_cast<::std::chrono::nanoseconds>(
+ end_time.time_since_epoch() - sec);
+ end_time_timespec.tv_sec = sec.count();
+ end_time_timespec.tv_nsec = nsec.count();
+ int returnval;
+ do {
+ returnval = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME,
+ &end_time_timespec, nullptr);
+ if (returnval != EINTR && returnval != 0) {
+ PLOG(FATAL, "clock_nanosleep(%jd, TIMER_ABSTIME, %p, nullptr) failed",
+ static_cast<uintmax_t>(CLOCK_MONOTONIC), &end_time_timespec);
+ }
+ } while (returnval != 0);
+}
+
+} // namespace this_thread
+} // namespace std
+
+
+namespace aos {
+namespace time {
+
+// State required to enable and use mock time.
+namespace {
+// True if mock time is enabled.
+// This does not need to be checked with the mutex held because setting time to
+// be enabled or disabled is atomic, and all future operations are atomic
+// anyways. If there is a race condition setting or clearing whether time is
+// enabled or not, it will still be a race condition if current_mock_time is
+// also set atomically with enabled.
+::std::atomic<bool> mock_time_enabled{false};
+// Mutex to make time reads and writes thread safe.
+Mutex time_mutex;
+// Current time when time is mocked.
+monotonic_clock::time_point current_mock_time = monotonic_clock::epoch();
+
+} // namespace
+
+void EnableMockTime(monotonic_clock::time_point now) {
+ MutexLocker time_mutex_locker(&time_mutex);
+ mock_time_enabled = true;
+ current_mock_time = now;
+}
+
+void UpdateMockTime() { SetMockTime(monotonic_clock::now()); }
+
+void DisableMockTime() {
+ MutexLocker time_mutex_locker(&time_mutex);
+ mock_time_enabled = false;
+}
+
+void SetMockTime(monotonic_clock::time_point now) {
+ MutexLocker time_mutex_locker(&time_mutex);
+ if (__builtin_expect(!mock_time_enabled, 0)) {
+ LOG(FATAL, "Tried to set mock time and mock time is not enabled\n");
+ }
+ current_mock_time = now;
+}
+
+void IncrementMockTime(monotonic_clock::duration amount) {
+ static ::aos::Mutex mutex;
+ ::aos::MutexLocker sync(&mutex);
+ SetMockTime(monotonic_clock::now() + amount);
+}
+
+void OffsetToNow(monotonic_clock::time_point now) {
+ CHECK_NOTNULL(&global_core);
+ CHECK_NOTNULL(global_core);
+ CHECK_NOTNULL(global_core->mem_struct);
+ const auto offset = now - monotonic_clock::now();
+ global_core->mem_struct->time_offset =
+ chrono::duration_cast<chrono::nanoseconds>(offset).count();
+}
+
+struct timespec to_timespec(
+ const ::aos::monotonic_clock::duration duration) {
+ struct timespec time_timespec;
+ ::std::chrono::seconds sec =
+ ::std::chrono::duration_cast<::std::chrono::seconds>(duration);
+ ::std::chrono::nanoseconds nsec =
+ ::std::chrono::duration_cast<::std::chrono::nanoseconds>(duration - sec);
+ time_timespec.tv_sec = sec.count();
+ time_timespec.tv_nsec = nsec.count();
+ return time_timespec;
+}
+
+struct timespec to_timespec(
+ const ::aos::monotonic_clock::time_point time) {
+ return to_timespec(time.time_since_epoch());
+}
+} // namespace time
+
+constexpr monotonic_clock::time_point monotonic_clock::min_time;
+
+monotonic_clock::time_point monotonic_clock::now() noexcept {
+ {
+ if (time::mock_time_enabled.load(::std::memory_order_relaxed)) {
+ MutexLocker time_mutex_locker(&time::time_mutex);
+ return time::current_mock_time;
+ }
+ }
+
+ struct timespec current_time;
+ if (clock_gettime(CLOCK_MONOTONIC, ¤t_time) != 0) {
+ PLOG(FATAL, "clock_gettime(%jd, %p) failed",
+ static_cast<uintmax_t>(CLOCK_MONOTONIC), ¤t_time);
+ }
+ const chrono::nanoseconds offset =
+ (&global_core == nullptr || global_core == nullptr ||
+ global_core->mem_struct == nullptr)
+ ? chrono::nanoseconds(0)
+ : chrono::nanoseconds(global_core->mem_struct->time_offset);
+
+ return time_point(::std::chrono::seconds(current_time.tv_sec) +
+ ::std::chrono::nanoseconds(current_time.tv_nsec)) + offset;
+}
+
+
+} // namespace aos