diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 72f5e2c20..924a8c484 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -264,8 +264,8 @@ class nsIScriptTimeoutHandler; // which also uses Mach factor analysis to determine load, because most // calls will have a max timeout and thus the function is likely to run at // *some* point. -static const int32_t MACH_FACTOR_MIN = 700; -static const int32_t MACH_CHECK_INTERVAL = 2000; +static const int32_t MACH_FACTOR_MIN = 900; +static const int32_t MACH_CHECK_INTERVAL = 1000; // This number is actually in the W3C standard, but we allow it to be // adjusted. static const int32_t CALLBACK_IDLE_INTERVAL = 50; @@ -275,7 +275,10 @@ static int32_t sIdleCallbackIdleInterval = CALLBACK_IDLE_INTERVAL; #include #include #include +#include +#include static processor_set_name_port_t sMachDefaultPset; +static uint32_t sNumCPUs; static struct processor_set_load_info sMachLoadInfo; static host_name_port_t sMachHost; @@ -1245,10 +1248,18 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow) CALLBACK_IDLE_INTERVAL); sMachHost = mach_host_self(); kern_return_t ret = processor_set_default(sMachHost, &sMachDefaultPset); + sNumCPUs = 1; if (ret != KERN_SUCCESS) { fprintf(stderr, "TenFourFox: Unable to initialize Mach idle monitoring: %i\n", (uint32_t)ret); sMachFactorMin = 0; } + int mib[2] = { CTL_HW, HW_NCPU }; + size_t len = sizeof(sNumCPUs); + if (sysctl(mib, 2, &sNumCPUs, &len, NULL, 0) == -1) + sNumCPUs = 1; +#if DEBUG + fprintf(stderr, "GlobalWindow: %i CPUs\n", sNumCPUs); +#endif } if (gDumpFile == nullptr) { @@ -11591,7 +11602,13 @@ SystemIsIdle() (processor_set_info_t)&sMachLoadInfo, &count); if (kr != KERN_SUCCESS) return true; - return (sMachLoadInfo.mach_factor > sMachFactorMin); +#if DEBUG + fprintf(stderr, "SystemIsIdle(%i/%i: %s)\n", + sMachLoadInfo.mach_factor, + sMachFactorMin * sNumCPUs, + (sMachLoadInfo.mach_factor > (sMachFactorMin * sNumCPUs)) ? "true" : "false"); +#endif + return (sMachLoadInfo.mach_factor > (sMachFactorMin * sNumCPUs)); } nsresult @@ -11640,6 +11657,9 @@ nsGlobalWindow::SetTimeoutOrIntervalOrIdleCallback(nsIScriptTimeoutHandler *aHan timeout->mDeadline = interval; timeout->mScriptHandler = nullptr; +// XXX: Current logic short circuits this and simply makes idle callbacks +// into fixed timeouts. +#if(0) // If RequestIdleCallback says this is not an interval, then it must // want it to run right away. Otherwise schedule the idle checks. if (aIsInterval) { @@ -11647,6 +11667,9 @@ nsGlobalWindow::SetTimeoutOrIntervalOrIdleCallback(nsIScriptTimeoutHandler *aHan } else interval = 0; timeout->mInterval = interval; +#else + // Leave interval as it is +#endif } else { timeout->mInterval = interval; timeout->mCallback = nullptr; @@ -12145,7 +12168,12 @@ nsGlobalWindow::RunTimeout(nsTimeout *aTimeout) timeout->mElapsed += timeout->mInterval; if (!timeout->mInterval || timeout->mElapsed >= timeout->mDeadline || SystemIsIdle()) { rescheduleOk = false; + timeout->mIsInterval = false; // don't reschedule timeout_was_cleared = RunTimeoutHandler(timeout, scx); + if (timeout->mTimer) { + timeout->mTimer->Cancel(); + timeout->mTimer = nullptr; + } } } else timeout_was_cleared = RunTimeoutHandler(timeout, scx); @@ -14004,13 +14032,20 @@ nsGlobalWindow::RequestIdleCallback(JSContext* aCx, { MOZ_RELEASE_ASSERT(IsInnerWindow()); AssertIsOnMainThread(); - int32_t handle = -1, timeout = 3600000; /* default 60 minutes */ + int32_t handle = -1, timeout = 5000; /* default 5 seconds */ nsresult rv; if (aOptions.mTimeout.WasPassed()) timeout = aOptions.mTimeout.Value(); - if (SystemIsIdle()) { +// XXX: Deferring initial run of the callback beyond the timeout period +// invariably causes problems. But if a timeout was specified, we can +// generally assume it's safe to hit that. + + if (1) { // SystemIsIdle()) { +#if DEBUG + fprintf(stderr, "Idle callback initialized, timeout %d ms\n", timeout); +#endif // The computer is already idle, so we will run the callback now. rv = SetTimeoutOrIntervalOrIdleCallback(nullptr, timeout, false, &handle, &aCallback); @@ -14019,6 +14054,7 @@ nsGlobalWindow::RequestIdleCallback(JSContext* aCx, rv = SetTimeoutOrIntervalOrIdleCallback(nullptr, timeout, true, &handle, &aCallback); } + if (NS_SUCCEEDED(rv)) return handle; @@ -14033,7 +14069,7 @@ nsGlobalWindow::CancelIdleCallback(uint32_t aHandle) ErrorResult ignored; // XXX: As written, this is just an alias for clearTimeout(), so - // web scripts could call either to clear any time of timeout + // web scripts could call either to clear any type of timeout // or interval. Do we care? if (aHandle > 0) { diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 371ca2448..fe3599e71 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -1043,7 +1043,7 @@ pref("dom.disable_window_open_feature.status", true); pref("dom.allow_scripts_to_close_windows", false); // TenFourFox issue 463 -pref("tenfourfox.dom.requestIdleCallback.enabled", true); +pref("tenfourfox.dom.requestIdleCallback.enabled", false); pref("dom.require_user_interaction_for_beforeunload", true);