diff --git a/xpcom/ds/TimeStamp.cpp b/xpcom/ds/TimeStamp.cpp new file mode 100644 index 00000000000..ac8c97c4c26 --- /dev/null +++ b/xpcom/ds/TimeStamp.cpp @@ -0,0 +1,64 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Implementation of the OS-independent methods of the TimeStamp class + */ + +#include "mozilla/TimeStamp.h" +#include "prenv.h" + +namespace mozilla { + +TimeStamp TimeStamp::sFirstTimeStamp; +TimeStamp TimeStamp::sProcessCreation; + +TimeStamp +TimeStamp::ProcessCreation(bool& aIsInconsistent) +{ + aIsInconsistent = false; + + if (sProcessCreation.IsNull()) { + char *mozAppRestart = PR_GetEnv("MOZ_APP_RESTART"); + TimeStamp ts; + + /* When calling PR_SetEnv() with an empty value the existing variable may + * be unset or set to the empty string depending on the underlying platform + * thus we have to check if the variable is present and not empty. */ + if (mozAppRestart && (strcmp(mozAppRestart, "") != 0)) { + /* Firefox was restarted, use the first time-stamp we've taken as the new + * process startup time and unset MOZ_APP_RESTART. */ + ts = sFirstTimeStamp; + PR_SetEnv("MOZ_APP_RESTART="); + } else { + TimeStamp now = Now(); + uint64_t uptime = ComputeProcessUptime(); + + ts = now - TimeDuration::FromMicroseconds(uptime); + + if ((ts > sFirstTimeStamp) || (uptime == 0)) { + /* If the process creation timestamp was inconsistent replace it with + * the first one instead and notify that a telemetry error was + * detected. */ + aIsInconsistent = true; + ts = sFirstTimeStamp; + } + } + + sProcessCreation = ts; + } + + return sProcessCreation; +} + +void +TimeStamp::RecordProcessRestart() +{ + PR_SetEnv("MOZ_APP_RESTART=1"); + sProcessCreation = TimeStamp(); +} + +} // namespace mozilla diff --git a/xpcom/ds/TimeStamp.h b/xpcom/ds/TimeStamp.h index 23bbdec8551..feb13b9a037 100644 --- a/xpcom/ds/TimeStamp.h +++ b/xpcom/ds/TimeStamp.h @@ -342,6 +342,16 @@ private: static TimeStamp Now(bool aHighResolution); + /** + * Computes the uptime of the current process in microseconds. The result + * is platform-dependent and needs to be checked against existing timestamps + * for consistency. + * + * @returns The number of microseconds since the calling process was started + * or 0 if an error was encountered while computing the uptime + */ + static uint64_t ComputeProcessUptime(); + /** * When built with PRIntervalTime, a value of 0 means this instance * is "null". Otherwise, the low 32 bits represent a PRIntervalTime, diff --git a/xpcom/ds/TimeStamp_darwin.cpp b/xpcom/ds/TimeStamp_darwin.cpp index a5dc5a8ff88..b2bd1f68629 100644 --- a/xpcom/ds/TimeStamp_darwin.cpp +++ b/xpcom/ds/TimeStamp_darwin.cpp @@ -24,7 +24,6 @@ #include "mozilla/TimeStamp.h" #include "nsCRT.h" -#include "prenv.h" #include "prprf.h" // Estimate of the smallest duration of time we can measure. @@ -83,9 +82,6 @@ ClockResolutionNs() namespace mozilla { -TimeStamp TimeStamp::sFirstTimeStamp; -TimeStamp TimeStamp::sProcessCreation; - double TimeDuration::ToSeconds() const { @@ -176,8 +172,8 @@ TimeStamp::Now(bool aHighResolution) // Computes and returns the process uptime in microseconds. // Returns 0 if an error was encountered. -static uint64_t -ComputeProcessUptime() +uint64_t +TimeStamp::ComputeProcessUptime() { struct timeval tv; int rv = gettimeofday(&tv, NULL); @@ -212,42 +208,4 @@ ComputeProcessUptime() return now - startTime; } -TimeStamp -TimeStamp::ProcessCreation(bool& aIsInconsistent) -{ - aIsInconsistent = false; - - if (sProcessCreation.IsNull()) { - char *mozAppRestart = PR_GetEnv("MOZ_APP_RESTART"); - TimeStamp ts; - - if (mozAppRestart) { - ts = TimeStamp(nsCRT::atoll(mozAppRestart)); - } else { - TimeStamp now = TimeStamp::Now(); - uint64_t uptime = ComputeProcessUptime(); - - ts = now - TimeDuration::FromMicroseconds(uptime); - - if ((ts > sFirstTimeStamp) || (uptime == 0)) { - // If the process creation timestamp was inconsistent replace it with the - // first one instead and notify that a telemetry error was detected. - aIsInconsistent = true; - ts = sFirstTimeStamp; - } - } - - sProcessCreation = ts; - } - - return sProcessCreation; -} - -void -TimeStamp::RecordProcessRestart() -{ - PR_SetEnv(PR_smprintf("MOZ_APP_RESTART=%lld", ClockTime())); - sProcessCreation = TimeStamp(); -} - -} +} // namespace mozilla diff --git a/xpcom/ds/TimeStamp_posix.cpp b/xpcom/ds/TimeStamp_posix.cpp index e3d090cf35f..c3af5922772 100644 --- a/xpcom/ds/TimeStamp_posix.cpp +++ b/xpcom/ds/TimeStamp_posix.cpp @@ -48,7 +48,6 @@ #include "mozilla/TimeStamp.h" #include "nsCRT.h" -#include "prenv.h" #include "prprf.h" #include "prthread.h" @@ -132,9 +131,6 @@ ClockResolutionNs() namespace mozilla { -TimeStamp TimeStamp::sFirstTimeStamp; -TimeStamp TimeStamp::sProcessCreation; - double TimeDuration::ToSeconds() const { @@ -283,11 +279,11 @@ ComputeProcessUptimeThread(void *aTime) *uptime = ((threadJiffies - selfJiffies) * kNsPerSec) / hz; } -// Computes and returns the process uptime in ns on Linux & its derivatives. +// Computes and returns the process uptime in us on Linux & its derivatives. // Returns 0 if an error was encountered. -static uint64_t -ComputeProcessUptime() +uint64_t +TimeStamp::ComputeProcessUptime() { uint64_t uptime = 0; PRThread *thread = PR_CreateThread(PR_USER_THREAD, @@ -300,17 +296,17 @@ ComputeProcessUptime() PR_JoinThread(thread); - return uptime; + return uptime / kNsPerUs; } #elif defined(__DragonFly__) || defined(__FreeBSD__) \ || defined(__NetBSD__) || defined(__OpenBSD__) -// Computes and returns the process uptime in ns on various BSD flavors. +// Computes and returns the process uptime in us on various BSD flavors. // Returns 0 if an error was encountered. -static uint64_t -ComputeProcessUptime() +uint64_t +TimeStamp::ComputeProcessUptime() { struct timespec ts; int rv = clock_gettime(CLOCK_REALTIME, &ts); @@ -345,55 +341,17 @@ ComputeProcessUptime() if (startTime > now) return 0; - return (now - startTime); + return (now - startTime) / kNsPerUs; } #else -static uint64_t -ComputeProcessUptime() +uint64_t +TimeStamp::ComputeProcessUptime() { return 0; } #endif -TimeStamp -TimeStamp::ProcessCreation(bool& aIsInconsistent) -{ - aIsInconsistent = false; - - if (sProcessCreation.IsNull()) { - char *mozAppRestart = PR_GetEnv("MOZ_APP_RESTART"); - TimeStamp ts; - - if (mozAppRestart) { - ts = TimeStamp(nsCRT::atoll(mozAppRestart)); - } else { - TimeStamp now = TimeStamp::Now(); - uint64_t uptime = ComputeProcessUptime(); - - ts = now - TimeDuration::FromMicroseconds(uptime / 1000); - - if ((ts > sFirstTimeStamp) || (uptime == 0)) { - // If the process creation timestamp was inconsistent replace it with the - // first one instead and notify that a telemetry error was detected. - aIsInconsistent = true; - ts = sFirstTimeStamp; - } - } - - sProcessCreation = ts; - } - - return sProcessCreation; -} - -void -TimeStamp::RecordProcessRestart() -{ - PR_SetEnv(PR_smprintf("MOZ_APP_RESTART=%lld", ClockTimeNs())); - sProcessCreation = TimeStamp(); -} - -} +} // namespace mozilla diff --git a/xpcom/ds/TimeStamp_windows.cpp b/xpcom/ds/TimeStamp_windows.cpp index 93f519d883b..55a876d2811 100644 --- a/xpcom/ds/TimeStamp_windows.cpp +++ b/xpcom/ds/TimeStamp_windows.cpp @@ -18,7 +18,6 @@ #include "nsCRT.h" #include "prlog.h" -#include "prenv.h" #include "prprf.h" #include @@ -183,9 +182,6 @@ static DWORD sLastGTCRollover = 0; namespace mozilla { -TimeStamp TimeStamp::sFirstTimeStamp; -TimeStamp TimeStamp::sProcessCreation; - typedef ULONGLONG (WINAPI* GetTickCount64_t)(); static GetTickCount64_t sGetTickCount64 = nullptr; @@ -562,11 +558,11 @@ TimeStamp::Now(bool aHighResolution) return TimeStamp(TimeStampValue(GTC, QPC, useQPC)); } -// Computes and returns the current process uptime in microseconds. -// Returns 0 if an error was encountered while computing the uptime. +// Computes and returns the process uptime in microseconds. +// Returns 0 if an error was encountered. -static uint64_t -ComputeProcessUptime() +uint64_t +TimeStamp::ComputeProcessUptime() { SYSTEMTIME nowSys; GetSystemTime(&nowSys); @@ -595,41 +591,4 @@ ComputeProcessUptime() return (nowUsec.QuadPart - startUsec.QuadPart) / 10ULL; } -TimeStamp -TimeStamp::ProcessCreation(bool& aIsInconsistent) -{ - aIsInconsistent = false; - - if (sProcessCreation.IsNull()) { - char *mozAppRestart = PR_GetEnv("MOZ_APP_RESTART"); - TimeStamp ts; - - if (mozAppRestart) { - ts = TimeStamp(TimeStampValue(nsCRT::atoll(mozAppRestart), 0, false)); - } else { - TimeStamp now = TimeStamp::Now(); - uint64_t uptime = ComputeProcessUptime(); - ts = now - TimeDuration::FromMicroseconds(static_cast(uptime)); - - if ((ts > sFirstTimeStamp) || (uptime == 0)) { - // If the process creation timestamp was inconsistent replace it with the - // first one instead and notify that a telemetry error was detected. - aIsInconsistent = true; - ts = sFirstTimeStamp; - } - } - - sProcessCreation = ts; - } - - return sProcessCreation; -} - -void -TimeStamp::RecordProcessRestart() -{ - PR_SetEnv(PR_smprintf("MOZ_APP_RESTART=%lld", ms2mt(sGetTickCount64()))); - sProcessCreation = TimeStamp(); -} - } // namespace mozilla diff --git a/xpcom/ds/moz.build b/xpcom/ds/moz.build index af6a5a16abe..cd4b7825d36 100644 --- a/xpcom/ds/moz.build +++ b/xpcom/ds/moz.build @@ -95,6 +95,7 @@ CPP_SOURCES += [ 'nsSupportsPrimitives.cpp', 'nsUnicharBuffer.cpp', 'nsVariant.cpp', + 'TimeStamp.cpp', ] if CONFIG['OS_ARCH'] == 'WINNT':