Add base/time.h

Introduces GetWallTime() and GetThreadTime().
The latter is required for benchmarks.

Bug: 73612642
Test: perfetto_unittests --gtest_filter=TimeTest*
Change-Id: I3eea8bcc3b3a98c10c1fad7d99875b5f4fd2ab2f
diff --git a/Android.bp b/Android.bp
index a820f17..9911868 100644
--- a/Android.bp
+++ b/Android.bp
@@ -3084,6 +3084,7 @@
     "src/base/test/vm_test_utils.cc",
     "src/base/thread_checker.cc",
     "src/base/thread_checker_unittest.cc",
+    "src/base/time_unittest.cc",
     "src/base/unix_task_runner.cc",
     "src/base/utils_unittest.cc",
     "src/base/watchdog.cc",
diff --git a/include/perfetto/base/BUILD.gn b/include/perfetto/base/BUILD.gn
index 1a4c10a..c9efc2d 100644
--- a/include/perfetto/base/BUILD.gn
+++ b/include/perfetto/base/BUILD.gn
@@ -22,6 +22,7 @@
     "string_splitter.h",
     "task_runner.h",
     "thread_checker.h",
+    "time.h",
     "unix_task_runner.h",
     "utils.h",
     "watchdog.h",
diff --git a/include/perfetto/base/android_task_runner.h b/include/perfetto/base/android_task_runner.h
index 37abed6..6d3fa4e 100644
--- a/include/perfetto/base/android_task_runner.h
+++ b/include/perfetto/base/android_task_runner.h
@@ -20,6 +20,7 @@
 #include "perfetto/base/scoped_file.h"
 #include "perfetto/base/task_runner.h"
 #include "perfetto/base/thread_checker.h"
+#include "perfetto/base/time.h"
 
 #include <poll.h>
 #include <chrono>
@@ -58,35 +59,6 @@
   void RemoveFileDescriptorWatch(int fd) override;
 
  private:
-  class TimePoint : public timespec {
-   public:
-    TimePoint() { tv_sec = tv_nsec = 0; }
-
-    bool operator<(const TimePoint& other) const {
-      if (tv_sec == other.tv_sec)
-        return tv_nsec < other.tv_nsec;
-      return tv_sec < other.tv_sec;
-    }
-
-    explicit operator bool() const { return tv_sec || tv_nsec; }
-
-    TimePoint AdvanceByMs(time_t ms) {
-      const time_t kSecondsPerNs = 1000000000;
-      PERFETTO_DCHECK(tv_nsec < kSecondsPerNs);
-      TimePoint result(*this);
-      time_t seconds = ms / 1000;
-      result.tv_sec += seconds;
-      ms -= seconds * 1000;
-      result.tv_nsec += ms * 1000 * 1000;
-      if (result.tv_nsec >= kSecondsPerNs) {
-        result.tv_sec++;
-        result.tv_nsec -= kSecondsPerNs;
-      }
-      return result;
-    }
-  };
-  TimePoint GetTime() const;
-
   bool OnFileDescriptorEvent(int signalled_fd, int events);
   void RunImmediateTask();
   void RunDelayedTask();
@@ -94,7 +66,7 @@
   void GetNextDelayedTaskRunTimeLocked(struct itimerspec* runtime);
 
   void ScheduleImmediateWakeUp();
-  void ScheduleDelayedWakeUp(const TimePoint& time);
+  void ScheduleDelayedWakeUp(TimeMillis time);
 
   ALooper* const looper_;
   ScopedFile immediate_event_;
@@ -107,7 +79,7 @@
   // Note: std::deque allocates blocks of 4k in some implementations. Consider
   // another data structure if we end up having many task runner instances.
   std::deque<std::function<void()>> immediate_tasks_;
-  std::multimap<TimePoint, std::function<void()>> delayed_tasks_;
+  std::multimap<TimeMillis, std::function<void()>> delayed_tasks_;
   std::map<int, std::function<void()>> watch_tasks_;
   bool quit_ = false;
   // --- End lock-protected members.
