Skip to content

Commit

Permalink
Bug 1432429 - Integrate FuzzyFox into the TimeStamp class. r=baku,fro…
Browse files Browse the repository at this point in the history
…ydnj

Creates GetFuzzyfoxEnabled() functions that check a static boolean.
Exposes SetFuzzyfoxEnabled() because we cannot depend on Pref
Observation code inside the TimeStamp class.

TimeStamp::Now will now return a Fuzzy value.

We add a NowReally function to support obtaining the real timestamp.

We also add a UsedCanonicalNow to expose whether the TimeStamp was real or fuzzy.
  • Loading branch information
tomrittervg committed Oct 9, 2018
1 parent b83b9c5 commit 61ca4f1
Show file tree
Hide file tree
Showing 7 changed files with 230 additions and 26 deletions.
34 changes: 31 additions & 3 deletions ipc/glue/IPCMessageUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -827,15 +827,43 @@ struct ParamTraits<mozilla::TimeStampValue>
{
WriteParam(aMsg, aParam.mGTC);
WriteParam(aMsg, aParam.mQPC);
WriteParam(aMsg, aParam.mHasQPC);
WriteParam(aMsg, aParam.mUsedCanonicalNow);
WriteParam(aMsg, aParam.mIsNull);
WriteParam(aMsg, aParam.mHasQPC);
}
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
{
return (ReadParam(aMsg, aIter, &aResult->mGTC) &&
ReadParam(aMsg, aIter, &aResult->mQPC) &&
ReadParam(aMsg, aIter, &aResult->mHasQPC) &&
ReadParam(aMsg, aIter, &aResult->mIsNull));
ReadParam(aMsg, aIter, &aResult->mUsedCanonicalNow) &&
ReadParam(aMsg, aIter, &aResult->mIsNull) &&
ReadParam(aMsg, aIter, &aResult->mHasQPC));
}
};

#else

template<>
struct ParamTraits<mozilla::TimeStamp63Bit>
{
typedef mozilla::TimeStamp63Bit paramType;
static void Write(Message* aMsg, const paramType& aParam)
{
WriteParam(aMsg, aParam.mUsedCanonicalNow);
WriteParam(aMsg, aParam.mTimeStamp);
}
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
{
bool success = true;
uint64_t result;

success &= ReadParam(aMsg, aIter, &result);
aResult->mUsedCanonicalNow = result & 0x01;

success &= ReadParam(aMsg, aIter, &result);
aResult->mTimeStamp = result & 0x7FFFFFFFFFFFFFFF;

return success;
}
};

Expand Down
63 changes: 63 additions & 0 deletions mozglue/misc/TimeStamp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* Implementation of the OS-independent methods of the TimeStamp class
*/

#include "mozilla/Atomics.h"
#include "mozilla/TimeStamp.h"
#include <stdio.h>
#include <string.h>
Expand Down Expand Up @@ -45,6 +46,33 @@ struct TimeStampInitialization
};
};

static bool sFuzzyfoxEnabled;

/* static */ bool
TimeStamp::GetFuzzyfoxEnabled()
{
return sFuzzyfoxEnabled;
}

/* static */ void
TimeStamp::SetFuzzyfoxEnabled(bool aValue)
{
sFuzzyfoxEnabled = aValue;
}

// These variables store the frozen time (as a TimeStamp) for FuzzyFox that
// will be reported if FuzzyFox is enabled.
// We overload the top bit of sCanonicalNow and sCanonicalGTC to
// indicate if a Timestamp is a fuzzed timestamp (bit set) or not
// (bit unset).
#ifdef XP_WIN
static Atomic<uint64_t> sCanonicalGTC;
static Atomic<uint64_t> sCanonicalQPC;
static Atomic<bool> sCanonicalHasQPC;
#else
static Atomic<uint64_t> sCanonicalNow;
#endif

static TimeStampInitialization sInitOnce;

MFBT_API TimeStamp
Expand Down Expand Up @@ -94,4 +122,39 @@ TimeStamp::RecordProcessRestart()
sInitOnce.mProcessCreation = TimeStamp();
}

MFBT_API TimeStamp
TimeStamp::NowFuzzy(TimeStampValue aValue)
{
#ifdef XP_WIN
TimeStampValue canonicalNow = TimeStampValue(sCanonicalGTC, sCanonicalQPC, sCanonicalHasQPC, true);
#else
TimeStampValue canonicalNow = TimeStampValue(sCanonicalNowTimeStamp);
#endif

if (TimeStamp::GetFuzzyfoxEnabled()) {
if(MOZ_LIKELY(!canonicalNow.IsNull())) {
return TimeStamp(canonicalNow);
}
}
// When we disable Fuzzyfox, time may goes backwards, so we need to make sure
// we don't do that.
else if (MOZ_UNLIKELY(canonicalNow > aValue)) {
return TimeStamp(canonicalNow);
}

return TimeStamp(aValue);
}

