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/. */
8 * Implementation of the OS-independent methods of the TimeStamp class
11 #include "mozilla/TimeStamp.h"
12 #include "mozilla/Uptime.h"
19 * Wrapper class used to initialize static data used by the TimeStamp class
21 struct TimeStampInitialization
{
23 * First timestamp taken when the class static initializers are run. This
24 * timestamp is used to sanitize timestamps coming from different sources.
26 TimeStamp mFirstTimeStamp
;
29 * Timestamp representing the time when the process was created. This field
30 * is populated lazily the first time this information is required and is
31 * replaced every time the process is restarted.
33 TimeStamp mProcessCreation
;
35 TimeStampInitialization() {
37 mFirstTimeStamp
= TimeStamp::Now();
38 // On Windows < 10, initializing the uptime requires `mFirstTimeStamp` to be
40 mozilla::InitializeUptime();
43 ~TimeStampInitialization() { TimeStamp::Shutdown(); }
46 static TimeStampInitialization sInitOnce
;
48 MFBT_API TimeStamp
TimeStamp::ProcessCreation() {
49 if (sInitOnce
.mProcessCreation
.IsNull()) {
50 char* mozAppRestart
= getenv("MOZ_APP_RESTART");
53 /* When calling PR_SetEnv() with an empty value the existing variable may
54 * be unset or set to the empty string depending on the underlying platform
55 * thus we have to check if the variable is present and not empty. */
56 if (mozAppRestart
&& (strcmp(mozAppRestart
, "") != 0)) {
57 /* Firefox was restarted, use the first time-stamp we've taken as the new
58 * process startup time. */
59 ts
= sInitOnce
.mFirstTimeStamp
;
61 TimeStamp now
= Now();
62 uint64_t uptime
= ComputeProcessUptime();
64 ts
= now
- TimeDuration::FromMicroseconds(static_cast<double>(uptime
));
66 if ((ts
> sInitOnce
.mFirstTimeStamp
) || (uptime
== 0)) {
67 ts
= sInitOnce
.mFirstTimeStamp
;
71 sInitOnce
.mProcessCreation
= ts
;
74 return sInitOnce
.mProcessCreation
;
77 void TimeStamp::RecordProcessRestart() {
78 sInitOnce
.mProcessCreation
= TimeStamp();
81 MFBT_API TimeStamp
TimeStamp::FirstTimeStamp() {
82 return sInitOnce
.mFirstTimeStamp
;
85 class TimeStampTests
{
86 // Check that nullity is set/not set correctly.
87 static_assert(TimeStamp
{TimeStampValue
{0}}.IsNull());
88 static_assert(!TimeStamp
{TimeStampValue
{1}}.IsNull());
90 // Check that some very basic comparisons work correctly.
91 static constexpr uint64_t sMidTime
= (uint64_t)1 << 63;
92 static_assert(TimeStampValue
{sMidTime
+ 5} > TimeStampValue
{sMidTime
- 5});
93 static_assert(TimeStampValue
{sMidTime
+ 5} >= TimeStampValue
{sMidTime
- 5});
94 static_assert(TimeStampValue
{sMidTime
- 5} < TimeStampValue
{sMidTime
+ 5});
95 static_assert(TimeStampValue
{sMidTime
- 5} <= TimeStampValue
{sMidTime
+ 5});
96 static_assert(TimeStampValue
{sMidTime
} == TimeStampValue
{sMidTime
});
97 static_assert(TimeStampValue
{sMidTime
} >= TimeStampValue
{sMidTime
});
98 static_assert(TimeStampValue
{sMidTime
} <= TimeStampValue
{sMidTime
});
99 static_assert(TimeStampValue
{sMidTime
- 5} != TimeStampValue
{sMidTime
+ 5});
101 // Check that comparisons involving very large and very small TimeStampValue's
102 // work correctly. This may seem excessive, but these asserts would have
103 // failed in the past due to a comparison such as "a > b" being implemented as
104 // "<cast to signed 64-bit value>(a - b) > 0". When a-b didn't fit into a
105 // signed 64-bit value, this would have given an incorrect result.
106 static_assert(TimeStampValue
{UINT64_MAX
} > TimeStampValue
{1});
107 static_assert(TimeStampValue
{1} < TimeStampValue
{UINT64_MAX
});
109 // NOTE/TODO: It would be nice to add some additional tests here that involve
110 // arithmetic between TimeStamps and TimeDurations (and verifying some of the
111 // special behaviors in some cases such as not wrapping around below zero) but
112 // that is not possible right now because those operators are not constexpr.
115 } // namespace mozilla