blob: d90d3786f2eb854bbaba44adb477deb7ba2e9169 [file] [log] [blame]
Primiano Tucci8934c6c2018-03-15 11:39:27 +00001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef INCLUDE_PERFETTO_BASE_TIME_H_
18#define INCLUDE_PERFETTO_BASE_TIME_H_
19
20#include <time.h>
21
22#include <chrono>
23
Oystein Eftevaag4966fdc2018-03-28 10:20:59 -070024#include "perfetto/base/build_config.h"
Primiano Tucci8934c6c2018-03-15 11:39:27 +000025#include "perfetto/base/logging.h"
26
Oystein Eftevaag4966fdc2018-03-28 10:20:59 -070027#if PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
Primiano Tucci808d6df2018-03-31 13:24:18 +010028#include <mach/mach_init.h>
29#include <mach/mach_port.h>
Oystein Eftevaag4966fdc2018-03-28 10:20:59 -070030#include <mach/mach_time.h>
Primiano Tucci808d6df2018-03-31 13:24:18 +010031#include <mach/thread_act.h>
Oystein Eftevaag4966fdc2018-03-28 10:20:59 -070032#endif
33
Primiano Tucci8934c6c2018-03-15 11:39:27 +000034namespace perfetto {
35namespace base {
36
Hector Dearman86cfbe12018-03-22 11:58:42 +000037using TimeSeconds = std::chrono::seconds;
Primiano Tucci8934c6c2018-03-15 11:39:27 +000038using TimeMillis = std::chrono::milliseconds;
39using TimeNanos = std::chrono::nanoseconds;
Primiano Tucci8934c6c2018-03-15 11:39:27 +000040
Sami Kyostilafbccb3c2018-03-21 14:00:47 +000041inline TimeNanos FromPosixTimespec(const struct timespec& ts) {
42 return TimeNanos(ts.tv_sec * 1000000000LL + ts.tv_nsec);
43}
44
Oystein Eftevaag4966fdc2018-03-28 10:20:59 -070045#if !PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
46
47constexpr clockid_t kWallTimeClockSource = CLOCK_MONOTONIC;
48
Primiano Tucci8934c6c2018-03-15 11:39:27 +000049inline TimeNanos GetTimeInternalNs(clockid_t clk_id) {
50 struct timespec ts = {};
51 PERFETTO_CHECK(clock_gettime(clk_id, &ts) == 0);
Sami Kyostilafbccb3c2018-03-21 14:00:47 +000052 return FromPosixTimespec(ts);
Primiano Tucci8934c6c2018-03-15 11:39:27 +000053}
54
55inline TimeNanos GetWallTimeNs() {
56 return GetTimeInternalNs(kWallTimeClockSource);
57}
58
Oystein Eftevaag4966fdc2018-03-28 10:20:59 -070059inline TimeNanos GetThreadCPUTimeNs() {
60 return GetTimeInternalNs(CLOCK_THREAD_CPUTIME_ID);
61}
62
63#else // !PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
64
65inline TimeNanos GetWallTimeNs() {
66 auto init_time_factor = []() -> uint64_t {
67 mach_timebase_info_data_t timebase_info;
68 mach_timebase_info(&timebase_info);
69 return timebase_info.numer / timebase_info.denom;
Primiano Tucci9daa4832018-03-28 23:28:17 +010070 };
Oystein Eftevaag4966fdc2018-03-28 10:20:59 -070071
72 static uint64_t monotonic_timebase_factor = init_time_factor();
73 return TimeNanos(mach_absolute_time() * monotonic_timebase_factor);
74}
75
Primiano Tucci808d6df2018-03-31 13:24:18 +010076inline TimeNanos GetThreadCPUTimeNs() {
77 mach_port_t this_thread = mach_thread_self();
78 mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
79 thread_basic_info_data_t info{};
80 kern_return_t kr =
81 thread_info(this_thread, THREAD_BASIC_INFO,
82 reinterpret_cast<thread_info_t>(&info), &count);
83 mach_port_deallocate(mach_task_self(), this_thread);
84
85 if (kr != KERN_SUCCESS) {
86 PERFETTO_DCHECK(false);
87 return TimeNanos(0);
88 }
89 return TimeNanos(info.user_time.seconds * 1000000000LL +
90 info.user_time.microseconds * 1000LL +
91 info.system_time.seconds * 1000000000LL +
92 info.system_time.microseconds * 1000LL);
93}
94
Oystein Eftevaag4966fdc2018-03-28 10:20:59 -070095#endif // !PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
96
Primiano Tucci8934c6c2018-03-15 11:39:27 +000097inline TimeMillis GetWallTimeMs() {
98 return std::chrono::duration_cast<TimeMillis>(GetWallTimeNs());
99}
100
Hector Dearman86cfbe12018-03-22 11:58:42 +0000101inline TimeSeconds GetWallTimeS() {
102 return std::chrono::duration_cast<TimeSeconds>(GetWallTimeNs());
103}
104
Primiano Tucci8934c6c2018-03-15 11:39:27 +0000105inline struct timespec ToPosixTimespec(TimeMillis time) {
106 struct timespec ts {};
107 const long time_s = static_cast<long>(time.count() / 1000);
108 ts.tv_sec = time_s;
109 ts.tv_nsec = (static_cast<long>(time.count()) - time_s * 1000L) * 1000000L;
110 return ts;
111}
112
113} // namespace base
114} // namespace perfetto
115
116#endif // INCLUDE_PERFETTO_BASE_TIME_H_