Bug 892371 - Adjust oom_score_adj values for foreground processes according to an LRU policy. r=dhylands, r=khuey

This commit is contained in:
Gabriele Svelto 2015-02-25 09:37:38 +01:00
parent 7c48c7afce
commit 6b38c6d632
11 changed files with 214 additions and 324 deletions

View File

@ -703,10 +703,11 @@ pref("dom.ipc.processPriorityManager.backgroundGracePeriodMS", 1000);
pref("dom.ipc.processPriorityManager.backgroundPerceivableGracePeriodMS", 5000);
pref("dom.ipc.processPriorityManager.temporaryPriorityLockMS", 5000);
// Number of different background levels for background processes. We use
// these different levels to force the low-memory killer to kill processes in
// a LRU order.
pref("dom.ipc.processPriorityManager.backgroundLRUPoolLevels", 5);
// Number of different background/foreground levels for background/foreground
// processes. We use these different levels to force the low-memory killer to
// kill processes in a LRU order.
pref("dom.ipc.processPriorityManager.BACKGROUND.LRUPoolLevels", 5);
pref("dom.ipc.processPriorityManager.FOREGROUND.LRUPoolLevels", 3);
// Kernel parameters for process priorities. These affect how processes are
// killed on low-memory and their relative CPU priorities.

View File

