lmkd: enable ro.lmk.kill_timeout_ms to be used with kill notifications

Allow lmkd to stop waiting for a kill notification if a kill takes longer
than ro.lmk.kill_timeout_ms.

Bug: 147315292
Test: lmkd_unit_test with ro.lmk.kill_timeout_ms set to 100
Signed-off-by: Suren Baghdasaryan <surenb@google.com>
Change-Id: Ia3eed3448fd6928a5e634c2737044722048b3578
diff --git a/lmkd.cpp b/lmkd.cpp
index 8691ad1..3b8a6fa 100644
--- a/lmkd.cpp
+++ b/lmkd.cpp
@@ -2252,21 +2252,23 @@
     int min_score_adj = 0;
     int swap_util = 0;
 
-    /* Skip while still killing a process */
-    if (is_kill_pending()) {
-        goto no_kill;
-    }
-    /*
-     * Process is dead, stop waiting. This has no effect if pidfds are supported and
-     * death notification already caused waiting to stop.
-     */
-    stop_wait_for_proc_kill(true);
-
     if (clock_gettime(CLOCK_MONOTONIC_COARSE, &curr_tm) != 0) {
         ALOGE("Failed to get current time");
         return;
     }
 
+    bool kill_pending = is_kill_pending();
+    if (kill_pending &&
+        (kill_timeout_ms == 0 || get_time_diff_ms(&last_kill_tm, &curr_tm) < kill_timeout_ms)) {
+        /* Skip while still killing a process */
+        goto no_kill;
+    }
+    /*
+     * Process is dead or kill timeout is over, stop waiting. This has no effect if pidfds are
+     * supported and death notification already caused waiting to stop.
+     */
+    stop_wait_for_proc_kill(!kill_pending);
+
     if (vmstat_parse(&vs) < 0) {
         ALOGE("Failed to parse vmstat!");
         return;
@@ -2933,6 +2935,15 @@
     return 0;
 }
 
+static bool polling_paused(struct polling_params *poll_params) {
+    return poll_params->paused_handler != NULL;
+}
+
+static void resume_polling(struct polling_params *poll_params, struct timespec curr_tm) {
+    poll_params->poll_start_tm = curr_tm;
+    poll_params->poll_handler = poll_params->paused_handler;
+}
+
 static void call_handler(struct event_handler_info* handler_info,
                          struct polling_params *poll_params, uint32_t events) {
     struct timespec curr_tm;
@@ -2959,8 +2970,7 @@
         poll_params->poll_handler = NULL;
         break;
     case POLLING_RESUME:
-        poll_params->poll_start_tm = curr_tm;
-        poll_params->poll_handler = poll_params->paused_handler;
+        resume_polling(poll_params, curr_tm);
         break;
     case POLLING_DO_NOT_CHANGE:
         if (get_time_diff_ms(&poll_params->poll_start_tm, &curr_tm) > PSI_WINDOW_SIZE_MS) {
@@ -3017,8 +3027,23 @@
                 call_handler(poll_params.poll_handler, &poll_params, 0);
             }
         } else {
-            /* Wait for events with no timeout */
-            nevents = epoll_wait(epollfd, events, maxevents, -1);
+            if (kill_timeout_ms && is_waiting_for_kill()) {
+                clock_gettime(CLOCK_MONOTONIC_COARSE, &curr_tm);
+                delay = kill_timeout_ms - get_time_diff_ms(&last_kill_tm, &curr_tm);
+                /* Wait for pidfds notification or kill timeout to expire */
+                nevents = (delay > 0) ? epoll_wait(epollfd, events, maxevents, delay) : 0;
+                if (nevents == 0) {
+                    /* Kill notification timed out */
+                    stop_wait_for_proc_kill(false);
+                    if (polling_paused(&poll_params)) {
+                        clock_gettime(CLOCK_MONOTONIC_COARSE, &curr_tm);
+                        resume_polling(&poll_params, curr_tm);
+                    }
+                }
+            } else {
+                /* Wait for events with no timeout */
+                nevents = epoll_wait(epollfd, events, maxevents, -1);
+            }
         }
 
         if (nevents == -1) {