diff --git a/include/perfetto/base/time.h b/include/perfetto/base/time.h
new file mode 100644
index 0000000..d0c2744
--- /dev/null
+++ b/include/perfetto/base/time.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef INCLUDE_PERFETTO_BASE_TIME_H_
+#define INCLUDE_PERFETTO_BASE_TIME_H_
+
+#include <time.h>
+
+#include <chrono>
+
+#include "perfetto/base/logging.h"
+
+namespace perfetto {
+namespace base {
+
+using TimeMillis = std::chrono::milliseconds;
+using TimeNanos = std::chrono::nanoseconds;
+constexpr clockid_t kWallTimeClockSource = CLOCK_MONOTONIC;
+
+inline TimeNanos GetTimeInternalNs(clockid_t clk_id) {
+  struct timespec ts = {};
+  PERFETTO_CHECK(clock_gettime(clk_id, &ts) == 0);
+  return TimeNanos(ts.tv_sec * 1000000000LL + ts.tv_nsec);
+}
+
+inline TimeNanos GetWallTimeNs() {
+  return GetTimeInternalNs(kWallTimeClockSource);
+}
+
+inline TimeMillis GetWallTimeMs() {
+  return std::chrono::duration_cast<TimeMillis>(GetWallTimeNs());
+}
+
+inline TimeNanos GetThreadCPUTimeNs() {
+  return GetTimeInternalNs(CLOCK_THREAD_CPUTIME_ID);
+}
+
+inline struct timespec ToPosixTimespec(TimeMillis time) {
+  struct timespec ts {};
+  const long time_s = static_cast<long>(time.count() / 1000);
+  ts.tv_sec = time_s;
+  ts.tv_nsec = (static_cast<long>(time.count()) - time_s * 1000L) * 1000000L;
+  return ts;
+}
+
+}  // namespace base
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_BASE_TIME_H_
diff --git a/include/perfetto/base/unix_task_runner.h b/include/perfetto/base/unix_task_runner.h
index 23da0ff..0bc2f64 100644
--- a/include/perfetto/base/unix_task_runner.h
+++ b/include/perfetto/base/unix_task_runner.h
@@ -20,6 +20,7 @@
 #include "perfetto/base/scoped_file.h"
 #include "perfetto/base/task_runner.h"
 #include "perfetto/base/thread_checker.h"
+#include "perfetto/base/time.h"
 
 #include <poll.h>
 #include <chrono>
@@ -53,15 +54,11 @@
   void RemoveFileDescriptorWatch(int fd) override;
 
  private:
-  using TimePoint = std::chrono::time_point<std::chrono::steady_clock>;
-  using TimeDurationMs = std::chrono::milliseconds;
-  TimePoint GetTime() const;
-
   void WakeUp();
 
   void UpdateWatchTasksLocked();
 
-  TimeDurationMs GetDelayToNextTaskLocked() const;
+  int GetDelayMsToNextTaskLocked() const;
   void RunImmediateAndDelayedTask();
   void PostFileDescriptorWatches();
   void RunFileDescriptorWatch(int fd);
@@ -78,7 +75,7 @@
   std::mutex lock_;
 
   std::deque<std::function<void()>> immediate_tasks_;
-  std::multimap<TimePoint, std::function<void()>> delayed_tasks_;
+  std::multimap<TimeMillis, std::function<void()>> delayed_tasks_;
   bool quit_ = false;
 
   struct WatchTask {
diff --git a/src/base/BUILD.gn b/src/base/BUILD.gn
index 1c3890e..41c47d0 100644
--- a/src/base/BUILD.gn
+++ b/src/base/BUILD.gn
@@ -105,6 +105,7 @@
     "task_runner_unittest.cc",
     "temp_file_unittest.cc",
     "thread_checker_unittest.cc",
+    "time_unittest.cc",
     "utils_unittest.cc",
     "weak_ptr_unittest.cc",
   ]
diff --git a/src/base/android_task_runner.cc b/src/base/android_task_runner.cc
index 850c30e..dfd8ead 100644
--- a/src/base/android_task_runner.cc
+++ b/src/base/android_task_runner.cc
@@ -27,7 +27,7 @@
     : looper_(ALooper_prepare(0 /* require callbacks */)),
       immediate_event_(eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC)),
       delayed_timer_(
-          timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC)) {
+          timerfd_create(kWallTimeClockSource, TFD_NONBLOCK | TFD_CLOEXEC)) {
   ALooper_acquire(looper_);
   PERFETTO_CHECK(immediate_event_);
   PERFETTO_CHECK(delayed_timer_);
@@ -80,15 +80,6 @@
   return immediate_tasks_.empty();
 }
 