MFBT_API void
TimeStamp::UpdateFuzzyTimeStamp(TimeStamp aValue)
{
#ifdef XP_WIN
sCanonicalGTC = aValue.mValue.mGTC;
sCanonicalQPC = aValue.mValue.mQPC;
sCanonicalHasQPC = aValue.mValue.mHasQPC;
#else
sCanonicalNowTimeStamp = aValue.mValue.mTimeStamp;
#endif
}

} // namespace mozilla
80 changes: 73 additions & 7 deletions mozglue/misc/TimeStamp.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,53 @@ template<typename T> struct ParamTraits;
namespace mozilla {

#ifndef XP_WIN
typedef uint64_t TimeStampValue;
struct TimeStamp63Bit
{
uint64_t mUsedCanonicalNow : 1;
uint64_t mTimeStamp : 63;

constexpr TimeStamp63Bit()
: mUsedCanonicalNow(0)
, mTimeStamp(0) { }

MOZ_IMPLICIT constexpr TimeStamp63Bit(const uint64_t aValue)
: mUsedCanonicalNow(0)
, mTimeStamp(aValue) { }

constexpr TimeStamp63Bit(const bool aUsedCanonicalNow, const int64_t aTimeStamp)
: mUsedCanonicalNow(aUsedCanonicalNow ? 1 : 0)
, mTimeStamp(aTimeStamp) { }

bool operator==(const TimeStamp63Bit aOther) const
{
uint64_t here, there;
memcpy(&here, this, sizeof(TimeStamp63Bit));
memcpy(&there, &aOther, sizeof(TimeStamp63Bit));
return here == there;
}

operator uint64_t () const
{
return mTimeStamp;
}

bool IsNull() const
{
return mTimeStamp == 0;
}

bool UsedCanonicalNow() const
{
return mUsedCanonicalNow;
}

void SetCanonicalNow()
{
mUsedCanonicalNow = 1;
}
};

typedef TimeStamp63Bit TimeStampValue;
#endif

class TimeStamp;
Expand Down Expand Up @@ -413,7 +459,7 @@ class TimeStamp
/**
* Initialize to the "null" moment
*/
constexpr TimeStamp() : mValue(0) {}
constexpr TimeStamp() : mValue() {}
// Default copy-constructor and assignment are OK

/**
Expand All @@ -434,24 +480,31 @@ class TimeStamp
{
static_assert(sizeof(aSystemTime) == sizeof(TimeStampValue),
"System timestamp should be same units as TimeStampValue");
return TimeStamp(aSystemTime);
return TimeStamp(TimeStampValue(false, aSystemTime));
}
#endif

/**
* Return true if this is the "null" moment
*/
bool IsNull() const { return mValue == 0; }
bool IsNull() const { return mValue.IsNull(); }

/**
* Return true if this is not the "null" moment, may be used in tests, e.g.:
* |if (timestamp) { ... }|
*/
explicit operator bool() const
{
return mValue != 0;
return !IsNull();
}

bool UsedCanonicalNow() const
{
return mValue.UsedCanonicalNow();
}
static MFBT_API bool GetFuzzyfoxEnabled();
static MFBT_API void SetFuzzyfoxEnabled(bool aValue);

/**
* Return a timestamp reflecting the current elapsed system time. This
* is monotonically increasing (i.e., does not decrease) over the
Expand All @@ -467,6 +520,7 @@ class TimeStamp
*/
static TimeStamp Now() { return Now(true); }
static TimeStamp NowLoRes() { return Now(false); }
static TimeStamp NowUnfuzzed() { return NowUnfuzzed(true); }

/**
* Return a timestamp representing the time when the current process was
Expand Down Expand Up @@ -531,7 +585,10 @@ class TimeStamp
// (We don't check for overflow because it's not obvious what the error
// behavior should be in that case.)
if (aOther.mValue < 0 && value > mValue) {
value = 0;
value = TimeStampValue();
}
if (mValue.UsedCanonicalNow()) {
value.SetCanonicalNow();
}
mValue = value;
return *this;
Expand All @@ -544,7 +601,10 @@ class TimeStamp
// (We don't check for overflow because it's not obvious what the error
// behavior should be in that case.)
if (aOther.mValue > 0 && value > mValue) {
value = 0;
value = TimeStampValue();
}
if (mValue.UsedCanonicalNow()) {
value.SetCanonicalNow();
}
mValue = value;
return *this;
Expand Down Expand Up @@ -598,6 +658,10 @@ class TimeStamp
MOZ_IMPLICIT TimeStamp(TimeStampValue aValue) : mValue(aValue) {}

static MFBT_API TimeStamp Now(bool aHighResolution);
static MFBT_API TimeStamp NowUnfuzzed(bool aHighResolution);
static MFBT_API TimeStamp NowFuzzy(TimeStampValue aValue);

static MFBT_API void UpdateFuzzyTimeStamp(TimeStamp aValue);

/**
* Computes the uptime of the current process in microseconds. The result
Expand All @@ -623,6 +687,8 @@ class TimeStamp
* When using a system clock, a value is system dependent.
*/
TimeStampValue mValue;

friend class Fuzzyfox;
};

} // namespace mozilla
Expand Down
9 changes: 7 additions & 2 deletions mozglue/misc/TimeStamp_darwin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,12 +159,17 @@ TimeStamp::Shutdown()
TimeStamp
TimeStamp::Now(bool aHighResolution)
{
return TimeStamp(ClockTime());
return TimeStamp::NowFuzzy(TimeStampValue(false, ClockTime()));
}

