Bug 1865597 - Add error checking when initializing parallel marking and disable on...
[gecko.git] / mozglue / misc / Uptime.cpp
blob924b1543591e240ca24f9f3c9cf42ce8aac37a90
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/. */
7 #include "Uptime.h"
9 #ifdef XP_WIN
10 # include "mozilla/DynamicallyLinkedFunctionPtr.h"
11 #endif // XP_WIN
13 #include <stdint.h>
15 #include "mozilla/TimeStamp.h"
16 #include "mozilla/Maybe.h"
17 #include "mozilla/Assertions.h"
19 using namespace mozilla;
21 namespace {
23 Maybe<uint64_t> NowIncludingSuspendMs();
24 Maybe<uint64_t> NowExcludingSuspendMs();
25 static Maybe<uint64_t> mStartExcludingSuspendMs;
26 static Maybe<uint64_t> mStartIncludingSuspendMs;
28 // Apple things
29 #if defined(__APPLE__) && defined(__MACH__)
30 # include <time.h>
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);
45 #elif defined(XP_WIN)
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)) {
53 return Nothing();
55 return Some(interrupt_time / kHNSperMS);
58 Maybe<uint64_t> NowIncludingSuspendMs() {
59 static const mozilla::StaticDynamicallyLinkedFunctionPtr<void(WINAPI*)(
60 PULONGLONG)>
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()));
69 } else {
70 return Nothing();
73 ULONGLONG interrupt_time;
74 pQueryInterruptTime(&interrupt_time);
75 return Some(interrupt_time / kHNSperMS);
78 #elif defined(XP_UNIX) // including BSDs and Android
79 # include <time.h>
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};
91 # ifdef XP_OPENBSD
92 if (clock_gettime(CLOCK_UPTIME, &ts)) {
93 # else
94 if (clock_gettime(CLOCK_MONOTONIC, &ts)) {
95 # endif
96 return Nothing();
98 return Some(TimespecToMilliseconds(ts));
101 Maybe<uint64_t> NowIncludingSuspendMs() {
102 # ifndef CLOCK_BOOTTIME
103 return Nothing();
104 # else
105 struct timespec ts = {0};
107 if (clock_gettime(CLOCK_BOOTTIME, &ts)) {
108 return Nothing();
110 return Some(TimespecToMilliseconds(ts));
111 # endif
114 #else // catch all
116 Maybe<uint64_t> NowExcludingSuspendMs() { return Nothing(); }
117 Maybe<uint64_t> NowIncludingSuspendMs() { return Nothing(); }
119 #endif
121 }; // anonymous namespace
123 namespace mozilla {
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) {
135 return Nothing();
137 Maybe<uint64_t> maybeNow = NowIncludingSuspendMs();
138 if (!maybeNow) {
139 return Nothing();
141 return Some(maybeNow.value() - mStartIncludingSuspendMs.value());
144 Maybe<uint64_t> ProcessUptimeExcludingSuspendMs() {
145 if (!mStartExcludingSuspendMs) {
146 return Nothing();
148 Maybe<uint64_t> maybeNow = NowExcludingSuspendMs();
149 if (!maybeNow) {
150 return Nothing();
152 return Some(maybeNow.value() - mStartExcludingSuspendMs.value());
155 }; // namespace mozilla