Bug 1432429 Add FuzzyFox class 2/14
MozReview-Commit-ID: 1luFLRDzZjq
--- a/layout/build/nsLayoutStatics.cpp
+++ b/layout/build/nsLayoutStatics.cpp
@@ -107,16 +107,20 @@
#include "mozilla/StaticPresData.h"
#include "mozilla/dom/WebIDLGlobalNameHash.h"
#include "mozilla/dom/ipc/IPCBlobInputStreamStorage.h"
#include "mozilla/dom/U2FTokenManager.h"
#include "mozilla/dom/PointerEventHandler.h"
#include "mozilla/dom/BlobURLProtocolHandler.h"
#include "nsThreadManager.h"
+#ifdef MOZ_FUZZYFOX
+#include "mozilla/Fuzzyfox.h"
+#endif
+
using namespace mozilla;
using namespace mozilla::net;
using namespace mozilla::dom;
using namespace mozilla::dom::ipc;
nsrefcnt nsLayoutStatics::sLayoutStaticRefcnt = 0;
nsresult
@@ -280,16 +284,20 @@ nsLayoutStatics::Initialize()
if (XRE_IsParentProcess()) {
// On content process we initialize DOMPrefs when PContentChild is fully
// initialized.
mozilla::dom::DOMPrefs::Initialize();
}
nsThreadManager::InitializeShutdownObserver();
+#ifdef MOZ_FUZZYFOX
+ mozilla::Fuzzyfox::Start();
+#endif
+
return NS_OK;
}
void
nsLayoutStatics::Shutdown()
{
// Don't need to shutdown nsWindowMemoryReporter, that will be done by the
// memory reporter manager.
--- a/mozglue/misc/TimeStamp_windows.cpp
+++ b/mozglue/misc/TimeStamp_windows.cpp
@@ -58,36 +58,30 @@ static const uint32_t kFailureThreshold
// If we are not able to get the value of GTC time increment, use this value
// which is the most usual increment.
static const DWORD kDefaultTimeIncrement = 156001;
// ----------------------------------------------------------------------------
// Global variables, not changing at runtime
// ----------------------------------------------------------------------------
-/**
- * The [mt] unit:
- *
- * Many values are kept in ticks of the Performance Coutner x 1000,
- * further just referred as [mt], meaning milli-ticks.
- *
- * This is needed to preserve maximum precision of the performance frequency
- * representation. GetTickCount64 values in milliseconds are multiplied with
- * frequency per second. Therefor we need to multiply QPC value by 1000 to
- * have the same units to allow simple arithmentic with both QPC and GTC.
- */
-
-#define ms2mt(x) ((x) * sFrequencyPerSec)
-#define mt2ms(x) ((x) / sFrequencyPerSec)
-#define mt2ms_f(x) (double(x) / sFrequencyPerSec)
-
// Result of QueryPerformanceFrequency
// We use default of 1 for the case we can't use QueryPerformanceCounter
// to make mt/ms conversions work despite that.
-static LONGLONG sFrequencyPerSec = 1;
+static uint64_t sFrequencyPerSec = 1;
+
+namespace mozilla {
+
+MFBT_API uint64_t
+GetQueryPerformanceFrequencyPerSec()
+{
+ return sFrequencyPerSec;
+}
+
+}
// How much we are tolerant to GTC occasional loose of resoltion.
// This number says how many multiples of the minimal GTC resolution
// detected on the system are acceptable. This number is empirical.
static const LONGLONG kGTCTickLeapTolerance = 4;
// Base tolerance (more: "inability of detection" range) threshold is calculated
// dynamically, and kept in sGTCResolutionThreshold.
--- a/mozglue/misc/TimeStamp_windows.h
+++ b/mozglue/misc/TimeStamp_windows.h
@@ -6,16 +6,34 @@
#ifndef mozilla_TimeStamp_windows_h
#define mozilla_TimeStamp_windows_h
#include "mozilla/Types.h"
namespace mozilla {
+/**
+ * The [mt] unit:
+ *
+ * Many values are kept in ticks of the Performance Coutner x 1000,
+ * further just referred as [mt], meaning milli-ticks.
+ *
+ * This is needed to preserve maximum precision of the performance frequency
+ * representation. GetTickCount64 values in milliseconds are multiplied with
+ * frequency per second. Therefore we need to multiply QPC value by 1000 to
+ * have the same units to allow simple arithmentic with both QPC and GTC.
+ */
+#define ms2mt(x) ((x) * mozilla::GetQueryPerformanceFrequencyPerSec())
+#define mt2ms(x) ((x) / mozilla::GetQueryPerformanceFrequencyPerSec())
+#define mt2ms_f(x) (double(x) / mozilla::GetQueryPerformanceFrequencyPerSec())
+
+MFBT_API uint64_t
+GetQueryPerformanceFrequencyPerSec();
+
class TimeStamp;
class TimeStampValue
{
friend struct IPC::ParamTraits<mozilla::TimeStampValue>;
friend class TimeStamp;
// Both QPC and GTC are kept in [mt] units.
new file mode 100644
--- /dev/null
+++ b/toolkit/components/fuzzyfox/Fuzzyfox.cpp
@@ -0,0 +1,207 @@
+/* -*- 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/. */
+
+#include "Fuzzyfox.h"
+#include "mozilla/Logging.h"
+#include "mozilla/Services.h"
+#include "mozilla/SystemGroup.h"
+#include "mozilla/TimeStamp.h"
+#include "nsComponentManagerUtils.h"
+#include "nsIObserverService.h"
+#include "nsISupportsPrimitives.h"
+#include "prrng.h"
+#include "prtime.h"
+
+// For usleep/Sleep & QueryPerformanceFrequency
+#ifdef XP_WIN
+#include <windows.h>
+#else
+#include <unistd.h>
+#endif
+
+using namespace mozilla;
+
+static LazyLogModule sFuzzyfoxLog("Fuzzyfox");
+
+#define PT_STATIC_CLOCK_GRAIN 80
+#define PT_DURATION_CENTER 100000
+
+#define US_TO_NS(x) (x*1000)
+#define NS_TO_US(x) (x/1000)
+
+#ifdef LOG
+#undef LOG
+#endif
+
+#define LOG(args) MOZ_LOG(sFuzzyfoxLog, mozilla::LogLevel::Debug, args)
+
+/* static */ void
+Fuzzyfox::Start()
+{
+ MOZ_ASSERT(NS_IsMainThread());
+
+ RefPtr<Fuzzyfox> r = new Fuzzyfox();
+ SystemGroup::Dispatch(TaskCategory::Other, r.forget());
+}
+
+Fuzzyfox::Fuzzyfox()
+ : Runnable("Fuzzyfox")
+ , mStartTime(ActualTime())
+ , mDuration(PickDuration())
+ , mTickType(eUptick)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+}
+
+Fuzzyfox::~Fuzzyfox() = default;
+
+NS_IMETHODIMP
+Fuzzyfox::Run()
+{
+ MOZ_ASSERT(NS_IsMainThread());
+
+ // We need to check how long its been since we ran
+ uint64_t endTime = ActualTime();
+
+ uint64_t remaining = 0;
+ uint64_t durationCount = 1;
+
+ // Pick the amount to sleep
+ if ((endTime - mStartTime) > mDuration) {
+ // We ran over our budget!
+ uint64_t over = (endTime - mStartTime) - mDuration;
+ LOG(("[Fuzzyfox][FuzzyfoxEvent] PT(%p) Overran budget of %" PRIu32 " by %" PRIu64 " \n",
+ this, mDuration, over));
+
+ //TODO: this should probably influence uptick/downtick stuff, and it doesn't
+ uint64_t nextDuration = PickDuration();
+ while (over > nextDuration) {
+ durationCount++;
+ over -= nextDuration;
+ nextDuration = PickDuration();
+ }
+
+ remaining = nextDuration - over;
+ } else {
+ // Didn't go over budget
+ remaining = mDuration - (endTime - mStartTime);
+ LOG(("[Fuzzyfox][FuzzyfoxEvent] PT(%p) Finishing budget of %" PRIu32 " with %" PRIu64 " \n",
+ this, mDuration, remaining));
+
+ }
+
+ // Sleep for now
+#ifdef XP_WIN
+ Sleep(remaining);
+#else
+ usleep(remaining);
+#endif
+
+ //TODO we slept extra long almost certainly, what do we do about that?
+
+ // Update clocks (and fire pending events etc)
+ UpdateClocks();
+
+ // Reset values
+ mTickType = mTickType == eUptick ? eDowntick : eUptick;
+ mStartTime = ActualTime();
+ mDuration = PickDuration();
+
+ // Queue next event
+ nsCOMPtr<nsIRunnable> r = this;
+ SystemGroup::Dispatch(TaskCategory::Other, r.forget());
+ return NS_OK;
+}
+
+uint64_t
+Fuzzyfox::ActualTime()
+{
+ return PR_Now();
+}
+
+uint64_t
+Fuzzyfox::PickDuration()
+{
+ // TODO: Fix to be secure
+ long int rval = rand();
+
+ // We want uniform distribution from 1->PT_DURATION_CENTER*2
+ // so that the mean is PT_DURATION_CENTER
+ return 1 + (rval % (PT_DURATION_CENTER * 2));
+}
+
+void
+Fuzzyfox::UpdateClocks()
+{
+ uint64_t time = ActualTime();
+ TimeStamp timestamp = TimeStamp::NowReally();
+
+ uint64_t newTime = RoundToGrain(time);
+ TimeStamp newTimeStamp = RoundToGrain(timestamp);
+
+ // newTime is the new canonical time for this scope!
+ LOG(("[Fuzzyfox][Fuzzyfox][Time] New time is %" PRIu64 "\n", newTimeStamp));
+
+ // Fire notifications
+ nsCOMPtr<nsIObserverService> os = services::GetObserverService();
+ if (NS_WARN_IF(!os)) {
+ return;
+ }
+
+ // Event firings on occur on downticks and have no data
+ if (mTickType == eDowntick) {
+ os->NotifyObservers(nullptr, "fuzzyfox-fire-outbound", nullptr);
+ }
+
+ nsCOMPtr<nsISupportsPRInt64> wrapper =
+ do_CreateInstance(NS_SUPPORTS_PRINT64_CONTRACTID);
+ if (NS_WARN_IF(!wrapper)) {
+ return;
+ }
+
+ wrapper->SetData(newTime);
+
+ // Clocks get the official 'realtime' time
+ // This happens on all ticks
+ os->NotifyObservers(wrapper, "fuzzyfox-update-clocks", nullptr);
+
+ // Update the timestamp canonicaltime
+ TimeStamp::UpdateFuzzyTimeStamp(newTimeStamp);
+}
+
+uint64_t
+Fuzzyfox::GetClockGrain()
+{
+ // Static for now
+ // Should be reading from some config probably
+ return PT_STATIC_CLOCK_GRAIN;
+}
+
+uint64_t
+Fuzzyfox::RoundToGrain(uint64_t aValue)
+{
+ uint64_t grain = GetClockGrain();
+ return US_TO_NS(aValue - (aValue % grain));
+}
+
+TimeStamp
+Fuzzyfox::RoundToGrain(TimeStamp aValue)
+{
+#ifdef XP_WIN
+ // grain is in us
+ uint64_t grain = GetClockGrain();
+ // GTC and QPS are stored in |mt| and need to be converted
+ uint64_t GTC = mt2ms(aValue.mValue.mGTC);
+ uint64_t QPC = mt2ms(aValue.mValue.mQPC);
+
+ return TimeStamp(TimeStampValue(
+ ms2mt(GTC - (GTC % grain)),
+ ms2mt(GTC - (GTC % grain)),
+ aValue.mValue.mHasQPC), true);
+#else
+ return TimeStamp(RoundToGrain(aValue.mValue));
+#endif
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/toolkit/components/fuzzyfox/Fuzzyfox.h
@@ -0,0 +1,59 @@
+/* -*- 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/. */
+
+#ifndef mozilla_Fuzzyfox_h
+#define mozilla_Fuzzyfox_h
+
+#include "nsThreadUtils.h"
+#include "mozilla/TimeStamp.h"
+
+namespace mozilla {
+
+class Fuzzyfox final : public Runnable
+{
+public:
+ static void
+ Start();
+
+ NS_IMETHOD
+ Run() override;
+
+private:
+ Fuzzyfox();
+ ~Fuzzyfox();
+
+ uint64_t
+ ActualTime();
+
+ uint64_t
+ PickDuration();
+
+ void
+ UpdateClocks();
+
+ uint64_t
+ GetClockGrain();
+
+ uint64_t
+ RoundToGrain(uint64_t aValue);
+
+ TimeStamp
+ RoundToGrain(TimeStamp aValue);
+
+ uint64_t mStartTime;
+ uint32_t mDuration;
+
+ enum Tick {
+ eUptick,
+ eDowntick,
+ };
+
+ Tick mTickType;
+};
+
+} // mozilla namespace
+
+#endif /* mozilla_Fuzzyfox_h */
new file mode 100644
--- /dev/null
+++ b/toolkit/components/fuzzyfox/moz.build
@@ -0,0 +1,15 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+SOURCES += [
+ 'Fuzzyfox.cpp',
+]
+
+EXPORTS.mozilla += [
+ 'Fuzzyfox.h'
+]
+
+FINAL_LIBRARY = 'xul'
--- a/toolkit/components/moz.build
+++ b/toolkit/components/moz.build
@@ -72,16 +72,19 @@ DIRS += [
'viewconfig',
'viewsource',
'windowcreator',
'windowwatcher',
'workerloader',
'xulstore'
]
+if CONFIG['MOZ_FUZZYFOX']:
+ DIRS += ['fuzzyfox']
+
if CONFIG['MOZ_BUILD_APP'] != 'mobile/android':
DIRS += ['narrate'];
if CONFIG['NS_PRINTING']:
DIRS += ['printing']
if CONFIG['BUILD_CTYPES']:
DIRS += ['ctypes']
--- a/xpcom/threads/Scheduler.cpp
+++ b/xpcom/threads/Scheduler.cpp
@@ -9,24 +9,26 @@
#include "jsfriendapi.h"
#include "LabeledEventQueue.h"
#include "LeakRefPtr.h"
#include "MainThreadQueue.h"
#include "mozilla/CooperativeThreadPool.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/ipc/BackgroundChild.h"
#include "mozilla/SchedulerGroup.h"
+#include "mozilla/ServoBindings.h"
#include "nsCycleCollector.h"
#include "nsIThread.h"
#include "nsPrintfCString.h"
#include "nsThread.h"
#include "nsThreadManager.h"
#include "PrioritizedEventQueue.h"
#include "xpcpublic.h"
#include "xpccomponents.h"
+#include "base/message_loop.h"
// Windows silliness. winbase.h defines an empty no-argument Yield macro.
#undef Yield
using namespace mozilla;
// Using the anonymous namespace here causes GCC to generate:
// error: 'mozilla::SchedulerImpl' has a field 'mozilla::SchedulerImpl::mQueue' whose type uses the anonymous namespace