Bug 1082290 - Add memory cgroup support to FxOS process control. r=gsvelto

This commit is contained in:
Dave Hylands 2015-01-12 14:19:00 -05:00
parent bcaf7910f2
commit f49858767d
2 changed files with 112 additions and 17 deletions

View File

@ -728,22 +728,30 @@ pref("hal.processPriorityManager.gonk.BACKGROUND.KillUnderKB", 20480);
pref("hal.processPriorityManager.gonk.BACKGROUND.cgroup", "apps/bg_non_interactive");
// Control group definitions (i.e., CPU priority groups) for B2G processes.
//
// memory_swappiness - 0 - The kernel will swap only to avoid an out of memory condition
// memory_swappiness - 60 - The default value.
// memory_swappiness - 100 - The kernel will swap aggressively.
// Foreground apps
pref("hal.processPriorityManager.gonk.cgroups.apps.cpu_shares", 1024);
pref("hal.processPriorityManager.gonk.cgroups.apps.cpu_notify_on_migrate", 0);
pref("hal.processPriorityManager.gonk.cgroups.apps.memory_swappiness", 10);
// Foreground apps with high priority, 16x more CPU than foreground ones
pref("hal.processPriorityManager.gonk.cgroups.apps/critical.cpu_shares", 16384);
pref("hal.processPriorityManager.gonk.cgroups.apps/critical.cpu_notify_on_migrate", 0);
pref("hal.processPriorityManager.gonk.cgroups.apps/critical.memory_swappiness", 0);
// Background perceivable apps, ~10x less CPU than foreground ones
pref("hal.processPriorityManager.gonk.cgroups.apps/bg_perceivable.cpu_shares", 103);
pref("hal.processPriorityManager.gonk.cgroups.apps/bg_perceivable.cpu_notify_on_migrate", 0);
pref("hal.processPriorityManager.gonk.cgroups.apps/bg_perceivable.memory_swappiness", 60);
// Background apps, ~20x less CPU than foreground ones and ~2x less than perceivable ones
pref("hal.processPriorityManager.gonk.cgroups.apps/bg_non_interactive.cpu_shares", 52);
pref("hal.processPriorityManager.gonk.cgroups.apps/bg_non_interactive.cpu_notify_on_migrate", 0);
pref("hal.processPriorityManager.gonk.cgroups.apps/bg_non_interactive.memory_swappiness", 100);
// By default the compositor thread on gonk runs without real-time priority. RT
// priority can be enabled by setting this pref to a value between 1 and 99.

View File