-AndroidTaskRunner::TimePoint AndroidTaskRunner::GetTime() const {
-  static_assert(sizeof(TimePoint) == sizeof(struct timespec),
-                "TimePoint layout must match struct timespec");
-  TimePoint now;
-  if (clock_gettime(CLOCK_MONOTONIC, &now) == -1)
-    PERFETTO_DPLOG("clock_gettime");
-  return now;
-}
-
 void AndroidTaskRunner::RunImmediateTask() {
   uint64_t unused = 0;
   if (read(immediate_event_.get(), &unused, sizeof(unused)) != sizeof(unused) &&
@@ -124,19 +115,19 @@
   }
 
   std::function<void()> delayed_task;
-  TimePoint next_wake_up;
+  TimeMillis next_wake_up{};
   {
     std::lock_guard<std::mutex> lock(lock_);
     if (delayed_tasks_.empty())
       return;
     auto it = delayed_tasks_.begin();
-    PERFETTO_DCHECK(!(GetTime() < it->first));
+    PERFETTO_DCHECK(!(GetWallTimeMs() < it->first));
     delayed_task = std::move(it->second);
     delayed_tasks_.erase(it);
     if (!delayed_tasks_.empty())
       next_wake_up = delayed_tasks_.begin()->first;
   }
-  if (next_wake_up)
+  if (next_wake_up.count())
     ScheduleDelayedWakeUp(next_wake_up);
   errno = 0;
   RunTask(delayed_task);
@@ -150,10 +141,10 @@
   }
 }
 
