DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/Atomics.h"
#include "mozilla/TimeStamp.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

namespace mozilla {

/**
 * Wrapper class used to initialize static data used by the TimeStamp class
 */
struct TimeStampInitialization {
  /**
   * First timestamp taken when the class static initializers are run. This
   * timestamp is used to sanitize timestamps coming from different sources.
   */
  TimeStamp mFirstTimeStamp;

  /**
   * Timestamp representing the time when the process was created. This field
   * is populated lazily the first time this information is required and is
   * replaced every time the process is restarted.
   */
  TimeStamp mProcessCreation;

  TimeStampInitialization() {
    TimeStamp::Startup();
    mFirstTimeStamp = TimeStamp::Now();
  };

  ~TimeStampInitialization() { TimeStamp::Shutdown(); };
};

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> sCanonicalNowTimeStamp;
#endif
static Atomic<int64_t> sCanonicalNowTime;
// This variable stores the frozen time (as ms since the epoch) for FuzzyFox
// to report if FuzzyFox is enabled.
static TimeStampInitialization sInitOnce;

MFBT_API TimeStamp TimeStamp::ProcessCreation(bool* aIsInconsistent) {
  if (aIsInconsistent) {
    *aIsInconsistent = false;
  }

  if (sInitOnce.mProcessCreation.IsNull()) {
    char* mozAppRestart = 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. */
      ts = sInitOnce.mFirstTimeStamp;
    } else {
      TimeStamp now = Now();
      uint64_t uptime = ComputeProcessUptime();

      ts = now - TimeDuration::FromMicroseconds(uptime);

      if ((ts > sInitOnce.mFirstTimeStamp) || (uptime == 0)) {
        /* If the process creation timestamp was inconsistent replace it with
         * the first one instead and notify that a telemetry error was
         * detected. */
        if (aIsInconsistent) {
          *aIsInconsistent = true;
        }
        ts = sInitOnce.mFirstTimeStamp;
      }
    }

    sInitOnce.mProcessCreation = ts;
  }

  return sInitOnce.mProcessCreation;
}

void 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
}

MFBT_API int64_t TimeStamp::NowFuzzyTime() { return sCanonicalNowTime; }

MFBT_API void TimeStamp::UpdateFuzzyTime(int64_t aValue) {
  sCanonicalNowTime = aValue;
}

}  // namespace mozilla