--- a/hal/gonk/GonkHal.cpp
+++ b/hal/gonk/GonkHal.cpp
@@ -1479,16 +1479,64 @@ SetNiceForPid(int aPid, int aNice)
}
HAL_LOG("Changed nice for pid %d from %d to %d.",
aPid, origProcPriority, aNice);
closedir(tasksDir);
}
+/*
+ * Used to store the nice value adjustments and oom_adj values for the various
+ * process priority levels.
+ */
+struct ProcessPriorityPrefs {
+ bool initialized;
+ int lowPriorityNice;
+ struct {
+ int nice;
+ int oomScoreAdj;
+ } priorities[NUM_PROCESS_PRIORITY];
+};
+
+/*
+ * Reads the preferences for the various process priority levels and sets up
+ * watchers so that if they're dynamically changed the change is reflected on
+ * the appropriate variables.
+ */
+void
+EnsureProcessPriorityPrefs(ProcessPriorityPrefs* prefs)
+{
+ if (prefs->initialized) {
+ return;
+ }
+
+ // Read the preferences for process priority levels
+ for (int i = PROCESS_PRIORITY_BACKGROUND; i < NUM_PROCESS_PRIORITY; i++) {
+ ProcessPriority priority = static_cast<ProcessPriority>(i);
+
+ // Read the nice values
+ const char* processPriorityStr = ProcessPriorityToString(priority);
+ nsPrintfCString niceStr("hal.processPriorityManager.gonk.%s.Nice",
+ processPriorityStr);
+ Preferences::AddIntVarCache(&prefs->priorities[i].nice, niceStr.get());
+
+ // Read the oom_adj scores
+ nsPrintfCString oomStr("hal.processPriorityManager.gonk.%s.OomScoreAdjust",
+ processPriorityStr);
+ Preferences::AddIntVarCache(&prefs->priorities[i].oomScoreAdj,
+ oomStr.get());
+ }
+
+ Preferences::AddIntVarCache(&prefs->lowPriorityNice,
+ "hal.processPriorityManager.gonk.LowCPUNice");
+
+ prefs->initialized = true;
+}
+
void
SetProcessPriority(int aPid,
ProcessPriority aPriority,
ProcessCPUPriority aCPUPriority,
uint32_t aBackgroundLRU)
{
HAL_LOG("SetProcessPriority(pid=%d, priority=%d, cpuPriority=%d, LRU=%u)",
aPid, aPriority, aCPUPriority, aBackgroundLRU);
@@ -1497,72 +1545,59 @@ SetProcessPriority(int aPid,
// OOM parameters according to our prefs.
//
// We could/should do this on startup instead of waiting for the first
// SetProcessPriorityCall. But in practice, the master process needs to set
// its priority early in the game, so we can reasonably rely on
// SetProcessPriority being called early in startup.
EnsureKernelLowMemKillerParamsSet();
- int32_t oomScoreAdj = 0;
- nsresult rv = Preferences::GetInt(nsPrintfCString(
- "hal.processPriorityManager.gonk.%s.OomScoreAdjust",
- ProcessPriorityToString(aPriority)).get(), &oomScoreAdj);
+ static ProcessPriorityPrefs prefs = { 0 };
+ EnsureProcessPriorityPrefs(&prefs);
+
+ int oomScoreAdj = prefs.priorities[aPriority].oomScoreAdj;
RoundOomScoreAdjUpWithBackroundLRU(oomScoreAdj, aBackgroundLRU);
- if (NS_SUCCEEDED(rv)) {
- int clampedOomScoreAdj = clamped<int>(oomScoreAdj, OOM_SCORE_ADJ_MIN,
- OOM_SCORE_ADJ_MAX);
- if(clampedOomScoreAdj != oomScoreAdj) {
- HAL_LOG("Clamping OOM adjustment for pid %d to %d", aPid,
- clampedOomScoreAdj);
- } else {
- HAL_LOG("Setting OOM adjustment for pid %d to %d", aPid,
- clampedOomScoreAdj);
- }
-
- // We try the newer interface first, and fall back to the older interface
- // on failure.
-
- if (!WriteToFile(nsPrintfCString("/proc/%d/oom_score_adj", aPid).get(),
- nsPrintfCString("%d", clampedOomScoreAdj).get()))
- {
- int oomAdj = OomAdjOfOomScoreAdj(clampedOomScoreAdj);
-
- WriteToFile(nsPrintfCString("/proc/%d/oom_adj", aPid).get(),
- nsPrintfCString("%d", oomAdj).get());
- }
+ int clampedOomScoreAdj = clamped<int>(oomScoreAdj, OOM_SCORE_ADJ_MIN,
+ OOM_SCORE_ADJ_MAX);
+ if (clampedOomScoreAdj != oomScoreAdj) {
+ HAL_LOG("Clamping OOM adjustment for pid %d to %d", aPid,
+ clampedOomScoreAdj);
} else {
- HAL_ERR("Unable to read oom_score_adj pref for priority %s; "
- "are the prefs messed up?", ProcessPriorityToString(aPriority));
- MOZ_ASSERT(false);
+ HAL_LOG("Setting OOM adjustment for pid %d to %d", aPid,
+ clampedOomScoreAdj);
}
- int32_t nice = 0;
+ // We try the newer interface first, and fall back to the older interface
+ // on failure.
+
+ if (!WriteToFile(nsPrintfCString("/proc/%d/oom_score_adj", aPid).get(),
+ nsPrintfCString("%d", clampedOomScoreAdj).get()))
+ {
+ int oomAdj = OomAdjOfOomScoreAdj(clampedOomScoreAdj);
+
+ WriteToFile(nsPrintfCString("/proc/%d/oom_adj", aPid).get(),
+ nsPrintfCString("%d", oomAdj).get());
+ }
+
+ int nice = 0;
if (aCPUPriority == PROCESS_CPU_PRIORITY_NORMAL) {
- rv = Preferences::GetInt(
- nsPrintfCString("hal.processPriorityManager.gonk.%s.Nice",
- ProcessPriorityToString(aPriority)).get(),
- &nice);
+ nice = prefs.priorities[aPriority].nice;
} else if (aCPUPriority == PROCESS_CPU_PRIORITY_LOW) {
- rv = Preferences::GetInt("hal.processPriorityManager.gonk.LowCPUNice",
- &nice);
+ nice = prefs.lowPriorityNice;
} else {
- HAL_ERR("Unable to read niceness pref for priority %s; "
- "are the prefs messed up?", ProcessPriorityToString(aPriority));
+ HAL_ERR("Unknown aCPUPriority value %d", aCPUPriority);
MOZ_ASSERT(false);
- rv = NS_ERROR_FAILURE;
+ return;
}
- if (NS_SUCCEEDED(rv)) {
- HAL_LOG("Setting nice for pid %d to %d", aPid, nice);
- SetNiceForPid(aPid, nice);
- }
+ HAL_LOG("Setting nice for pid %d to %d", aPid, nice);
+ SetNiceForPid(aPid, nice);
}
static bool
IsValidRealTimePriority(int aValue, int aSchedulePolicy)
{
return (aValue >= sched_get_priority_min(aSchedulePolicy)) &&
(aValue <= sched_get_priority_max(aSchedulePolicy));
}
@@ -1603,47 +1638,86 @@ SetRealTimeThreadPriority(pid_t aTid,
int rv = sched_setscheduler(aTid, policy, &schedParam);
if (rv) {
HAL_LOG("Failed to set thread %d to real time priority level %s; error %s",
aTid, ThreadPriorityToString(aThreadPriority), strerror(errno));
}
}
+/*
+ * Used to store the nice value adjustments and real time priorities for the
+ * various thread priority levels.
+ */
+struct ThreadPriorityPrefs {
+ bool initialized;
+ struct {
+ int nice;
+ int realTime;
+ } priorities[NUM_THREAD_PRIORITY];
+};
+
+/*
+ * Reads the preferences for the various process priority levels and sets up
+ * watchers so that if they're dynamically changed the change is reflected on
+ * the appropriate variables.
+ */
+void
+EnsureThreadPriorityPrefs(ThreadPriorityPrefs* prefs)
+{
+ if (prefs->initialized) {
+ return;
+ }
+
+ for (int i = THREAD_PRIORITY_COMPOSITOR; i < NUM_THREAD_PRIORITY; i++) {
+ ThreadPriority priority = static_cast<ThreadPriority>(i);
+
+ // Read the nice values
+ const char* threadPriorityStr = ThreadPriorityToString(priority);
+ nsPrintfCString niceStr("hal.gonk.%s.nice", threadPriorityStr);
+ Preferences::AddIntVarCache(&prefs->priorities[i].nice, niceStr.get());
+
+ // Read the real-time priorities
+ nsPrintfCString realTimeStr("hal.gonk.%s.rt_priority", threadPriorityStr);
+ Preferences::AddIntVarCache(&prefs->priorities[i].realTime,
+ realTimeStr.get());
+ }
+
+ prefs->initialized = true;
+}
+
static void
SetThreadPriority(pid_t aTid, hal::ThreadPriority aThreadPriority)
{
// See bug 999115, we can only read preferences on the main thread otherwise
// we create a race condition in HAL
MOZ_ASSERT(NS_IsMainThread(), "Can only set thread priorities on main thread");
MOZ_ASSERT(aThreadPriority >= 0);
- const char* threadPriorityStr;
+ static ThreadPriorityPrefs prefs = { 0 };
+ EnsureThreadPriorityPrefs(&prefs);
+
switch (aThreadPriority) {
case THREAD_PRIORITY_COMPOSITOR:
- threadPriorityStr = ThreadPriorityToString(aThreadPriority);
break;
default:
HAL_ERR("Unrecognized thread priority %d; Doing nothing",
aThreadPriority);
return;
}
- int realTimePriority = Preferences::GetInt(
- nsPrintfCString("hal.gonk.%s.rt_priority", threadPriorityStr).get());
+ int realTimePriority = prefs.priorities[aThreadPriority].realTime;
if (IsValidRealTimePriority(realTimePriority, SCHED_FIFO)) {
SetRealTimeThreadPriority(aTid, aThreadPriority, realTimePriority);
return;
}
- int niceValue = Preferences::GetInt(
- nsPrintfCString("hal.gonk.%s.nice", threadPriorityStr).get());
-
- SetThreadNiceValue(aTid, aThreadPriority, niceValue);
+ SetThreadNiceValue(aTid, aThreadPriority,
+ prefs.priorities[aThreadPriority].nice);
}
namespace {
/**
* This class sets the priority of threads given the kernel thread's id and a
* value taken from hal::ThreadPriority.
*