-void AndroidTaskRunner::ScheduleDelayedWakeUp(const TimePoint& time) {
-  PERFETTO_DCHECK(time);
+void AndroidTaskRunner::ScheduleDelayedWakeUp(TimeMillis time) {
+  PERFETTO_DCHECK(time.count());
   struct itimerspec wake_up = {};
-  wake_up.it_value = time;
+  wake_up.it_value = ToPosixTimespec(time);
   if (timerfd_settime(delayed_timer_.get(), TFD_TIMER_ABSTIME, &wake_up,
                       nullptr) == -1) {
     PERFETTO_DPLOG("timerfd_settime");
@@ -174,7 +165,7 @@
 void AndroidTaskRunner::PostDelayedTask(std::function<void()> task,
                                         int delay_ms) {
   PERFETTO_DCHECK(delay_ms >= 0);
-  auto runtime = GetTime().AdvanceByMs(delay_ms);
+  TimeMillis runtime = GetWallTimeMs() + TimeMillis(delay_ms);
   bool is_next = false;
   {
     std::lock_guard<std::mutex> lock(lock_);
diff --git a/src/base/time_unittest.cc b/src/base/time_unittest.cc
new file mode 100644
index 0000000..0a89632
--- /dev/null
+++ b/src/base/time_unittest.cc
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "perfetto/base/time.h"
+
+#include "gtest/gtest.h"
+
+namespace perfetto {
+namespace base {
+namespace {
+
+TEST(TimeTest, Conversions) {
+  TimeMillis ms = GetWallTimeMs();
+  TimeNanos ns = GetWallTimeNs();
+  EXPECT_NEAR(ms.count(), ns.count() / 1000000, 1000);
+
+  {
+    struct timespec ts = ToPosixTimespec(TimeMillis(0));
+    EXPECT_EQ(0, ts.tv_sec);
+    EXPECT_EQ(0, ts.tv_nsec);
+  }
+  {
+    struct timespec ts = ToPosixTimespec(TimeMillis(1));
+    EXPECT_EQ(0, ts.tv_sec);
+    EXPECT_EQ(1000000, ts.tv_nsec);
+  }
+  {
+    struct timespec ts = ToPosixTimespec(TimeMillis(12345));
+    EXPECT_EQ(12, ts.tv_sec);
+    EXPECT_EQ(345000000, ts.tv_nsec);
+  }
+  {
+    struct timespec ts = ToPosixTimespec(TimeMillis(1000000000001LL));
+    EXPECT_EQ(1000000000, ts.tv_sec);
+    EXPECT_EQ(1000000, ts.tv_nsec);
+  }
+}
+
+}  // namespace
+}  // namespace base
+}  // namespace perfetto
diff --git a/src/base/unix_task_runner.cc b/src/base/unix_task_runner.cc
index d182e63..76b344b 100644
--- a/src/base/unix_task_runner.cc
+++ b/src/base/unix_task_runner.cc
@@ -23,6 +23,8 @@
 #include <stdlib.h>
 #include <unistd.h>
 
+#include <limits>
+
 namespace perfetto {
 namespace base {
 
@@ -58,10 +60,6 @@
 
 UnixTaskRunner::~UnixTaskRunner() = default;
 
-UnixTaskRunner::TimePoint UnixTaskRunner::GetTime() const {
-  return std::chrono::steady_clock::now();
-}
-
 void UnixTaskRunner::WakeUp() {
   const char dummy = 'P';
   if (write(control_write_.get(), &dummy, 1) <= 0 && errno != EAGAIN)
@@ -77,7 +75,7 @@
       std::lock_guard<std::mutex> lock(lock_);
       if (quit_)
         return;
-      poll_timeout_ms = static_cast<int>(GetDelayToNextTaskLocked().count());
+      poll_timeout_ms = GetDelayMsToNextTaskLocked();
       UpdateWatchTasksLocked();
     }
     int ret = PERFETTO_EINTR(poll(
@@ -121,7 +119,7 @@
   // becomes an issue.
   std::function<void()> immediate_task;
   std::function<void()> delayed_task;
-  auto now = GetTime();
+  TimeMillis now = GetWallTimeMs();
   {
     std::lock_guard<std::mutex> lock(lock_);
     if (!immediate_tasks_.empty()) {
@@ -197,17 +195,15 @@
   RunTask(task);
 }
 
-UnixTaskRunner::TimeDurationMs UnixTaskRunner::GetDelayToNextTaskLocked()
-    const {
+int UnixTaskRunner::GetDelayMsToNextTaskLocked() const {
   PERFETTO_DCHECK_THREAD(thread_checker_);
   if (!immediate_tasks_.empty())
-    return TimeDurationMs(0);
+    return 0;
   if (!delayed_tasks_.empty()) {
-    return std::max(TimeDurationMs(0),
-                    std::chrono::duration_cast<TimeDurationMs>(
-                        delayed_tasks_.begin()->first - GetTime()));
+    TimeMillis diff = delayed_tasks_.begin()->first - GetWallTimeMs();
+    return std::max(0, static_cast<int>(diff.count()));
   }
-  return TimeDurationMs(-1);
+  return -1;
 }
 
 void UnixTaskRunner::PostTask(std::function<void()> task) {
@@ -223,7 +219,7 @@
 
 void UnixTaskRunner::PostDelayedTask(std::function<void()> task, int delay_ms) {
   PERFETTO_DCHECK(delay_ms >= 0);
-  auto runtime = GetTime() + std::chrono::milliseconds(delay_ms);
+  TimeMillis runtime = GetWallTimeMs() + TimeMillis(delay_ms);
   {
     std::lock_guard<std::mutex> lock(lock_);
     delayed_tasks_.insert(std::make_pair(runtime, std::move(task)));
diff --git a/src/ftrace_reader/ftrace_controller.cc b/src/ftrace_reader/ftrace_controller.cc
index da49221..cf4c80b 100644
--- a/src/ftrace_reader/ftrace_controller.cc
+++ b/src/ftrace_reader/ftrace_controller.cc
@@ -30,6 +30,7 @@
 
 #include "perfetto/base/build_config.h"
 #include "perfetto/base/logging.h"
+#include "perfetto/base/time.h"
 #include "perfetto/base/utils.h"
 #include "src/ftrace_reader/cpu_reader.h"
 #include "src/ftrace_reader/event_info.h"
@@ -142,9 +143,7 @@
 }
 
 uint64_t FtraceController::NowMs() const {
-  timespec now;
-  clock_gettime(CLOCK_MONOTONIC, &now);
-  return (now.tv_sec * 1000000000L + now.tv_nsec) / 1000000L;
+  return base::GetWallTimeMs().count();
 }
 
 // static