diff --git a/include/lmkd.h b/include/lmkd.h index d710d50..1a65270 100644 --- a/include/lmkd.h +++ b/include/lmkd.h @@ -36,6 +36,7 @@ enum lmk_cmd { LMK_PROCKILL, /* Unsolicited msg to subscribed clients on proc kills */ LMK_UPDATE_PROPS, /* Reinit properties */ LMK_STAT_KILL_OCCURRED, /* Unsolicited msg to subscribed clients on proc kills for statsd log */ + LMK_START_MONITORING, /* Start psi monitoring if it was skipped earlier */ }; /* @@ -256,6 +257,15 @@ static inline size_t lmkd_pack_set_update_props(LMKD_CTRL_PACKET packet) { return sizeof(int); } +/* + * Prepare LMK_START_MONITORING packet and return packet size in bytes. + * Warning: no checks performed, caller should ensure valid parameters. + */ +static inline size_t lmkd_pack_start_monitoring(LMKD_CTRL_PACKET packet) { + packet[0] = htonl(LMK_START_MONITORING); + return sizeof(int); +} + /* * Prepare LMK_UPDATE_PROPS reply packet and return packet size in bytes. * Warning: no checks performed, caller should ensure valid parameters. diff --git a/lmkd.cpp b/lmkd.cpp index 02fb553..c604826 100644 --- a/lmkd.cpp +++ b/lmkd.cpp @@ -194,6 +194,7 @@ static int mpevfd[VMPRESS_LEVEL_COUNT] = { -1, -1, -1 }; static bool pidfd_supported; static int last_kill_pid_or_fd = -1; static struct timespec last_kill_tm; +static bool monitors_initialized; /* lmkd configurable parameters */ static bool debug_process_killing; @@ -216,6 +217,7 @@ static int64_t filecache_min_kb; static int64_t stall_limit_critical; static bool use_psi_monitors = false; static int kpoll_fd; +static bool delay_monitors_until_boot; static struct psi_threshold psi_thresholds[VMPRESS_LEVEL_COUNT] = { { PSI_SOME, 70 }, /* 70ms out of 1sec for partial stall */ { PSI_SOME, 100 }, /* 100ms out of 1sec for partial stall */ @@ -1510,7 +1512,7 @@ static void ctrl_command_handler(int dsock_idx) { goto wronglen; result = -1; if (update_props()) { - if (!use_inkernel_interface) { + if (!use_inkernel_interface && monitors_initialized) { /* Reinitialize monitors to apply new settings */ destroy_monitors(); if (init_monitors()) { @@ -1533,6 +1535,24 @@ static void ctrl_command_handler(int dsock_idx) { exit(1); } break; + case LMK_START_MONITORING: + if (nargs != 0) + goto wronglen; + // Registration is needed only if it was skipped earlier. + if (monitors_initialized) + return; + if (!property_get_bool("sys.boot_completed", false)) { + ALOGE("LMK_START_MONITORING cannot be handled before boot completed"); + return; + } + + if (!init_monitors()) { + /* Failure to start psi monitoring, crash to be restarted */ + ALOGE("Failure to initialize monitoring. Exiting..."); + exit(1); + } + ALOGI("Initialized monitors after boot completed."); + break; default: ALOGE("Received unknown command code %d", cmd); return; @@ -3343,6 +3363,7 @@ static bool init_monitors() { } else { ALOGI("Using vmpressure for memory pressure detection"); } + monitors_initialized = true; return true; } @@ -3482,8 +3503,13 @@ static int init(void) { } } } else { - if (!init_monitors()) { - return -1; + // Do not register monitors until boot completed for devices configured + // for delaying monitors. This is done to save CPU cycles for low + // resource devices during boot up. + if (!delay_monitors_until_boot || property_get_bool("sys.boot_completed", false)) { + if (!init_monitors()) { + return -1; + } } /* let the others know it does support reporting kills */ property_set("sys.lmk.reportkills", "1"); @@ -3749,6 +3775,7 @@ static bool update_props() { swap_util_max = clamp(0, 100, GET_LMK_PROPERTY(int32, "swap_util_max", 100)); filecache_min_kb = GET_LMK_PROPERTY(int64, "filecache_min_kb", 0); stall_limit_critical = GET_LMK_PROPERTY(int64, "stall_limit_critical", 100); + delay_monitors_until_boot = GET_LMK_PROPERTY(bool, "delay_monitors_until_boot", false); reaper.enable_debug(debug_process_killing);