TimeStamp
TimeStamp::NowUnfuzzed(bool aHighResolution)
{
return TimeStamp(TimeStampValue(false, ClockTime()));
}

// Computes and returns the process uptime in microseconds.
// Returns 0 if an error was encountered.

uint64_t
TimeStamp::ComputeProcessUptime()
{
Expand Down
8 changes: 7 additions & 1 deletion mozglue/misc/TimeStamp_posix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,13 @@ TimeStamp::Shutdown()
TimeStamp
TimeStamp::Now(bool aHighResolution)
{
return TimeStamp(ClockTimeNs());
return TimeStamp::NowFuzzy(TimeStampValue(false, ClockTimeNs()));
}

TimeStamp
TimeStamp::NowUnfuzzed(bool aHighResolution)
{
return TimeStamp(TimeStampValue(false, ClockTimeNs()));
}

#if defined(XP_LINUX) || defined(ANDROID)
Expand Down
26 changes: 20 additions & 6 deletions mozglue/misc/TimeStamp_windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,12 +269,13 @@ InitResolution()
// TimeStampValue implementation
// ----------------------------------------------------------------------------
MFBT_API
TimeStampValue::TimeStampValue(ULONGLONG aGTC, ULONGLONG aQPC, bool aHasQPC)
TimeStampValue::TimeStampValue(ULONGLONG aGTC, ULONGLONG aQPC, bool aHasQPC, bool aUsedCanonicalNow)
: mGTC(aGTC)
, mQPC(aQPC)
, mUsedCanonicalNow(aUsedCanonicalNow)
, mHasQPC(aHasQPC)
, mIsNull(false)
{
mIsNull = aGTC == 0 && aQPC == 0;
}

MFBT_API TimeStampValue&
Expand Down Expand Up @@ -372,7 +373,7 @@ TimeStampValue::CheckQPC(const TimeStampValue& aOther) const
MFBT_API uint64_t
TimeStampValue::operator-(const TimeStampValue& aOther) const
{
if (mIsNull && aOther.mIsNull) {
if (IsNull() && aOther.IsNull()) {
return uint64_t(0);
}

Expand Down Expand Up @@ -523,16 +524,29 @@ TimeStamp::Shutdown()
DeleteCriticalSection(&sTimeStampLock);
}

MFBT_API TimeStamp
TimeStamp::Now(bool aHighResolution)

TimeStampValue
NowInternal(bool aHighResolution)
{
// sUseQPC is volatile
bool useQPC = (aHighResolution && sUseQPC);

// Both values are in [mt] units.
ULONGLONG QPC = useQPC ? PerformanceCounter() : uint64_t(0);
ULONGLONG GTC = ms2mt(GetTickCount64());
return TimeStamp(TimeStampValue(GTC, QPC, useQPC));
return TimeStampValue(GTC, QPC, useQPC, false);
}

MFBT_API TimeStamp
TimeStamp::Now(bool aHighResolution)
{
return TimeStamp::NowFuzzy(NowInternal(aHighResolution));
}

MFBT_API TimeStamp
TimeStamp::NowUnfuzzed(bool aHighResolution)
{
return TimeStamp(NowInternal(aHighResolution));
}

// Computes and returns the process uptime in microseconds.
Expand Down
Loading

0 comments on commit 61ca4f1

Please sign in to comment.