1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
10 # include "mozilla/DynamicallyLinkedFunctionPtr.h"
15 #include "mozilla/TimeStamp.h"
16 #include "mozilla/Maybe.h"
17 #include "mozilla/Assertions.h"
19 using namespace mozilla
;
23 Maybe
<uint64_t> NowIncludingSuspendMs();
24 Maybe
<uint64_t> NowExcludingSuspendMs();
25 static Maybe
<uint64_t> mStartExcludingSuspendMs
;
26 static Maybe
<uint64_t> mStartIncludingSuspendMs
;
29 #if defined(__APPLE__) && defined(__MACH__)
31 # include <sys/time.h>
32 # include <sys/types.h>
33 # include <mach/mach_time.h>
35 const uint64_t kNSperMS
= 1000000;
37 Maybe
<uint64_t> NowExcludingSuspendMs() {
38 return Some(clock_gettime_nsec_np(CLOCK_UPTIME_RAW
) / kNSperMS
);
41 Maybe
<uint64_t> NowIncludingSuspendMs() {
42 return Some(clock_gettime_nsec_np(CLOCK_MONOTONIC_RAW
) / kNSperMS
);
47 // Number of hundreds of nanoseconds in a millisecond
48 static constexpr uint64_t kHNSperMS
= 10000;
50 Maybe
<uint64_t> NowExcludingSuspendMs() {
51 ULONGLONG interrupt_time
;
52 if (!QueryUnbiasedInterruptTime(&interrupt_time
)) {
55 return Some(interrupt_time
/ kHNSperMS
);
58 Maybe
<uint64_t> NowIncludingSuspendMs() {
59 static const mozilla::StaticDynamicallyLinkedFunctionPtr
<void(WINAPI
*)(
61 pQueryInterruptTime(L
"KernelBase.dll", "QueryInterruptTime");
62 if (!pQueryInterruptTime
) {
63 // On Windows, this does include the time the computer was suspended so it's
64 // an adequate fallback.
65 TimeStamp processCreation
= TimeStamp::ProcessCreation();
66 TimeStamp now
= TimeStamp::Now();
67 if (!processCreation
.IsNull() && !now
.IsNull()) {
68 return Some(uint64_t((now
- processCreation
).ToMilliseconds()));
73 ULONGLONG interrupt_time
;
74 pQueryInterruptTime(&interrupt_time
);
75 return Some(interrupt_time
/ kHNSperMS
);
78 #elif defined(XP_UNIX) // including BSDs and Android
81 // Number of nanoseconds in a millisecond.
82 static constexpr uint64_t kNSperMS
= 1000000;
84 uint64_t TimespecToMilliseconds(struct timespec aTs
) {
85 return aTs
.tv_sec
* 1000 + aTs
.tv_nsec
/ kNSperMS
;
88 Maybe
<uint64_t> NowExcludingSuspendMs() {
89 struct timespec ts
= {0};
92 if (clock_gettime(CLOCK_UPTIME
, &ts
)) {
94 if (clock_gettime(CLOCK_MONOTONIC
, &ts
)) {
98 return Some(TimespecToMilliseconds(ts
));
101 Maybe
<uint64_t> NowIncludingSuspendMs() {
102 # ifndef CLOCK_BOOTTIME
105 struct timespec ts
= {0};
107 if (clock_gettime(CLOCK_BOOTTIME
, &ts
)) {
110 return Some(TimespecToMilliseconds(ts
));
116 Maybe
<uint64_t> NowExcludingSuspendMs() { return Nothing(); }
117 Maybe
<uint64_t> NowIncludingSuspendMs() { return Nothing(); }
121 }; // anonymous namespace
125 void InitializeUptime() {
126 MOZ_RELEASE_ASSERT(mStartIncludingSuspendMs
.isNothing() &&
127 mStartExcludingSuspendMs
.isNothing(),
128 "Must not be called more than once");
129 mStartIncludingSuspendMs
= NowIncludingSuspendMs();
130 mStartExcludingSuspendMs
= NowExcludingSuspendMs();
133 Maybe
<uint64_t> ProcessUptimeMs() {
134 if (!mStartIncludingSuspendMs
) {
137 Maybe
<uint64_t> maybeNow
= NowIncludingSuspendMs();
141 return Some(maybeNow
.value() - mStartIncludingSuspendMs
.value());
144 Maybe
<uint64_t> ProcessUptimeExcludingSuspendMs() {
145 if (!mStartExcludingSuspendMs
) {
148 Maybe
<uint64_t> maybeNow
= NowExcludingSuspendMs();
152 return Some(maybeNow
.value() - mStartExcludingSuspendMs
.value());
155 }; // namespace mozilla