@ -50,9 +50,9 @@ const browserElementTestHelpers = {
enableProcessPriorityManager: function() {
this._setPrefs(
['dom.ipc.processPriorityManager.BACKGROUND.LRUPoolLevels', 2],
['dom.ipc.processPriorityManager.testMode', true],
['dom.ipc.processPriorityManager.enabled', true],
['dom.ipc.processPriorityManager.backgroundLRUPoolLevels', 2]
['dom.ipc.processPriorityManager.enabled', true]
);
},
@ -187,28 +187,28 @@ function expectPriorityChange(childID, expectedPriority) {
});
}
// Returns a promise which is resolved or rejected the next time the background
// process childID changes its priority. We resolve if the backgroundLRU
// matches expectedBackgroundLRU and we reject otherwise.
// Returns a promise which is resolved or rejected the next time the
// process childID changes its priority. We resolve if the LRU parameter
// matches expectedLRU and we reject otherwise.
function expectPriorityWithBackgroundLRUSet(childID, expectedBackgroundLRU) {
function expectPriorityWithLRUSet(childID, expectedLRU) {
return new Promise(function(resolve, reject) {
browserElementTestHelpers.addProcessPriorityObserver(
'process-priority-with-background-LRU-set',
'process-priority-with-LRU-set',
function(subject, topic, data) {
var [id, priority, backgroundLRU] = data.split(":");
var [id, priority, lru] = data.split(":");
if (id != childID) {
return;
}
is(backgroundLRU, expectedBackgroundLRU,
'Expected backgroundLRU ' + backgroundLRU +
is(lru, expectedLRU,
'Expected LRU ' + lru +
' of childID ' + childID +
' to change to ' + expectedBackgroundLRU);
' to change to ' + expectedLRU);
if (backgroundLRU == expectedBackgroundLRU) {
if (lru == expectedLRU) {
resolve();
} else {
reject();

View File

@ -49,7 +49,7 @@ function runTest() {
// We wait until another one is set to background, too.
// Once there are two in background, the first one (LRU order)
// should have 'backgroundLRU' equals 1
var p = expectPriorityWithBackgroundLRUSet(childID, '1');
var p = expectPriorityWithLRUSet(childID, '1');
iframe2.setVisible(false);
return p;

View File

@ -10,6 +10,7 @@
#include "mozilla/dom/Element.h"
#include "mozilla/dom/TabParent.h"
#include "mozilla/Hal.h"
#include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/Preferences.h"
#include "mozilla/Services.h"
#include "mozilla/unused.h"
@ -54,17 +55,18 @@
# define LOGP(fmt, ...) \
__android_log_print(ANDROID_LOG_INFO, \
"Gecko:ProcessPriorityManager", \
"[%schild-id=%llu, pid=%d] " fmt, \
"[%schild-id=%" PRIu64 ", pid=%d] " fmt, \
NameWithComma().get(), \
(long long unsigned) ChildID(), Pid(), ## __VA_ARGS__)
static_cast<uint64_t>(ChildID()), Pid(), ## __VA_ARGS__)
#elif defined(ENABLE_LOGGING)
# define LOG(fmt, ...) \
printf("ProcessPriorityManager - " fmt "\n", ##__VA_ARGS__)
# define LOGP(fmt, ...) \
printf("ProcessPriorityManager[%schild-id=%llu, pid=%d] - " fmt "\n", \
printf("ProcessPriorityManager[%schild-id=%" PRIu64 ", pid=%d] - " \
fmt "\n", \
NameWithComma().get(), \
(unsigned long long) ChildID(), Pid(), ##__VA_ARGS__)
static_cast<uint64_t>(ChildID()), Pid(), ##__VA_ARGS__)
#elif defined(PR_LOGGING)
static PRLogModuleInfo*
@ -80,9 +82,9 @@
("ProcessPriorityManager - " fmt, ##__VA_ARGS__))
# define LOGP(fmt, ...) \
PR_LOG(GetPPMLog(), PR_LOG_DEBUG, \
("ProcessPriorityManager[%schild-id=%llu, pid=%d] - " fmt, \
("ProcessPriorityManager[%schild-id=%" PRIu64 ", pid=%d] - " fmt, \
NameWithComma().get(), \
(unsigned long long) ChildID(), Pid(), ##__VA_ARGS__))
static_cast<uint64_t>(ChildID()), Pid(), ##__VA_ARGS__))
#else
#define LOG(fmt, ...)
#define LOGP(fmt, ...)
@ -96,6 +98,42 @@ namespace {
class ParticularProcessPriorityManager;
class ProcessLRUPool MOZ_FINAL
{
public:
/**
* Creates a new process LRU pool for the specified priority.
*/
ProcessLRUPool(ProcessPriority aPriority, uint32_t aBias);
/**
* Used to remove a particular process priority manager from the LRU pool
* when the associated ContentParent is destroyed or its priority changes.
*/
void Remove(ParticularProcessPriorityManager* aParticularManager);
/**
* Used to add a particular process priority manager into the LRU pool when
* the associated ContentParent's priority changes.
*/
void Add(ParticularProcessPriorityManager* aParticularManager);
private:
ProcessPriority mPriority;
uint32_t mLRUPoolLevels;
uint32_t mLRUPoolSize;
uint32_t mBias;
nsTArray<ParticularProcessPriorityManager*> mLRUPool;
uint32_t CalculateLRULevel(uint32_t aLRUPoolIndex);
void AdjustLRUValues(
nsTArray<ParticularProcessPriorityManager*>::index_type aStart,
bool removed);
DISALLOW_EVIL_CONSTRUCTORS(ProcessLRUPool);
};
/**
* This singleton class does the work to implement the process priority manager
* in the main process. This class may not be used in child processes. (You
@ -129,7 +167,7 @@ public:
*/
void SetProcessPriority(ContentParent* aContentParent,
ProcessPriority aPriority,
uint32_t aBackgroundLRU = 0);
uint32_t aLRU = 0);
/**
* If a magic testing-only pref is set, notify the observer service on the
@ -179,8 +217,17 @@ private:
nsDataHashtable<nsUint64HashKey, nsRefPtr<ParticularProcessPriorityManager> >
mParticularManagers;
/** True if the main process is holding a high-priority wakelock */
bool mHighPriority;
/** Contains the PIDs of child processes holding high-priority wakelocks */
nsTHashtable<nsUint64HashKey> mHighPriorityChildIDs;
/** Contains a pseudo-LRU list of background processes */
ProcessLRUPool mBackgroundLRUPool;
/** Contains a pseudo-LRU list of foreground processes */
ProcessLRUPool mForegroundLRUPool;
};
/**
@ -262,7 +309,7 @@ public:
void ScheduleResetPriority(const char* aTimeoutPref);
void ResetPriority();
void ResetPriorityNow();
void SetPriorityNow(ProcessPriority aPriority, uint32_t aBackgroundLRU = 0);
void SetPriorityNow(ProcessPriority aPriority, uint32_t aLRU = 0);
void ShutDown();
@ -278,6 +325,7 @@ private:
ContentParent* mContentParent;
uint64_t mChildID;
ProcessPriority mPriority;
uint32_t mLRU;
bool mHoldsCPUWakeLock;
bool mHoldsHighPriorityWakeLock;
@ -289,46 +337,6 @@ private:
nsCOMPtr<nsITimer> mResetPriorityTimer;
};
class BackgroundProcessLRUPool MOZ_FINAL
{
public:
static BackgroundProcessLRUPool* Singleton();
/**
* Used to remove a ContentParent from background LRU pool when
* it is destroyed or its priority changed from BACKGROUND to others.
*/
void RemoveFromBackgroundLRUPool(ContentParent* aContentParent);
/**
* Used to add a ContentParent into background LRU pool when
* its priority changed to BACKGROUND from others.
*/
void AddIntoBackgroundLRUPool(ContentParent* aContentParent);
private:
static StaticAutoPtr<BackgroundProcessLRUPool> sSingleton;
int32_t mLRUPoolLevels;
int32_t mLRUPoolSize;
int32_t mLRUPoolAvailableIndex;
nsTArray<ContentParent*> mLRUPool;
uint32_t CalculateLRULevel(uint32_t aBackgroundLRUPoolIndex);
nsresult UpdateAvailableIndexInLRUPool(
ContentParent* aContentParent,
int32_t aTargetIndex = -1);
void ShiftLRUPool();
void EnsureLRUPool();
BackgroundProcessLRUPool();
DISALLOW_EVIL_CONSTRUCTORS(BackgroundProcessLRUPool);
};
/* static */ bool ProcessPriorityManagerImpl::sInitialized = false;
/* static */ bool ProcessPriorityManagerImpl::sPrefListenersRegistered = false;
/* static */ StaticRefPtr<ProcessPriorityManagerImpl>
@ -399,6 +407,8 @@ ProcessPriorityManagerImpl::GetSingleton()
ProcessPriorityManagerImpl::ProcessPriorityManagerImpl()
: mHighPriority(false)
, mBackgroundLRUPool(PROCESS_PRIORITY_BACKGROUND, 1)
, mForegroundLRUPool(PROCESS_PRIORITY_FOREGROUND, 0)
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
RegisterWakeLockObserver(this);
@ -473,13 +483,13 @@ ProcessPriorityManagerImpl::GetParticularProcessPriorityManager(
void
ProcessPriorityManagerImpl::SetProcessPriority(ContentParent* aContentParent,
ProcessPriority aPriority,
uint32_t aBackgroundLRU)
uint32_t aLRU)
{
MOZ_ASSERT(aContentParent);
nsRefPtr<ParticularProcessPriorityManager> pppm =
GetParticularProcessPriorityManager(aContentParent);
if (pppm) {
pppm->SetPriorityNow(aPriority, aBackgroundLRU);
pppm->SetPriorityNow(aPriority, aLRU);
}
}
@ -507,6 +517,10 @@ ProcessPriorityManagerImpl::ObserveContentParentDestroyed(nsISupports* aSubject)
nsRefPtr<ParticularProcessPriorityManager> pppm;
mParticularManagers.Get(childID, &pppm);
if (pppm) {
// Unconditionally remove the manager from the pools
mBackgroundLRUPool.Remove(pppm);
mForegroundLRUPool.Remove(pppm);
pppm->ShutDown();
mParticularManagers.Remove(childID);
@ -528,21 +542,32 @@ ProcessPriorityManagerImpl::NotifyProcessPriorityChanged(
ParticularProcessPriorityManager* aParticularManager,
ProcessPriority aOldPriority)
{
/* We're interested only in changes to/from FOREGROUND_HIGH as we use we
* need to track high priority processes so that we can react to their
* presence. */
ProcessPriority newPriority = aParticularManager->CurrentPriority();
bool isPreallocated = aParticularManager->IsPreallocated();
if (aOldPriority < PROCESS_PRIORITY_FOREGROUND_HIGH &&
aParticularManager->CurrentPriority() <
PROCESS_PRIORITY_FOREGROUND_HIGH) {
return;
if (newPriority == PROCESS_PRIORITY_BACKGROUND &&
aOldPriority != PROCESS_PRIORITY_BACKGROUND &&
!isPreallocated) {
mBackgroundLRUPool.Add(aParticularManager);
} else if (newPriority != PROCESS_PRIORITY_BACKGROUND &&
aOldPriority == PROCESS_PRIORITY_BACKGROUND &&
!isPreallocated) {
mBackgroundLRUPool.Remove(aParticularManager);
}
if (aParticularManager->CurrentPriority() >=
PROCESS_PRIORITY_FOREGROUND_HIGH) {
if (newPriority == PROCESS_PRIORITY_FOREGROUND &&
aOldPriority != PROCESS_PRIORITY_FOREGROUND) {
mForegroundLRUPool.Add(aParticularManager);
} else if (newPriority != PROCESS_PRIORITY_FOREGROUND &&
aOldPriority == PROCESS_PRIORITY_FOREGROUND) {
mForegroundLRUPool.Remove(aParticularManager);
}
if (newPriority >= PROCESS_PRIORITY_FOREGROUND_HIGH &&
aOldPriority < PROCESS_PRIORITY_FOREGROUND_HIGH) {
mHighPriorityChildIDs.PutEntry(aParticularManager->ChildID());
} else {
} else if (newPriority < PROCESS_PRIORITY_FOREGROUND_HIGH &&
aOldPriority >= PROCESS_PRIORITY_FOREGROUND_HIGH) {
mHighPriorityChildIDs.RemoveEntry(aParticularManager->ChildID());
}
}
@ -575,6 +600,7 @@ ParticularProcessPriorityManager::ParticularProcessPriorityManager(
: mContentParent(aContentParent)
, mChildID(aContentParent->ChildID())
, mPriority(PROCESS_PRIORITY_UNKNOWN)
, mLRU(0)
, mHoldsCPUWakeLock(false)
, mHoldsHighPriorityWakeLock(false)
{
@ -937,51 +963,31 @@ ParticularProcessPriorityManager::ComputePriority()
void
ParticularProcessPriorityManager::SetPriorityNow(ProcessPriority aPriority,
uint32_t aBackgroundLRU)
uint32_t aLRU)
{
if (aPriority == PROCESS_PRIORITY_UNKNOWN) {
MOZ_ASSERT(false);
return;
}
if (aBackgroundLRU > 0 &&
aPriority == PROCESS_PRIORITY_BACKGROUND &&
mPriority == PROCESS_PRIORITY_BACKGROUND) {
hal::SetProcessPriority(Pid(), mPriority, aBackgroundLRU);
nsPrintfCString ProcessPriorityWithBackgroundLRU("%s:%d",
ProcessPriorityToString(mPriority), aBackgroundLRU);
FireTestOnlyObserverNotification("process-priority-with-background-LRU-set",
ProcessPriorityWithBackgroundLRU.get());
}
if (!mContentParent ||
!ProcessPriorityManagerImpl::PrefsEnabled() ||
(mPriority == aPriority)) {
if (!ProcessPriorityManagerImpl::PrefsEnabled() ||
!mContentParent ||
((mPriority == aPriority) && (mLRU == aLRU))) {
return;
}
// If the prefs were disabled after this ParticularProcessPriorityManager was
// created, we can at least avoid any further calls to
// hal::SetProcessPriority. Supporting dynamic enabling/disabling of the
// ProcessPriorityManager is mostly for testing.
if (!ProcessPriorityManagerImpl::PrefsEnabled()) {
if ((mPriority == aPriority) && (mLRU != aLRU)) {
mLRU = aLRU;
hal::SetProcessPriority(Pid(), mPriority, aLRU);
nsPrintfCString processPriorityWithLRU("%s:%d",
ProcessPriorityToString(mPriority), aLRU);
FireTestOnlyObserverNotification("process-priority-with-LRU-set",
processPriorityWithLRU.get());
return;
}
if (aPriority == PROCESS_PRIORITY_BACKGROUND &&
mPriority != PROCESS_PRIORITY_BACKGROUND &&
!IsPreallocated()) {
ProcessPriorityManager::AddIntoBackgroundLRUPool(mContentParent);
}
if (aPriority != PROCESS_PRIORITY_BACKGROUND &&
mPriority == PROCESS_PRIORITY_BACKGROUND &&
!IsPreallocated()) {
ProcessPriorityManager::RemoveFromBackgroundLRUPool(mContentParent);
}
LOGP("Changing priority from %s to %s.",
ProcessPriorityToString(mPriority),
ProcessPriorityToString(aPriority));
@ -1018,10 +1024,6 @@ ParticularProcessPriorityManager::ShutDown()
mResetPriorityTimer = nullptr;
}
if (mPriority == PROCESS_PRIORITY_BACKGROUND && !IsPreallocated()) {
ProcessPriorityManager::RemoveFromBackgroundLRUPool(mContentParent);
}
mContentParent = nullptr;
}
@ -1162,179 +1164,112 @@ ProcessPriorityManagerChild::CurrentProcessIsHighPriority()
mCachedPriority >= PROCESS_PRIORITY_FOREGROUND_HIGH;
}
/* static */ StaticAutoPtr<BackgroundProcessLRUPool>
BackgroundProcessLRUPool::sSingleton;
/* static */ BackgroundProcessLRUPool*
BackgroundProcessLRUPool::Singleton()
ProcessLRUPool::ProcessLRUPool(ProcessPriority aPriority, uint32_t aBias)
: mPriority(aPriority)
, mLRUPoolLevels(1)
, mBias(aBias)
{
if (!sSingleton) {
sSingleton = new BackgroundProcessLRUPool();
ClearOnShutdown(&sSingleton);
}
return sSingleton;
}
BackgroundProcessLRUPool::BackgroundProcessLRUPool()
{
EnsureLRUPool();
}
uint32_t
BackgroundProcessLRUPool::CalculateLRULevel(uint32_t aBackgroundLRUPoolIndex)
{
// Set LRU level of each background process and maintain LRU buffer as below:
// Priority background : LRU0
// Priority background+1: LRU1, LRU2
// Priority background+2: LRU3, LRU4, LRU5, LRU6
// Priority background+3: LRU7, LRU8, LRU9, LRU10, LRU11, LRU12, LRU13, LRU14
// ...
// Priority background+L-1: 2^(number of background LRU pool levels - 1)
// (End of buffer)
return (uint32_t)(log((float)aBackgroundLRUPoolIndex) / log(2.0));
}
void
BackgroundProcessLRUPool::EnsureLRUPool()
{
// We set mBackgroundLRUPoolLevels according to our pref.
// We set mLRUPoolLevels according to our pref.
// This value is used to set background process LRU pool
if (!NS_SUCCEEDED(Preferences::GetInt(
"dom.ipc.processPriorityManager.backgroundLRUPoolLevels",
&mLRUPoolLevels))) {
mLRUPoolLevels = 1;
}
const char* str = ProcessPriorityToString(aPriority);
nsPrintfCString pref("dom.ipc.processPriorityManager.%s.LRUPoolLevels", str);
if (mLRUPoolLevels <= 0) {
MOZ_CRASH();
}
Preferences::GetUint(pref.get(), &mLRUPoolLevels);
// GonkHal defines OOM_ADJUST_MAX is 15 and b2g.js defines
// PROCESS_PRIORITY_BACKGROUND's oom_score_adj is 667 and oom_adj is 10.
// This means we can only have at most (15 -10 + 1) = 6 background LRU levels.
// See bug 822325 comment 49
MOZ_ASSERT(mLRUPoolLevels <= 6);
// Similarly we can have at most 4 foreground LRU levels. We should really be
// getting rid of oom_adj and just rely on oom_score_adj only which would
// lift this constraint.
MOZ_ASSERT(aPriority != PROCESS_PRIORITY_BACKGROUND || mLRUPoolLevels <= 6);
MOZ_ASSERT(aPriority != PROCESS_PRIORITY_FOREGROUND || mLRUPoolLevels <= 4);
// LRU pool size = 2 ^ (number of background LRU pool levels) - 1
mLRUPoolSize = (1 << mLRUPoolLevels) - 1;
mLRUPoolAvailableIndex = 0;
LOG("Making %s LRU pool with size(%d)", str, mLRUPoolSize);
}
LOG("Making background LRU pool with size(%d)", mLRUPoolSize);
uint32_t
ProcessLRUPool::CalculateLRULevel(uint32_t aLRU)
{
// This is used to compute the LRU adjustment for the specified LRU position.
// We use power-of-two groups with increasing adjustments that look like the
// following:
mLRUPool.InsertElementsAt(0, mLRUPoolSize, (ContentParent*)nullptr);
// Priority : LRU0, LRU1
// Priority+1: LRU2, LRU3
// Priority+2: LRU4, LRU5, LRU6, LRU7
// Priority+3: LRU8, LRU9, LRU10, LRU11, LRU12, LRU12, LRU13, LRU14, LRU15
// ...
// Priority+L-1: 2^(number of LRU pool levels - 1)
// (End of buffer)
// Biasing the input can be used to shift the assignment
int exp;
unused << frexp(static_cast<double>(aLRU), &exp);
uint32_t level = std::max(exp - 1, 0);
return std::min(mLRUPoolLevels - 1, level);
}
void
BackgroundProcessLRUPool::RemoveFromBackgroundLRUPool(
ContentParent* aContentParent)
ProcessLRUPool::Remove(ParticularProcessPriorityManager* aParticularManager)
{
for (int32_t i = 0; i < mLRUPoolSize; i++) {
if (mLRUPool[i]) {
if (mLRUPool[i]->ChildID() == aContentParent->ChildID()) {
nsTArray<ParticularProcessPriorityManager*>::index_type index =
mLRUPool.IndexOf(aParticularManager);
mLRUPool[i] = nullptr;
LOG("Remove ChildID(%llu) from LRU pool", aContentParent->ChildID());
// After we remove this ContentParent from LRU pool, we still need to
// update the available index if the index of removed one is less than
// the available index we already have.
UpdateAvailableIndexInLRUPool(aContentParent, i);
break;
}
}
}
}
nsresult
BackgroundProcessLRUPool::UpdateAvailableIndexInLRUPool(
ContentParent* aContentParent,
int32_t aTargetIndex)
{
// If we specify which index we want to assign to mLRUPoolAvailableIndex,
// We have to make sure the index in LRUPool doesn't point to any
// ContentParent.
if (aTargetIndex >= 0 && aTargetIndex < mLRUPoolSize &&
aTargetIndex < mLRUPoolAvailableIndex &&
!mLRUPool[aTargetIndex]) {
mLRUPoolAvailableIndex = aTargetIndex;
return NS_OK;
}
// When we didn't specify any legal aTargetIndex, then we just check
// whether current mLRUPoolAvailableIndex points to any ContentParent or not.
if (mLRUPoolAvailableIndex >= 0 && mLRUPoolAvailableIndex < mLRUPoolSize &&
!(mLRUPool[mLRUPoolAvailableIndex])) {
return NS_OK;
}
// Both above way failed. So now we have to find proper value
// for mLRUPoolAvailableIndex.
// We are looking for an available index. We only shift process with
// LRU less than the available index should have, so we stop update
// mLRUPoolAvailableIndex from the for loop once we got a candidate.
mLRUPoolAvailableIndex = -1;
for (int32_t i = 0; i < mLRUPoolSize; i++) {
if (mLRUPool[i]) {
if (mLRUPool[i]->ChildID() == aContentParent->ChildID()) {
LOG("ChildID(%llu) already in LRU pool", aContentParent->ChildID());
MOZ_ASSERT(false);
return NS_ERROR_UNEXPECTED;
}
continue;
} else {
if (mLRUPoolAvailableIndex == -1) {
mLRUPoolAvailableIndex = i;
}
}
}
// If the LRUPool is already full, mLRUPoolAvailableIndex is still -1 after
// above loop finished. We should set mLRUPoolAvailableIndex
// to mLRUPoolSize - 1 in this case. Here uses the mod operator to do it:
// New mLRUPoolAvailableIndex either equals old mLRUPoolAvailableIndex, or
// mLRUPoolSize - 1 if old mLRUPoolAvailableIndex is -1.
mLRUPoolAvailableIndex =
(mLRUPoolAvailableIndex + mLRUPoolSize) % mLRUPoolSize;
return NS_OK;
}
void
BackgroundProcessLRUPool::ShiftLRUPool()
{
for (int32_t i = mLRUPoolAvailableIndex; i > 0; i--) {
mLRUPool[i] = mLRUPool[i - 1];
// Check whether i+1 is power of Two.
// If so, then it crossed a LRU group boundary and
// we need to assign its new process priority LRU.
if (!((i + 1) & i)) {
ProcessPriorityManagerImpl::GetSingleton()->SetProcessPriority(
mLRUPool[i], PROCESS_PRIORITY_BACKGROUND, CalculateLRULevel(i + 1));
}
}
}
void
BackgroundProcessLRUPool::AddIntoBackgroundLRUPool(
ContentParent* aContentParent)
{
// We have to make sure that we have correct available index in LRU pool
if (!NS_SUCCEEDED(
UpdateAvailableIndexInLRUPool(aContentParent))) {
if (index == nsTArray<ParticularProcessPriorityManager*>::NoIndex) {
return;
}
mLRUPool.RemoveElementAt(index);
AdjustLRUValues(index, /* removed */ true);
LOG("Remove ChildID(%" PRIu64 ") from %s LRU pool",
static_cast<uint64_t>(aParticularManager->ChildID()),
ProcessPriorityToString(mPriority));
}
/*
* Adjust the LRU values of all the processes in an LRU pool. When true the
* `removed` parameter indicates that the processes were shifted left because
* an element was removed; otherwise it means the elements were shifted right
* as an element was added.
*/
void
ProcessLRUPool::AdjustLRUValues(
nsTArray<ParticularProcessPriorityManager*>::index_type aStart,
bool removed)
{
uint32_t adj = (removed ? 1 : 0) + mBias;
for (nsTArray<ParticularProcessPriorityManager*>::index_type i = aStart;
i < mLRUPool.Length();
i++) {
/* Check whether i is a power of two. If so, then it crossed a LRU group
* boundary and we need to assign its new process priority LRU. Note that
* depending on the direction and the bias this test will pick different
* elements. */
if (((i + adj) & (i + adj - 1)) == 0) {
mLRUPool[i]->SetPriorityNow(mPriority, CalculateLRULevel(i + mBias));
}
}
}
void
ProcessLRUPool::Add(ParticularProcessPriorityManager* aParticularManager)
{
// Shift the list in the pool, so we have room at index 0 for the newly added
// ContentParent
ShiftLRUPool();
// manager
mLRUPool.InsertElementAt(0, aParticularManager);
AdjustLRUValues(1, /* removed */ false);
mLRUPool[0] = aContentParent;
LOG("Add ChildID(%llu) into LRU pool", aContentParent->ChildID());
LOG("Add ChildID(%" PRIu64 ") into %s LRU pool",
static_cast<uint64_t>(aParticularManager->ChildID()),
ProcessPriorityToString(mPriority));
}
} // anonymous namespace
@ -1361,31 +1296,6 @@ ProcessPriorityManager::SetProcessPriority(ContentParent* aContentParent,
}
}
/* static */ void
ProcessPriorityManager::RemoveFromBackgroundLRUPool(
ContentParent* aContentParent)
{
MOZ_ASSERT(aContentParent);
BackgroundProcessLRUPool* singleton =
BackgroundProcessLRUPool::Singleton();
if (singleton) {
singleton->RemoveFromBackgroundLRUPool(aContentParent);
}
}
/* static */ void
ProcessPriorityManager::AddIntoBackgroundLRUPool(ContentParent* aContentParent)
{
MOZ_ASSERT(aContentParent);
BackgroundProcessLRUPool* singleton =
BackgroundProcessLRUPool::Singleton();
if (singleton) {
singleton->AddIntoBackgroundLRUPool(aContentParent);
}
}
/* static */ bool
ProcessPriorityManager::CurrentProcessIsForeground()
{

View File

@ -74,18 +74,6 @@ public:
*/
static bool AnyProcessHasHighPriority();
/**
* Used to remove a ContentParent from background LRU pool when
* it is destroyed or its priority changed from BACKGROUND to others.
*/
static void RemoveFromBackgroundLRUPool(dom::ContentParent* aContentParent);
/**
* Used to add a ContentParent into background LRU pool when
* its priority changed to BACKGROUND from others.
*/
static void AddIntoBackgroundLRUPool(dom::ContentParent* aContentParent);
private:
ProcessPriorityManager();
DISALLOW_EVIL_CONSTRUCTORS(ProcessPriorityManager);

View File

@ -51,7 +51,7 @@ function setPref(pref, value) {
setPref('dom.ipc.processPriorityManager.testMode', true);
setPref('dom.ipc.processPriorityManager.enabled', true);
setPref('dom.ipc.processPriorityManager.backgroundLRUPoolLevels', 2);
setPref('dom.ipc.processPriorityManager.BACKGROUND.LRUPoolLevels', 2);
function runTest()
{

View File

@ -51,7 +51,7 @@ function setPref(pref, value) {
setPref('dom.ipc.processPriorityManager.testMode', true);
setPref('dom.ipc.processPriorityManager.enabled', true);
setPref('dom.ipc.processPriorityManager.backgroundLRUPoolLevels', 2);
setPref('dom.ipc.processPriorityManager.BACKGROUND.LRUPoolLevels', 2);
setPref('dom.ipc.processPrelaunch.testMode', true); // For testing deadlock.
function runTest()

View File

@ -861,14 +861,11 @@ SetAlarm(int32_t aSeconds, int32_t aNanoseconds)
}
void
SetProcessPriority(int aPid,
ProcessPriority aPriority,
uint32_t aBackgroundLRU)
SetProcessPriority(int aPid, ProcessPriority aPriority, uint32_t aLRU)
{
// n.b. The sandboxed implementation crashes; SetProcessPriority works only
// from the main process.
MOZ_ASSERT(aBackgroundLRU == 0 || aPriority == PROCESS_PRIORITY_BACKGROUND);
PROXY_IF_SANDBOXED(SetProcessPriority(aPid, aPriority, aBackgroundLRU));
PROXY_IF_SANDBOXED(SetProcessPriority(aPid, aPriority, aLRU));
}
void

View File

@ -11,12 +11,10 @@ namespace mozilla {
namespace hal_impl {
void
SetProcessPriority(int aPid,
ProcessPriority aPriority,
uint32_t aBackgroundLRU)
SetProcessPriority(int aPid, ProcessPriority aPriority, uint32_t aLRU)
{
HAL_LOG("FallbackProcessPriority - SetProcessPriority(%d, %s, %u)\n",
aPid, ProcessPriorityToString(aPriority), aBackgroundLRU);
aPid, ProcessPriorityToString(aPriority), aLRU);
}
} // hal_impl

View File

@ -1199,12 +1199,12 @@ OomAdjOfOomScoreAdj(int aOomScoreAdj)
}
static void
RoundOomScoreAdjUpWithBackroundLRU(int& aOomScoreAdj, uint32_t aBackgroundLRU)
RoundOomScoreAdjUpWithLRU(int& aOomScoreAdj, uint32_t aLRU)
{
// We want to add minimum value to round OomScoreAdj up according to
// the steps by aBackgroundLRU.
// the steps by aLRU.
aOomScoreAdj +=
ceil(((float)OOM_SCORE_ADJ_MAX / OOM_ADJUST_MAX) * aBackgroundLRU);
ceil(((float)OOM_SCORE_ADJ_MAX / OOM_ADJUST_MAX) * aLRU);
}
#define OOM_LOG(level, args...) __android_log_print(level, "OomLogger", ##args)
@ -1790,12 +1790,10 @@ EnsureKernelLowMemKillerParamsSet()
}
void
SetProcessPriority(int aPid,
ProcessPriority aPriority,
uint32_t aBackgroundLRU)
SetProcessPriority(int aPid, ProcessPriority aPriority, uint32_t aLRU)
{
HAL_LOG("SetProcessPriority(pid=%d, priority=%d, LRU=%u)",
aPid, aPriority, aBackgroundLRU);
aPid, aPriority, aLRU);
// If this is the first time SetProcessPriority was called, set the kernel's
// OOM parameters according to our prefs.
@ -1810,7 +1808,7 @@ SetProcessPriority(int aPid,
int oomScoreAdj = pc->OomScoreAdj();
RoundOomScoreAdjUpWithBackroundLRU(oomScoreAdj, aBackgroundLRU);
RoundOomScoreAdjUpWithLRU(oomScoreAdj, aLRU);
// We try the newer interface first, and fall back to the older interface
// on failure.

View File

@ -355,9 +355,7 @@ SetAlarm(int32_t aSeconds, int32_t aNanoseconds)
}
void
SetProcessPriority(int aPid,
ProcessPriority aPriority,
uint32_t aBackgroundLRU)
SetProcessPriority(int aPid, ProcessPriority aPriority, uint32_t aLRU)
{
NS_RUNTIMEABORT("Only the main process may set processes' priorities.");
}