Bug 1057261 - Cache the preferences affecting process and thread priorities. r=dhylands
authorGabriele Svelto <gsvelto@mozilla.com>
Fri, 26 Sep 2014 16:37:31 +0200
changeset 232132 b00ca413f85b32ef54a71063ddbf7ba3496f7a34
parent 232131 de956d0e0c46c4c1eec29be075c7f4d55d2e7d7d
child 232133 8b8a64a58627d469bfcbfd9ef691effe68425bbe
push id4187
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:29:12 +0000
treeherdermozilla-beta@f23cc6a30c11 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdhylands
bugs1057261
milestone35.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1057261 - Cache the preferences affecting process and thread priorities. r=dhylands
hal/gonk/GonkHal.cpp
--- 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.
  *