gecko-dev/ipc/glue/IdleSchedulerChild.cpp
Boris Zbarsky 3ae961a2da Bug 1589561. Factor out idle handling from PrioritizedEventQueue. r=smaug
We could try to move the EnforcePendingTaskGuarantee() bit into
PeekIdleDeadline, but then we'd need to check HasReadyEvent() on
mDeferredTimersQueue and mIdleQueue before we possibly unlock the mutex under
PeekIdleDeadline, and it's not clear that that state cannot change once the
mutex is unlocked...

The EnsureIsActive() call at the end of GetIdleDeadlineInternal in the !aIsPeek
case only makes sense if there are in fact idle tasks available to run when
GetDeadlineForIdleTask is called, because otherwise it would incorrectly set us
active when we are not running any tasks.

Differential Revision: https://phabricator.services.mozilla.com/D49696

--HG--
rename : xpcom/threads/PrioritizedEventQueue.cpp => xpcom/threads/IdlePeriodState.cpp
rename : xpcom/threads/PrioritizedEventQueue.h => xpcom/threads/IdlePeriodState.h
extra : moz-landing-system : lando
2019-10-20 15:08:44 +00:00

93 lines
3.0 KiB
C++

/* -*- 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 "mozilla/ipc/IdleSchedulerChild.h"
#include "mozilla/ipc/IdleSchedulerParent.h"
#include "mozilla/Atomics.h"
#include "mozilla/IdlePeriodState.h"
#include "BackgroundChild.h"
namespace mozilla {
namespace ipc {
static IdleSchedulerChild* sMainThreadIdleScheduler = nullptr;
IdleSchedulerChild::~IdleSchedulerChild() {
if (sMainThreadIdleScheduler == this) {
sMainThreadIdleScheduler = nullptr;
}
MOZ_ASSERT(!mIdlePeriodState);
}
void IdleSchedulerChild::Init(IdlePeriodState* aIdlePeriodState) {
mIdlePeriodState = aIdlePeriodState;
RefPtr<IdleSchedulerChild> scheduler = this;
auto resolve =
[&](Tuple<mozilla::Maybe<SharedMemoryHandle>, uint32_t>&& aResult) {
if (Get<0>(aResult)) {
mActiveCounter.SetHandle(*Get<0>(aResult), false);
mActiveCounter.Map(sizeof(int32_t));
mChildId = Get<1>(aResult);
if (mChildId && mIdlePeriodState && mIdlePeriodState->IsActive()) {
SetActive();
}
}
};
auto reject = [&](ResponseRejectReason) {};
SendInitForIdleUse(std::move(resolve), std::move(reject));
}
IPCResult IdleSchedulerChild::RecvIdleTime(uint64_t aId, TimeDuration aBudget) {
if (mIdlePeriodState) {
mIdlePeriodState->SetIdleToken(aId, aBudget);
}
return IPC_OK();
}
void IdleSchedulerChild::SetActive() {
if (mChildId && CanSend() && mActiveCounter.memory()) {
++(static_cast<Atomic<int32_t>*>(
mActiveCounter.memory())[NS_IDLE_SCHEDULER_INDEX_OF_ACTIVITY_COUNTER]);
++(static_cast<Atomic<int32_t>*>(mActiveCounter.memory())[mChildId]);
}
}
bool IdleSchedulerChild::SetPaused() {
if (mChildId && CanSend() && mActiveCounter.memory()) {
--(static_cast<Atomic<int32_t>*>(mActiveCounter.memory())[mChildId]);
// The following expression reduces the global activity count and checks if
// it drops below the cpu counter limit.
return (static_cast<Atomic<int32_t>*>(
mActiveCounter
.memory())[NS_IDLE_SCHEDULER_INDEX_OF_ACTIVITY_COUNTER])-- ==
static_cast<Atomic<int32_t>*>(
mActiveCounter.memory())[NS_IDLE_SCHEDULER_INDEX_OF_CPU_COUNTER];
}
return false;
}
IdleSchedulerChild* IdleSchedulerChild::GetMainThreadIdleScheduler() {
MOZ_ASSERT(NS_IsMainThread());
if (sMainThreadIdleScheduler) {
return sMainThreadIdleScheduler;
}
ipc::PBackgroundChild* background =
ipc::BackgroundChild::GetOrCreateForCurrentThread();
if (background) {
sMainThreadIdleScheduler = new ipc::IdleSchedulerChild();
background->SendPIdleSchedulerConstructor(sMainThreadIdleScheduler);
}
return sMainThreadIdleScheduler;
}
} // namespace ipc
} // namespace mozilla