From c4081918a7b847e250817d6b248ef3762a65123c Mon Sep 17 00:00:00 2001 From: Suren Baghdasaryan Date: Tue, 28 Apr 2020 15:52:29 -0700 Subject: [PATCH 1/9] lmkd: Add property re-initialization support Add --reinit command-line option to allow updating lmkd properties. For example to enable debug logging in the running lmkd process user should issue: setprop ro.lmk.debug true lmkd --reinit Bug: 155149944 Test: lmkd_unit_test after resetting lmkd properties Signed-off-by: Suren Baghdasaryan Merged-In: Ic60331f3368f5a7fdfe09ad7d47c7ccf0a497685 Change-Id: Ic60331f3368f5a7fdfe09ad7d47c7ccf0a497685 --- Android.bp | 1 + include/liblmkd_utils.h | 14 ++++ include/lmkd.h | 34 +++++++++ liblmkd_utils.cpp | 24 ++++++ lmkd.cpp | 158 ++++++++++++++++++++++++++++++++++------ lmkd.rc | 3 + 6 files changed, 213 insertions(+), 21 deletions(-) diff --git a/Android.bp b/Android.bp index ef53b6b..43d9e76 100644 --- a/Android.bp +++ b/Android.bp @@ -24,6 +24,7 @@ cc_binary { static_libs: [ "libstatslogc", "libstatslog_lmkd", + "liblmkd_utils", ], local_include_dirs: ["include"], cflags: ["-Werror", "-DLMKD_TRACE_KILLS"], diff --git a/include/liblmkd_utils.h b/include/liblmkd_utils.h index 92e4d41..a84db84 100644 --- a/include/liblmkd_utils.h +++ b/include/liblmkd_utils.h @@ -47,6 +47,20 @@ int lmkd_register_proc(int sock, struct lmk_procprio *params); */ int lmkd_unregister_proc(int sock, struct lmk_procremove *params); +enum update_props_result { + UPDATE_PROPS_SUCCESS, + UPDATE_PROPS_FAIL, + UPDATE_PROPS_SEND_ERR, + UPDATE_PROPS_RECV_ERR, + UPDATE_PROPS_FORMAT_ERR, +}; + +/* + * Updates lmkd properties. + * In the case of ERR_SEND or ERR_RECV errno is set appropriately. + */ +enum update_props_result lmkd_update_props(int sock); + /* * Creates memcg directory for given process. * On success returns 0. diff --git a/include/lmkd.h b/include/lmkd.h index c22cb78..ad5dc75 100644 --- a/include/lmkd.h +++ b/include/lmkd.h @@ -34,6 +34,7 @@ enum lmk_cmd { LMK_GETKILLCNT, /* Get number of kills */ LMK_SUBSCRIBE, /* Subscribe for asynchronous events */ LMK_PROCKILL, /* Unsolicited msg to subscribed clients on proc kills */ + LMK_UPDATE_PROPS, /* Reinit properties */ }; /* @@ -244,6 +245,39 @@ static inline size_t lmkd_pack_set_prockills(LMKD_CTRL_PACKET packet, pid_t pid, return 3 * sizeof(int); } +/* + * Prepare LMK_UPDATE_PROPS packet and return packet size in bytes. + * Warning: no checks performed, caller should ensure valid parameters. + */ +static inline size_t lmkd_pack_set_update_props(LMKD_CTRL_PACKET packet) { + packet[0] = htonl(LMK_UPDATE_PROPS); + return sizeof(int); +} + +/* + * Prepare LMK_UPDATE_PROPS reply packet and return packet size in bytes. + * Warning: no checks performed, caller should ensure valid parameters. + */ +static inline size_t lmkd_pack_set_update_props_repl(LMKD_CTRL_PACKET packet, int result) { + packet[0] = htonl(LMK_UPDATE_PROPS); + packet[1] = htonl(result); + return 2 * sizeof(int); +} + +/* LMK_PROCPRIO reply payload */ +struct lmk_update_props_reply { + int result; +}; + +/* + * For LMK_UPDATE_PROPS reply payload. + * Warning: no checks performed, caller should ensure valid parameters. + */ +static inline void lmkd_pack_get_update_props_repl(LMKD_CTRL_PACKET packet, + struct lmk_update_props_reply* params) { + params->result = ntohl(packet[1]); +} + __END_DECLS #endif /* _LMKD_H_ */ diff --git a/liblmkd_utils.cpp b/liblmkd_utils.cpp index 280c149..45e867e 100644 --- a/liblmkd_utils.cpp +++ b/liblmkd_utils.cpp @@ -53,6 +53,30 @@ int lmkd_unregister_proc(int sock, struct lmk_procremove *params) { return (ret < 0) ? -1 : 0; } +enum update_props_result lmkd_update_props(int sock) { + LMKD_CTRL_PACKET packet; + size_t size; + + size = lmkd_pack_set_update_props(packet); + if (TEMP_FAILURE_RETRY(write(sock, packet, size)) < 0) { + return UPDATE_PROPS_SEND_ERR; + } + + size = TEMP_FAILURE_RETRY(read(sock, packet, CTRL_PACKET_MAX_SIZE)); + if (size < 0) { + return UPDATE_PROPS_RECV_ERR; + } + + if (size != 2 * sizeof(int) || lmkd_pack_get_cmd(packet) != LMK_UPDATE_PROPS) { + return UPDATE_PROPS_FORMAT_ERR; + } + + struct lmk_update_props_reply params; + lmkd_pack_get_update_props_repl(packet, ¶ms); + + return params.result == 0 ? UPDATE_PROPS_SUCCESS : UPDATE_PROPS_FAIL; +} + int create_memcg(uid_t uid, pid_t pid) { char buf[256]; int tasks_file; diff --git a/lmkd.cpp b/lmkd.cpp index 23bb5c3..351b41a 100644 --- a/lmkd.cpp +++ b/lmkd.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -142,6 +143,8 @@ /* ro.lmk.psi_complete_stall_ms property defaults */ #define DEF_COMPLETE_STALL 700 +#define LMKD_REINIT_PROP "lmkd.reinit" + static inline int sys_pidfd_open(pid_t pid, unsigned int flags) { return syscall(__NR_pidfd_open, pid, flags); } @@ -526,6 +529,10 @@ static uint32_t killcnt_total = 0; /* PAGE_SIZE / 1024 */ static long page_k; +static void update_props(); +static bool init_monitors(); +static void destroy_monitors(); + static int clamp(int low, int high, int value) { return max(min(value, high), low); } @@ -1364,6 +1371,7 @@ static void ctrl_command_handler(int dsock_idx) { int nargs; int targets; int kill_cnt; + int result; len = ctrl_data_read(dsock_idx, (char *)packet, CTRL_PACKET_MAX_SIZE, &cred); if (len <= 0) @@ -1419,6 +1427,29 @@ static void ctrl_command_handler(int dsock_idx) { /* This command code is NOT expected at all */ ALOGE("Received unexpected command code %d", cmd); break; + case LMK_UPDATE_PROPS: + if (nargs != 0) + goto wronglen; + update_props(); + if (!use_inkernel_interface) { + /* Reinitialize monitors to apply new settings */ + destroy_monitors(); + result = init_monitors() ? 0 : -1; + } else { + result = 0; + } + len = lmkd_pack_set_update_props_repl(packet, result); + if (ctrl_data_write(dsock_idx, (char *)packet, len) != len) { + ALOGE("Failed to report operation results"); + } + if (!result) { + ALOGI("Properties reinitilized"); + } else { + /* New settings can't be supported, crash to be restarted */ + ALOGE("New configuration is not supported. Exiting..."); + exit(1); + } + break; default: ALOGE("Received unknown command code %d", cmd); return; @@ -1923,9 +1954,9 @@ static void stop_wait_for_proc_kill(bool finished) { if (pidfd_supported) { /* unregister fd */ - if (epoll_ctl(epollfd, EPOLL_CTL_DEL, last_kill_pid_or_fd, &epev) != 0) { + if (epoll_ctl(epollfd, EPOLL_CTL_DEL, last_kill_pid_or_fd, &epev)) { + // Log an error and keep going ALOGE("epoll_ctl for last killed process failed; errno=%d", errno); - return; } maxevents--; close(last_kill_pid_or_fd); @@ -2688,10 +2719,15 @@ static bool init_mp_psi(enum vmpressure_level level, bool use_new_strategy) { static void destroy_mp_psi(enum vmpressure_level level) { int fd = mpevfd[level]; + if (fd < 0) { + return; + } + if (unregister_psi_monitor(epollfd, fd) < 0) { ALOGE("Failed to unregister psi monitor for %s memory pressure; errno=%d", level_name[level], errno); } + maxevents--; destroy_psi_monitor(fd); mpevfd[level] = -1; } @@ -2794,11 +2830,60 @@ err_open_mpfd: return false; } +static void destroy_mp_common(enum vmpressure_level level) { + struct epoll_event epev; + int fd = mpevfd[level]; + + if (fd < 0) { + return; + } + + if (epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, &epev)) { + // Log an error and keep going + ALOGE("epoll_ctl for level %s failed; errno=%d", level_name[level], errno); + } + maxevents--; + close(fd); + mpevfd[level] = -1; +} + static void kernel_event_handler(int data __unused, uint32_t events __unused, struct polling_params *poll_params __unused) { poll_kernel(kpoll_fd); } +static bool init_monitors() { + /* Try to use psi monitor first if kernel has it */ + use_psi_monitors = property_get_bool("ro.lmk.use_psi", true) && + init_psi_monitors(); + /* Fall back to vmpressure */ + if (!use_psi_monitors && + (!init_mp_common(VMPRESS_LEVEL_LOW) || + !init_mp_common(VMPRESS_LEVEL_MEDIUM) || + !init_mp_common(VMPRESS_LEVEL_CRITICAL))) { + ALOGE("Kernel does not support memory pressure events or in-kernel low memory killer"); + return false; + } + if (use_psi_monitors) { + ALOGI("Using psi monitors for memory pressure detection"); + } else { + ALOGI("Using vmpressure for memory pressure detection"); + } + return true; +} + +static void destroy_monitors() { + if (use_psi_monitors) { + destroy_mp_psi(VMPRESS_LEVEL_CRITICAL); + destroy_mp_psi(VMPRESS_LEVEL_MEDIUM); + destroy_mp_psi(VMPRESS_LEVEL_LOW); + } else { + destroy_mp_common(VMPRESS_LEVEL_CRITICAL); + destroy_mp_common(VMPRESS_LEVEL_MEDIUM); + destroy_mp_common(VMPRESS_LEVEL_LOW); + } +} + static int init(void) { static struct event_handler_info kernel_poll_hinfo = { 0, kernel_event_handler }; struct reread_data file_data = { @@ -2866,22 +2951,9 @@ static int init(void) { } } } else { - /* Try to use psi monitor first if kernel has it */ - use_psi_monitors = property_get_bool("ro.lmk.use_psi", true) && - init_psi_monitors(); - /* Fall back to vmpressure */ - if (!use_psi_monitors && - (!init_mp_common(VMPRESS_LEVEL_LOW) || - !init_mp_common(VMPRESS_LEVEL_MEDIUM) || - !init_mp_common(VMPRESS_LEVEL_CRITICAL))) { - ALOGE("Kernel does not support memory pressure events or in-kernel low memory killer"); + if (!init_monitors()) { return -1; } - if (use_psi_monitors) { - ALOGI("Using psi monitors for memory pressure detection"); - } else { - ALOGI("Using vmpressure for memory pressure detection"); - } /* let the others know it does support reporting kills */ property_set("sys.lmk.reportkills", "1"); } @@ -2965,7 +3037,7 @@ static void mainloop(void) { poll_params.update = POLLING_DO_NOT_CHANGE; while (1) { - struct epoll_event events[maxevents]; + struct epoll_event events[MAX_EPOLL_EVENTS]; int nevents; int i; @@ -3042,11 +3114,41 @@ static void mainloop(void) { } } -int main(int argc __unused, char **argv __unused) { - struct sched_param param = { - .sched_priority = 1, - }; +int issue_reinit() { + LMKD_CTRL_PACKET packet; + size_t size; + int sock; + sock = lmkd_connect(); + if (sock < 0) { + ALOGE("failed to connect to lmkd: %s", strerror(errno)); + return -1; + } + + enum update_props_result res = lmkd_update_props(sock); + switch (res) { + case UPDATE_PROPS_SUCCESS: + ALOGI("lmkd updated properties successfully"); + break; + case UPDATE_PROPS_SEND_ERR: + ALOGE("failed to send lmkd request: %s", strerror(errno)); + break; + case UPDATE_PROPS_RECV_ERR: + ALOGE("failed to receive lmkd reply: %s", strerror(errno)); + break; + case UPDATE_PROPS_FORMAT_ERR: + ALOGE("lmkd reply is invalid"); + break; + case UPDATE_PROPS_FAIL: + ALOGE("lmkd failed to update its properties"); + break; + } + + close(sock); + return res == UPDATE_PROPS_SUCCESS ? 0 : -1; +} + +static void update_props() { /* By default disable low level vmpressure events */ level_oomadj[VMPRESS_LEVEL_LOW] = property_get_int32("ro.lmk.low", OOM_SCORE_ADJ_MAX + 1); @@ -3082,6 +3184,17 @@ int main(int argc __unused, char **argv __unused) { low_ram_device ? DEF_THRASHING_LOWRAM : DEF_THRASHING)); thrashing_limit_decay_pct = clamp(0, 100, property_get_int32("ro.lmk.thrashing_limit_decay", low_ram_device ? DEF_THRASHING_DECAY_LOWRAM : DEF_THRASHING_DECAY)); +} + +int main(int argc, char **argv) { + if ((argc > 1) && argv[1] && !strcmp(argv[1], "--reinit")) { + if (property_set(LMKD_REINIT_PROP, "0")) { + ALOGE("Failed to reset " LMKD_REINIT_PROP " property"); + } + return issue_reinit(); + } + + update_props(); ctx = create_android_logger(KILLINFO_LOG_TAG); @@ -3104,6 +3217,9 @@ int main(int argc __unused, char **argv __unused) { } /* CAP_NICE required */ + struct sched_param param = { + .sched_priority = 1, + }; if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { ALOGW("set SCHED_FIFO failed %s", strerror(errno)); } diff --git a/lmkd.rc b/lmkd.rc index 982a188..17c6560 100644 --- a/lmkd.rc +++ b/lmkd.rc @@ -6,3 +6,6 @@ service lmkd /system/bin/lmkd critical socket lmkd seqpacket+passcred 0660 system system writepid /dev/cpuset/system-background/tasks + +on property:lmkd.reinit=1 + exec_background /system/bin/lmkd --reinit From 3f84a211e57c8e4af5cdb2d862404a288241e8d9 Mon Sep 17 00:00:00 2001 From: Suren Baghdasaryan Date: Fri, 24 Apr 2020 16:54:55 -0700 Subject: [PATCH 2/9] lmkd: polling code cleanup - Remove unused POLLING_STOP state - Simplify POLLING_DO_NOT_CHANGE state handling - Correct last_poll_tm assignment logic Bug: 147315292 Test: lmkd_unit_test Signed-off-by: Suren Baghdasaryan Merged-In: If0674eda954a25f0f6c9188501ff77db8ba0813b Change-Id: If0674eda954a25f0f6c9188501ff77db8ba0813b --- lmkd.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/lmkd.cpp b/lmkd.cpp index 351b41a..256cce6 100644 --- a/lmkd.cpp +++ b/lmkd.cpp @@ -216,7 +216,6 @@ static android_log_context ctx; enum polling_update { POLLING_DO_NOT_CHANGE, POLLING_START, - POLLING_STOP, POLLING_PAUSE, POLLING_RESUME, }; @@ -2990,9 +2989,12 @@ static void call_handler(struct event_handler_info* handler_info, struct polling_params *poll_params, uint32_t events) { struct timespec curr_tm; + poll_params->update = POLLING_DO_NOT_CHANGE; handler_info->handler(handler_info->data, events, poll_params); clock_gettime(CLOCK_MONOTONIC_COARSE, &curr_tm); - poll_params->last_poll_tm = curr_tm; + if (poll_params->poll_handler == handler_info) { + poll_params->last_poll_tm = curr_tm; + } switch (poll_params->update) { case POLLING_START: @@ -3004,9 +3006,6 @@ static void call_handler(struct event_handler_info* handler_info, poll_params->poll_start_tm = curr_tm; poll_params->poll_handler = handler_info; break; - case POLLING_STOP: - poll_params->poll_handler = NULL; - break; case POLLING_PAUSE: poll_params->paused_handler = handler_info; poll_params->poll_handler = NULL; @@ -3019,11 +3018,10 @@ static void call_handler(struct event_handler_info* handler_info, if (get_time_diff_ms(&poll_params->poll_start_tm, &curr_tm) > PSI_WINDOW_SIZE_MS) { /* Polled for the duration of PSI window, time to stop */ poll_params->poll_handler = NULL; + poll_params->paused_handler = NULL; } - /* WARNING: skipping the rest of the function */ - return; + break; } - poll_params->update = POLLING_DO_NOT_CHANGE; } static void mainloop(void) { @@ -3034,7 +3032,7 @@ static void mainloop(void) { long delay = -1; poll_params.poll_handler = NULL; - poll_params.update = POLLING_DO_NOT_CHANGE; + poll_params.paused_handler = NULL; while (1) { struct epoll_event events[MAX_EPOLL_EVENTS]; From c7e51b7b2a327a90212d42e0eccf502035717a3d Mon Sep 17 00:00:00 2001 From: Suren Baghdasaryan Date: Tue, 28 Apr 2020 16:02:13 -0700 Subject: [PATCH 3/9] 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 Merged-In: Ia3eed3448fd6928a5e634c2737044722048b3578 Change-Id: Ia3eed3448fd6928a5e634c2737044722048b3578 --- lmkd.cpp | 53 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/lmkd.cpp b/lmkd.cpp index 256cce6..cd3d928 100644 --- a/lmkd.cpp +++ b/lmkd.cpp @@ -2273,21 +2273,23 @@ static void mp_event_psi(int data, uint32_t events, struct polling_params *poll_ bool cut_thrashing_limit = false; int min_score_adj = 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; @@ -2985,6 +2987,15 @@ static int init(void) { 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; @@ -3011,8 +3022,7 @@ static void call_handler(struct event_handler_info* handler_info, 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) { @@ -3069,8 +3079,23 @@ static void mainloop(void) { 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) { From dd7ec447abaa93597c024c96c97c4d3fd89ab1b9 Mon Sep 17 00:00:00 2001 From: Suren Baghdasaryan Date: Mon, 11 May 2020 16:31:57 -0700 Subject: [PATCH 4/9] lmkd: Remove unused variables and fix type mismatches Fix compilation warnings by removing unused variables and add typecasting whenever mixed type comparisons are performed. Bug: 147315292 Signed-off-by: Suren Baghdasaryan Merged-In: I7f0839d803a6bf6532f077208ce54aba761dc9fe Change-Id: I7f0839d803a6bf6532f077208ce54aba761dc9fe --- liblmkd_utils.cpp | 2 +- lmkd.cpp | 11 ++++------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/liblmkd_utils.cpp b/liblmkd_utils.cpp index 45e867e..55d7f62 100644 --- a/liblmkd_utils.cpp +++ b/liblmkd_utils.cpp @@ -55,7 +55,7 @@ int lmkd_unregister_proc(int sock, struct lmk_procremove *params) { enum update_props_result lmkd_update_props(int sock) { LMKD_CTRL_PACKET packet; - size_t size; + int size; size = lmkd_pack_set_update_props(packet); if (TEMP_FAILURE_RETRY(write(sock, packet, size)) < 0) { diff --git a/lmkd.cpp b/lmkd.cpp index cd3d928..ede1958 100644 --- a/lmkd.cpp +++ b/lmkd.cpp @@ -2124,7 +2124,6 @@ static int find_and_kill_process(int min_score_adj, int kill_reason, const char } static int64_t get_memory_usage(struct reread_data *file_data) { - int ret; int64_t mem_usage; char *buf; @@ -2279,8 +2278,8 @@ static void mp_event_psi(int data, uint32_t events, struct polling_params *poll_ } 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)) { + if (kill_pending && (kill_timeout_ms == 0 || + get_time_diff_ms(&last_kill_tm, &curr_tm) < static_cast(kill_timeout_ms))) { /* Skip while still killing a process */ goto no_kill; } @@ -2457,7 +2456,6 @@ no_kill: } static void mp_event_common(int data, uint32_t events, struct polling_params *poll_params) { - int ret; unsigned long long evcount; int64_t mem_usage, memsw_usage; int64_t mem_pressure; @@ -2512,7 +2510,8 @@ static void mp_event_common(int data, uint32_t events, struct polling_params *po return; } - if (kill_timeout_ms && get_time_diff_ms(&last_kill_tm, &curr_tm) < kill_timeout_ms) { + if (kill_timeout_ms && + get_time_diff_ms(&last_kill_tm, &curr_tm) < static_cast(kill_timeout_ms)) { /* * If we're within the no-kill timeout, see if there's pending reclaim work * from the last killed process. If so, skip killing for now. @@ -3138,8 +3137,6 @@ static void mainloop(void) { } int issue_reinit() { - LMKD_CTRL_PACKET packet; - size_t size; int sock; sock = lmkd_connect(); From 5096d16091990ed6fd82e4937fb4c00997c7db1b Mon Sep 17 00:00:00 2001 From: Suren Baghdasaryan Date: Mon, 11 May 2020 16:34:52 -0700 Subject: [PATCH 5/9] lmkd: Enable stricter compiler checks Enable -Wall and -Wextra compiler flags to catch compilation warnings. Bug: 147315292 Signed-off-by: Suren Baghdasaryan Merged-In: Ia802dbd7abb167d66b76390e269e4a4418ca5def Change-Id: Ia802dbd7abb167d66b76390e269e4a4418ca5def --- Android.bp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Android.bp b/Android.bp index 43d9e76..f177b0d 100644 --- a/Android.bp +++ b/Android.bp @@ -27,7 +27,12 @@ cc_binary { "liblmkd_utils", ], local_include_dirs: ["include"], - cflags: ["-Werror", "-DLMKD_TRACE_KILLS"], + cflags: [ + "-Wall", + "-Werror", + "-Wextra", + "-DLMKD_TRACE_KILLS" + ], init_rc: ["lmkd.rc"], defaults: ["stats_defaults"], logtags: ["event.logtags"], @@ -39,6 +44,7 @@ cc_library_static { cflags: [ "-Wall", "-Werror", + "-Wextra", ], defaults: ["stats_defaults"], shared_libs: [ From 0e589f61ba95edcef6aa8ddae7e32b239ff49903 Mon Sep 17 00:00:00 2001 From: Suren Baghdasaryan Date: Tue, 19 May 2020 12:44:31 -0700 Subject: [PATCH 6/9] lmkd: Fix min_score_adj to exclude killing foreground processes In the cases when foreground processes should not be killed min_score_adjust should be set above PERCEPTIBLE_APP_ADJ to prevent such kills. Bug: 155709603 Test: memory stress test with multiple foreground apps Signed-off-by: Suren Baghdasaryan Change-Id: If187654b8001ce843ec6085ccd2042d75a986dae --- lmkd.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lmkd.cpp b/lmkd.cpp index ede1958..e77b472 100644 --- a/lmkd.cpp +++ b/lmkd.cpp @@ -2400,7 +2400,7 @@ static void mp_event_psi(int data, uint32_t events, struct polling_params *poll_ PRId64 "%%)", wmark > WMARK_LOW ? "min" : "low", thrashing); cut_thrashing_limit = true; /* Do not kill perceptible apps because of thrashing */ - min_score_adj = PERCEPTIBLE_APP_ADJ; + min_score_adj = PERCEPTIBLE_APP_ADJ + 1; } else if (reclaim == DIRECT_RECLAIM && thrashing > thrashing_limit) { /* Page cache is thrashing while in direct reclaim (mostly happens on lowram devices) */ kill_reason = DIRECT_RECL_AND_THRASHING; @@ -2408,7 +2408,7 @@ static void mp_event_psi(int data, uint32_t events, struct polling_params *poll_ PRId64 "%%)", thrashing); cut_thrashing_limit = true; /* Do not kill perceptible apps because of thrashing */ - min_score_adj = PERCEPTIBLE_APP_ADJ; + min_score_adj = PERCEPTIBLE_APP_ADJ + 1; } /* Kill a process if necessary */ From c2b228e4985cb2a29510996a2cd694881ebcf8ce Mon Sep 17 00:00:00 2001 From: Suren Baghdasaryan Date: Tue, 19 May 2020 13:07:23 -0700 Subject: [PATCH 7/9] lmkd: Set the default free swap threshold to 10% for all devices Lower the min swap threshold to 10% for all devices to limit kills while swap still has enough space. Bug: 155709603 Test: memory stress test with multiple foreground apps Signed-off-by: Suren Baghdasaryan Change-Id: I443486763c034ed0603ea52b81c060c3969af9a5 --- lmkd.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lmkd.cpp b/lmkd.cpp index e77b472..100b92e 100644 --- a/lmkd.cpp +++ b/lmkd.cpp @@ -129,8 +129,7 @@ * System property defaults */ /* ro.lmk.swap_free_low_percentage property defaults */ -#define DEF_LOW_SWAP_LOWRAM 10 -#define DEF_LOW_SWAP 20 +#define DEF_LOW_SWAP 10 /* ro.lmk.thrashing_limit property defaults */ #define DEF_THRASHING_LOWRAM 30 #define DEF_THRASHING 100 @@ -3195,7 +3194,7 @@ static void update_props() { per_app_memcg = 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)); + 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", From 7afa46397875f76fa0eb9576872c7ab3e2895844 Mon Sep 17 00:00:00 2001 From: Suren Baghdasaryan Date: Tue, 19 May 2020 12:59:18 -0700 Subject: [PATCH 8/9] lmkd: Do not kill perceptible apps due to low swap if above min wmark Prevent kills of perceptible apps due to swap shortages unless system free memory is below the min watermark. This prevents kills of important apps when the system is recovering from the memory pressure. Bug: 155709603 Test: memory stress test with multiple foreground apps Signed-off-by: Suren Baghdasaryan Merged-In: I6beb4b55f8b4f7bc22818b5a7bdfa3adc6cd31c1 Change-Id: I6beb4b55f8b4f7bc22818b5a7bdfa3adc6cd31c1 --- lmkd.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lmkd.cpp b/lmkd.cpp index 100b92e..098fe9f 100644 --- a/lmkd.cpp +++ b/lmkd.cpp @@ -2386,12 +2386,20 @@ static void mp_event_psi(int data, uint32_t events, struct polling_params *poll_ snprintf(kill_desc, sizeof(kill_desc), "device is low on swap (%" PRId64 "kB < %" PRId64 "kB) and thrashing (%" PRId64 "%%)", mi.field.free_swap * page_k, swap_low_threshold * page_k, thrashing); + /* Do not kill perceptible apps unless below min watermark */ + if (wmark < WMARK_LOW) { + min_score_adj = PERCEPTIBLE_APP_ADJ + 1; + } } else if (swap_is_low && wmark < WMARK_HIGH) { /* Both free memory and swap are low */ kill_reason = LOW_MEM_AND_SWAP; snprintf(kill_desc, sizeof(kill_desc), "%s watermark is breached and swap is low (%" PRId64 "kB < %" PRId64 "kB)", wmark > WMARK_LOW ? "min" : "low", mi.field.free_swap * page_k, swap_low_threshold * page_k); + /* Do not kill perceptible apps unless below min watermark */ + if (wmark < WMARK_LOW) { + min_score_adj = PERCEPTIBLE_APP_ADJ + 1; + } } else if (wmark < WMARK_HIGH && thrashing > thrashing_limit) { /* Page cache is thrashing while memory is low */ kill_reason = LOW_MEM_AND_THRASHING; From dfc73bc2fe5d0fa2fa4a8caa9522a1419453485b Mon Sep 17 00:00:00 2001 From: Martin Liu Date: Tue, 2 Jun 2020 13:05:51 +0800 Subject: [PATCH 9/9] lmkd: Fix do not kill perceptible apps due to low swap if above min wmark Fix code logic to obey our intetion of not killing perceptible apps due to low swap if above min wmark. Bug: 155709603 Test: boot Signed-off-by: Martin Liu Merged-In: Ifc09c2a1fe7e21faa096988f471644f63951d81c Change-Id: Ifc09c2a1fe7e21faa096988f471644f63951d81c --- lmkd.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lmkd.cpp b/lmkd.cpp index 098fe9f..882ae4a 100644 --- a/lmkd.cpp +++ b/lmkd.cpp @@ -2387,7 +2387,7 @@ static void mp_event_psi(int data, uint32_t events, struct polling_params *poll_ "kB < %" PRId64 "kB) and thrashing (%" PRId64 "%%)", mi.field.free_swap * page_k, swap_low_threshold * page_k, thrashing); /* Do not kill perceptible apps unless below min watermark */ - if (wmark < WMARK_LOW) { + if (wmark > WMARK_MIN) { min_score_adj = PERCEPTIBLE_APP_ADJ + 1; } } else if (swap_is_low && wmark < WMARK_HIGH) { @@ -2397,7 +2397,7 @@ static void mp_event_psi(int data, uint32_t events, struct polling_params *poll_ PRId64 "kB < %" PRId64 "kB)", wmark > WMARK_LOW ? "min" : "low", mi.field.free_swap * page_k, swap_low_threshold * page_k); /* Do not kill perceptible apps unless below min watermark */ - if (wmark < WMARK_LOW) { + if (wmark > WMARK_MIN) { min_score_adj = PERCEPTIBLE_APP_ADJ + 1; } } else if (wmark < WMARK_HIGH && thrashing > thrashing_limit) {