lmkd: add logic to kill the heaviest of the eligible processes

(cherry pick from commit 662492ab1d21f138483a8f3943483924e8779d29)

Killing the most memory-demanding process from the set of eligible
processes yields better results on high-performance devices than
killing the first one we could find. This is in line with how in-kernel
lowmemorykiller driver chooses its victims.

Bug: 63631020
Test: alloc-stress

Change-Id: Ie1ef7f33f3e79698a9b4120c14490386d6129f9b
Merged-In: Ie1ef7f33f3e79698a9b4120c14490386d6129f9b
Signed-off-by: Suren Baghdasaryan <surenb@google.com>
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index d438203..17ebb14 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -91,6 +91,7 @@
 static int64_t upgrade_pressure;
 static int64_t downgrade_pressure;
 static bool is_go_device;
+static bool kill_heaviest_task;
 
 /* control socket listen and data */
 static int ctrl_lfd;
@@ -593,6 +594,29 @@
     return (struct proc *)adjslot_tail(&procadjslot_list[ADJTOSLOT(oomadj)]);
 }
 
+static struct proc *proc_get_heaviest(int oomadj) {
+    struct adjslot_list *head = &procadjslot_list[ADJTOSLOT(oomadj)];
+    struct adjslot_list *curr = head->next;
+    struct proc *maxprocp = NULL;
+    int maxsize = 0;
+    while (curr != head) {
+        int pid = ((struct proc *)curr)->pid;
+        int tasksize = proc_get_size(pid);
+        if (tasksize <= 0) {
+            struct adjslot_list *next = curr->next;
+            pid_remove(pid);
+            curr = next;
+        } else {
+            if (tasksize > maxsize) {
+                maxsize = tasksize;
+                maxprocp = (struct proc *)curr;
+            }
+            curr = curr->next;
+        }
+    }
+    return maxprocp;
+}
+
 /* Kill one process specified by procp.  Returns the size of the process killed */
 static int kill_one_process(struct proc* procp, int min_score_adj,
                             enum vmpressure_level level) {
@@ -643,7 +667,10 @@
         struct proc *procp;
 
 retry:
-        procp = proc_adj_lru(i);
+        if (kill_heaviest_task)
+            procp = proc_get_heaviest(i);
+        else
+            procp = proc_adj_lru(i);
 
         if (procp) {
             killed_size = kill_one_process(procp, min_score_adj, level);
@@ -929,6 +956,8 @@
         (int64_t)property_get_int32("ro.lmk.upgrade_pressure", 100);
     downgrade_pressure =
         (int64_t)property_get_int32("ro.lmk.downgrade_pressure", 100);
+    kill_heaviest_task =
+        property_get_bool("ro.lmk.kill_heaviest_task", true);
     is_go_device = property_get_bool("ro.config.low_ram", false);
 
     // MCL_ONFAULT pins pages as they fault instead of loading