mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1082290 - Add memory cgroup support to FxOS process control. r=gsvelto
This commit is contained in:
parent
fc7c0ecc40
commit
adf1953f29
@ -730,22 +730,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", 1);
|
||||
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", 1);
|
||||
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.
|
||||
|
@ -1323,7 +1323,8 @@ private:
|
||||
ProcessPriority mPriority;
|
||||
int32_t mOomScoreAdj;
|
||||
int32_t mKillUnderKB;
|
||||
int mCGroupProcsFd;
|
||||
int mCpuCGroupProcsFd;
|
||||
int mMemCGroupProcsFd;
|
||||
nsCString mGroup;
|
||||
|
||||
/**
|
||||
@ -1340,7 +1341,7 @@ private:
|
||||
/**
|
||||
* Get the full path of the cgroup.procs file associated with the group.
|
||||
*/
|
||||
nsCString CGroupProcsFilename()
|
||||
nsCString CpuCGroupProcsFilename()
|
||||
{
|
||||
nsCString cgroupName = mGroup;
|
||||
|
||||
@ -1356,12 +1357,60 @@ 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);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a directory and parents (essentially mkdir -p, but
|
||||
* this only create the directories within the cgroup name).
|
||||
*/
|
||||
static bool MakeCGroupDir(const nsACString& aRootDir,
|
||||
const nsACString& aGroupName)
|
||||
{
|
||||
NS_NAMED_LITERAL_CSTRING(kSlash, "/");
|
||||
|
||||
// Create directories contained within aGroupName
|
||||
nsCString cgroupIter = aGroupName + kSlash;
|
||||
|
||||
int32_t offset = 0;
|
||||
while ((offset = cgroupIter.FindChar('/', offset)) != -1) {
|
||||
nsAutoCString path = aRootDir + 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++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to create the cgroup for the given PriorityClass, if it doesn't already
|
||||
* exist. This essentially implements mkdir -p; that is, we create parent
|
||||
@ -1373,7 +1422,7 @@ 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, "/");
|
||||
@ -1393,20 +1442,8 @@ EnsureCGroupExists(const nsACString &aGroup)
|
||||
+ NS_LITERAL_CSTRING("cpu_notify_on_migrate"));
|
||||
int cpuNotifyOnMigrate = Preferences::GetInt(cpuNotifyOnMigratePref.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 = kDevCpuCtl + 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++;
|
||||
if (!MakeCGroupDir(kDevCpuCtl, aGroup)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsAutoCString pathPrefix(kDevCpuCtl + aGroup + kSlash);
|
||||
@ -1429,11 +1466,46 @@ 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 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());
|
||||
|
||||
if (!MakeCGroupDir(kMemCtl, aGroup)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
PriorityClass::PriorityClass(ProcessPriority aPriority)
|
||||
: mPriority(aPriority)
|
||||
, mOomScoreAdj(0)
|
||||
, mKillUnderKB(0)
|
||||
, mCGroupProcsFd(-1)
|
||||
, mCpuCGroupProcsFd(-1)
|
||||
, mMemCGroupProcsFd(-1)
|
||||
{
|
||||
DebugOnly<nsresult> rv;
|
||||
|
||||
@ -1447,14 +1519,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);
|
||||
MOZ_TEMP_FAILURE_RETRY(close(mCpuCGroupProcsFd));
|
||||
MOZ_TEMP_FAILURE_RETRY(close(mMemCGroupProcsFd));
|
||||
}
|
||||
|
||||
PriorityClass::PriorityClass(const PriorityClass& aOther)
|
||||
@ -1463,7 +1539,8 @@ PriorityClass::PriorityClass(const PriorityClass& aOther)
|
||||
, mKillUnderKB(aOther.mKillUnderKB)
|
||||
, mGroup(aOther.mGroup)
|
||||
{
|
||||
mCGroupProcsFd = OpenCGroupProcs();
|
||||
mCpuCGroupProcsFd = OpenCpuCGroupProcs();
|
||||
mMemCGroupProcsFd = OpenMemCGroupProcs();
|
||||
}
|
||||
|
||||
PriorityClass& PriorityClass::operator=(const PriorityClass& aOther)
|
||||
@ -1472,20 +1549,29 @@ 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(mCpuCGroupProcsFd, str.get(), str.Length()) < 0) {
|
||||
HAL_ERR("Couldn't add PID %d to the %s cpu control group",
|
||||
aPid, mGroup.get());
|
||||
}
|
||||
}
|
||||
|
||||
nsPrintfCString str("%d", aPid);
|
||||
if (mMemCGroupProcsFd >= 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(mMemCGroupProcsFd, str.get(), str.Length()) < 0) {
|
||||
HAL_ERR("Couldn't add PID %d to the %s memory control group",
|
||||
aPid, mGroup.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user