@ -1351,7 +1351,8 @@ private:
ProcessPriority mPriority;
int32_t mOomScoreAdj;
int32_t mKillUnderKB;
int mCGroupProcsFd;
int mCpuCGroupProcsFd;
int mMemCGroupProcsFd;
nsCString mGroup;
/**
@ -1368,7 +1369,7 @@ private:
/**
* Get the full path of the cgroup.procs file associated with the group.
*/
nsCString CGroupProcsFilename()
nsCString CpuCGroupProcsFilename()
{
nsCString cgroupName = mGroup;
@ -1384,9 +1385,30 @@ private:
NS_LITERAL_CSTRING("cgroup.procs");
}
int OpenCGroupProcs()
nsCString MemCGroupProcsFilename()
{
return open(CGroupProcsFilename().get(), O_WRONLY);
nsCString cgroupName = mGroup;
/* If mGroup is empty, our cgroup.procs file is the root procs file,
* located at /sys/fs/cgroup/memory/cgroup.procs. Otherwise our procs
* file is /sys/fs/cgroup/memory/NAME/cgroup.procs. */
if (!mGroup.IsEmpty()) {
cgroupName.AppendLiteral("/");
}
return NS_LITERAL_CSTRING("/sys/fs/cgroup/memory/") + cgroupName +
NS_LITERAL_CSTRING("cgroup.procs");
}
int OpenCpuCGroupProcs()
{
return open(CpuCGroupProcsFilename().get(), O_WRONLY);
}
int OpenMemCGroupProcs()
{
return open(MemCGroupProcsFilename().get(), O_WRONLY);
}
};
@ -1401,11 +1423,14 @@ private:
* exists. Otherwise, return false.
*/
static bool
EnsureCGroupExists(const nsACString &aGroup)
EnsureCpuCGroupExists(const nsACString &aGroup)
{
NS_NAMED_LITERAL_CSTRING(kDevCpuCtl, "/dev/cpuctl/");
NS_NAMED_LITERAL_CSTRING(kSlash, "/");
nsAutoCString groupName(aGroup);
HAL_LOG("EnsureCpuCGroupExists for group '%s'", groupName.get());
nsAutoCString prefPrefix("hal.processPriorityManager.gonk.cgroups.");
/* If cgroup is not empty, append the cgroup name and a dot to obtain the
@ -1436,6 +1461,7 @@ EnsureCGroupExists(const nsACString &aGroup)
offset++;
}
HAL_LOG("EnsureCpuCGroupExists created group '%s'", groupName.get());
nsAutoCString pathPrefix(kDevCpuCtl + aGroup + kSlash);
nsAutoCString cpuSharesPath(pathPrefix + NS_LITERAL_CSTRING("cpu.shares"));
@ -1457,11 +1483,61 @@ EnsureCGroupExists(const nsACString &aGroup)
return true;
}
static bool
EnsureMemCGroupExists(const nsACString &aGroup)
{
NS_NAMED_LITERAL_CSTRING(kMemCtl, "/sys/fs/cgroup/memory/");
NS_NAMED_LITERAL_CSTRING(kSlash, "/");
nsAutoCString groupName(aGroup);
HAL_LOG("EnsureMemCGroupExists for group '%s'", groupName.get());
nsAutoCString prefPrefix("hal.processPriorityManager.gonk.cgroups.");
/* If cgroup is not empty, append the cgroup name and a dot to obtain the
* group specific preferences. */
if (!aGroup.IsEmpty()) {
prefPrefix += aGroup + NS_LITERAL_CSTRING(".");
}
nsAutoCString memSwappinessPref(prefPrefix + NS_LITERAL_CSTRING("memory_swappiness"));
int memSwappiness = Preferences::GetInt(memSwappinessPref.get());
// Create mCGroup and its parent directories, as necessary.
nsCString cgroupIter = aGroup + kSlash;
int32_t offset = 0;
while ((offset = cgroupIter.FindChar('/', offset)) != -1) {
nsAutoCString path = kMemCtl + Substring(cgroupIter, 0, offset);
int rv = mkdir(path.get(), 0744);
if (rv == -1 && errno != EEXIST) {
HAL_LOG("Could not create the %s control group.", path.get());
return false;
}
offset++;
}
HAL_LOG("EnsureMemCGroupExists created group '%s'", groupName.get());
nsAutoCString pathPrefix(kMemCtl + aGroup + kSlash);
nsAutoCString memSwappinessPath(pathPrefix + NS_LITERAL_CSTRING("memory.swappiness"));
if (!WriteToFile(memSwappinessPath.get(),
nsPrintfCString("%d", memSwappiness).get())) {
HAL_LOG("Could not set the memory.swappiness for group %s", memSwappinessPath.get());
return false;
}
HAL_LOG("Set memory.swappiness for group %s to %d", memSwappinessPath.get(), memSwappiness);
return true;
}
PriorityClass::PriorityClass(ProcessPriority aPriority)
: mPriority(aPriority)
, mOomScoreAdj(0)
, mKillUnderKB(0)
, mCGroupProcsFd(-1)
, mCpuCGroupProcsFd(-1)
, mMemCGroupProcsFd(-1)
{
DebugOnly<nsresult> rv;
@ -1475,14 +1551,18 @@ PriorityClass::PriorityClass(ProcessPriority aPriority)
rv = Preferences::GetCString(PriorityPrefName("cgroup").get(), &mGroup);
MOZ_ASSERT(NS_SUCCEEDED(rv), "Missing control group preference");
if (EnsureCGroupExists(mGroup)) {
mCGroupProcsFd = OpenCGroupProcs();
if (EnsureCpuCGroupExists(mGroup)) {
mCpuCGroupProcsFd = OpenCpuCGroupProcs();
}
if (EnsureMemCGroupExists(mGroup)) {
mMemCGroupProcsFd = OpenMemCGroupProcs();
}
}
PriorityClass::~PriorityClass()
{
close(mCGroupProcsFd);
close(mCpuCGroupProcsFd);
close(mMemCGroupProcsFd);
}
PriorityClass::PriorityClass(const PriorityClass& aOther)
@ -1491,7 +1571,8 @@ PriorityClass::PriorityClass(const PriorityClass& aOther)
, mKillUnderKB(aOther.mKillUnderKB)
, mGroup(aOther.mGroup)
{
mCGroupProcsFd = OpenCGroupProcs();
mCpuCGroupProcsFd = OpenCpuCGroupProcs();
mMemCGroupProcsFd = OpenMemCGroupProcs();
}
PriorityClass& PriorityClass::operator=(const PriorityClass& aOther)
@ -1500,20 +1581,26 @@ PriorityClass& PriorityClass::operator=(const PriorityClass& aOther)
mOomScoreAdj = aOther.mOomScoreAdj;
mKillUnderKB = aOther.mKillUnderKB;
mGroup = aOther.mGroup;
mCGroupProcsFd = OpenCGroupProcs();
mCpuCGroupProcsFd = OpenCpuCGroupProcs();
mMemCGroupProcsFd = OpenMemCGroupProcs();
return *this;
}
void PriorityClass::AddProcess(int aPid)
{
if (mCGroupProcsFd < 0) {
return;
}
if (mCpuCGroupProcsFd >= 0) {
nsPrintfCString str("%d", aPid);
if (write(mCGroupProcsFd, str.get(), strlen(str.get())) < 0) {
HAL_ERR("Couldn't add PID %d to the %s control group", aPid, mGroup.get());
if (write(mCpuCGroupProcsFd, str.get(), strlen(str.get())) < 0) {
HAL_ERR("Couldn't add PID %d to the %s cpu control group", aPid, mGroup.get());
}
}
if (mMemCGroupProcsFd >= 0) {
nsPrintfCString str("%d", aPid);
if (write(mMemCGroupProcsFd, str.get(), strlen(str.get())) < 0) {
HAL_ERR("Couldn't add PID %d to the %s memory control group", aPid, mGroup.get());
}
}
}