lmkd: Enable new kill strategy, add and adjust required system properties

Enable new kill strategy when PSI mode is used in combination with
ro.lmk.use_minfree_levels=false. Adjust ro.lmk.swap_free_low_percentage,
introduce ro.lmk.psi_partial_stall_ms and ro.lmk.psi_complete_stall_ms
system properties to support two levels of PSI events measuring partial
and complete stalls. Add ro.lmk.use_new_strategy system property to switch
to the old strategy if necessary.

Bug: 132642304
Test: lmkd_unit_test, ACT memory pressure tests
Change-Id: I6f1b65e19dbe9b58c862e5e4255270c82f0afb9a
Signed-off-by: Suren Baghdasaryan <surenb@google.com>
diff --git a/lmkd/README.md b/lmkd/README.md
index a735955..8a73692 100644
--- a/lmkd/README.md
+++ b/lmkd/README.md
@@ -80,3 +80,11 @@
                              the threshold when system does not recover even
                              after a kill. Default for low-RAM devices = 50,
                              for high-end devices = 10
+
+  ro.lmk.psi_partial_stall_ms: partial PSI stall threshold in milliseconds for
+                             triggering low memory notification. Default for
+                             low-RAM devices = 200, for high-end devices = 70
+
+  ro.lmk.psi_complete_stall_ms: complete PSI stall threshold in milliseconds for
+                             triggering critical memory notification. Default =
+                             700
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index 42e3db3..1db3d5a 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -133,6 +133,11 @@
 /* ro.lmk.thrashing_limit_decay property defaults */
 #define DEF_THRASHING_DECAY_LOWRAM 50
 #define DEF_THRASHING_DECAY 10
+/* ro.lmk.psi_partial_stall_ms property defaults */
+#define DEF_PARTIAL_STALL_LOWRAM 200
+#define DEF_PARTIAL_STALL 70
+/* ro.lmk.psi_complete_stall_ms property defaults */
+#define DEF_COMPLETE_STALL 700
 
 /* default to old in-kernel interface if no memory pressure events */
 static bool use_inkernel_interface = true;
@@ -174,6 +179,8 @@
 static bool use_minfree_levels;
 static bool per_app_memcg;
 static int swap_free_low_percentage;
+static int psi_partial_stall_ms;
+static int psi_complete_stall_ms;
 static int thrashing_limit_pct;
 static int thrashing_limit_decay_pct;
 static bool use_psi_monitors = false;
@@ -2406,8 +2413,15 @@
     }
 }
 
-static bool init_mp_psi(enum vmpressure_level level) {
-    int fd = init_psi_monitor(psi_thresholds[level].stall_type,
+static bool init_mp_psi(enum vmpressure_level level, bool use_new_strategy) {
+    int fd;
+
+    /* Do not register a handler if threshold_ms is not set */
+    if (!psi_thresholds[level].threshold_ms) {
+        return true;
+    }
+
+    fd = init_psi_monitor(psi_thresholds[level].stall_type,
         psi_thresholds[level].threshold_ms * US_PER_MS,
         PSI_WINDOW_SIZE_MS * US_PER_MS);
 
@@ -2415,7 +2429,7 @@
         return false;
     }
 
-    vmpressure_hinfo[level].handler = mp_event_common;
+    vmpressure_hinfo[level].handler = use_new_strategy ? mp_event_psi : mp_event_common;
     vmpressure_hinfo[level].data = level;
     if (register_psi_monitor(epollfd, fd, &vmpressure_hinfo[level]) < 0) {
         destroy_psi_monitor(fd);
@@ -2439,14 +2453,29 @@
 }
 
 static bool init_psi_monitors() {
-    if (!init_mp_psi(VMPRESS_LEVEL_LOW)) {
+    /*
+     * When PSI is used on low-ram devices or on high-end devices without memfree levels
+     * use new kill strategy based on zone watermarks, free swap and thrashing stats
+     */
+    bool use_new_strategy =
+        property_get_bool("ro.lmk.use_new_strategy", low_ram_device || !use_minfree_levels);
+
+    /* In default PSI mode override stall amounts using system properties */
+    if (use_new_strategy) {
+        /* Do not use low pressure level */
+        psi_thresholds[VMPRESS_LEVEL_LOW].threshold_ms = 0;
+        psi_thresholds[VMPRESS_LEVEL_MEDIUM].threshold_ms = psi_partial_stall_ms;
+        psi_thresholds[VMPRESS_LEVEL_CRITICAL].threshold_ms = psi_complete_stall_ms;
+    }
+
+    if (!init_mp_psi(VMPRESS_LEVEL_LOW, use_new_strategy)) {
         return false;
     }
-    if (!init_mp_psi(VMPRESS_LEVEL_MEDIUM)) {
+    if (!init_mp_psi(VMPRESS_LEVEL_MEDIUM, use_new_strategy)) {
         destroy_mp_psi(VMPRESS_LEVEL_LOW);
         return false;
     }
-    if (!init_mp_psi(VMPRESS_LEVEL_CRITICAL)) {
+    if (!init_mp_psi(VMPRESS_LEVEL_CRITICAL, use_new_strategy)) {
         destroy_mp_psi(VMPRESS_LEVEL_MEDIUM);
         destroy_mp_psi(VMPRESS_LEVEL_LOW);
         return false;
@@ -2831,6 +2860,10 @@
         property_get_bool("ro.config.per_app_memcg", low_ram_device);
     swap_free_low_percentage = clamp(0, 100, property_get_int32("ro.lmk.swap_free_low_percentage",
         low_ram_device ? DEF_LOW_SWAP_LOWRAM : DEF_LOW_SWAP));
+    psi_partial_stall_ms = property_get_int32("ro.lmk.psi_partial_stall_ms",
+        low_ram_device ? DEF_PARTIAL_STALL_LOWRAM : DEF_PARTIAL_STALL);
+    psi_complete_stall_ms = property_get_int32("ro.lmk.psi_complete_stall_ms",
+        DEF_COMPLETE_STALL);
     thrashing_limit_pct = max(0, property_get_int32("ro.lmk.thrashing_limit",
         low_ram_device ? DEF_THRASHING_LOWRAM : DEF_THRASHING));
     thrashing_limit_decay_pct = clamp(0, 100, property_get_int32("ro.lmk.thrashing_limit_decay",