From: SangYoun Kwak Date: Wed, 1 Feb 2023 09:10:41 +0000 (+0900) Subject: lowmem-controller: Split up lowmem-controller feature from lowmem module X-Git-Tag: accepted/tizen/unified/20230207.165818^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=93916119c25b65eb1607ebb79798910b6594dd7b;p=platform%2Fcore%2Fsystem%2Fresourced.git lowmem-controller: Split up lowmem-controller feature from lowmem module The lowmem-controller.c was created by extracting the killing-process feature from lowmem.c. * Newly created: lowmem-controller.c, lowmem-controller.h * "lowmem_controller_kill_candidates" function of lowmem-controller.c kills procs/apps from candidates list provided by the core(lowmem.c). * Symbols used only in lowmem-controller.c were moved from lowmem.c to lowmem-controller.c. * Symbols used both lowmem.c and lowmem-controller.c were moved from lowmem.c to lowmem.h. Change-Id: I8bd0f65acc9df771385c1839096f1283424ce2a5 Signed-off-by: SangYoun Kwak --- diff --git a/src/resource-limiter/memory/lowmem-controller.c b/src/resource-limiter/memory/lowmem-controller.c new file mode 100644 index 0000000..118b7cb --- /dev/null +++ b/src/resource-limiter/memory/lowmem-controller.c @@ -0,0 +1,193 @@ +/** + * resourced + * + * Copyright (c) 2023 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either excontroller or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file lowmem-controller.c + * @desc Provides controller functionalities to kill procs/apps + */ + +#include +#include + +#include "lowmem.h" +#include "lowmem-controller.h" +#include "proc-common.h" +#include "proc-main.h" +#include "resourced.h" +#include "procfs.h" +#include "trace.h" +#include "util.h" +#include "safe-kill.h" + +#define MAX_VICTIMS_BETWEEN_CHECK 3 + +static int num_vict_between_check = MAX_VICTIMS_BETWEEN_CHECK; + +static int lowmem_kill_victim(const struct task_info *tsk, int flags, + int memps_log, unsigned int *victim_size, + void(*oom_popup)(void)) +{ + pid_t pid; + int ret; + char appname[PATH_MAX]; + int sigterm = 0; + struct proc_app_info *pai; + + pid = tsk->pid; + + if (pid <= 0 || pid == getpid()) + return RESOURCED_ERROR_FAIL; + + ret = proc_get_cmdline(pid, appname, sizeof appname); + if (ret == RESOURCED_ERROR_FAIL) + return RESOURCED_ERROR_FAIL; + + if (!strcmp("memps", appname) || + !strcmp("crash-worker", appname) || + !strcmp("system-syspopup", appname)) { + _E("%s(%d) was selected, skip it", appname, pid); + return RESOURCED_ERROR_FAIL; + } + + pai = tsk->pai; + if (pai) { + resourced_proc_status_change(PROC_CGROUP_SET_TERMINATE_REQUEST, + pid, NULL, NULL, PROC_TYPE_NONE); + + if (tsk->oom_score_lru <= OOMADJ_BACKGRD_LOCKED) { + sigterm = 1; + } else if (tsk->oom_score_lru > OOMADJ_BACKGRD_LOCKED && + tsk->oom_score_lru < OOMADJ_BACKGRD_UNLOCKED) { + int app_flag = pai->flags; + sigterm = app_flag & PROC_SIGTERM; + } + + if (pai->memory.oom_killed) + sigterm = 0; + + pai->memory.oom_killed = true; + } + + if (sigterm) + safe_kill(pid, SIGTERM); + else + safe_kill(pid, SIGKILL); + + _D("[LMK] we killed, force(%d), %d (%s) score = %d, size: rss = %u KB, sigterm = %d\n", + flags & OOM_FORCE, pid, appname, tsk->oom_score_adj, + tsk->size, sigterm); + *victim_size = tsk->size; + + if (tsk->oom_score_lru > OOMADJ_FOREGRD_UNLOCKED) + return RESOURCED_ERROR_NONE; + + oom_popup(); + + return RESOURCED_ERROR_NONE; +} + +/* return LOWMEM_RECLAIM_CONT when killing should be continued */ +static int lowmem_check_kill_continued(struct task_info *tsk, int flags, + unsigned lmk_start_threshold_mb) +{ + unsigned int available_mb = 0; + + /** + * Processes with the priority higher than perceptible are killed + * only when the available memory is less than dynamic oom threshold. + */ + if (tsk->oom_score_lru > OOMADJ_BACKGRD_PERCEPTIBLE) + return LOWMEM_RECLAIM_CONT; + + if (flags & (OOM_FORCE | OOM_SINGLE_SHOT)) { + _I("[LMK] %d is dropped during force kill, flag=%d", + tsk->pid, flags); + return LOWMEM_RECLAIM_DROP; + } + available_mb = proc_get_mem_available(); + if (available_mb > lmk_start_threshold_mb) { + _I("[LMK] available=%d MB, larger than %u MB, do not kill foreground", + available_mb, lmk_start_threshold_mb); + return LOWMEM_RECLAIM_RETRY; + } + return LOWMEM_RECLAIM_CONT; +} + +int lowmem_controller_kill_candidates(GArray *candidates, + unsigned should_be_freed, unsigned int threshold, + int max_victims, int flags, + int *status, unsigned int *total_victim_size, + unsigned lmk_start_threshold_mb, + void(*oom_popup)(void)) +{ + int ret_kill = 0; + int victim_cnt = 0; + unsigned int victim_size = 0; + unsigned int victim_size_sum = 0; + int killer_status = *status; + int should_be_freed_kb = MBYTE_TO_KBYTE(should_be_freed); + + for (int i = 0; i < candidates->len; i++) { + struct task_info *tsk; + + if (i >= max_victims) { + killer_status = LOWMEM_RECLAIM_NEXT_TYPE; + break; + } + + /** + * Available memory is checking only every + * num_vict_between_check process for reducing burden. + */ + if (!(i % num_vict_between_check) && + proc_get_mem_available() > threshold) { + killer_status = LOWMEM_RECLAIM_DONE; + break; + } + + if (!(flags & OOM_NOMEMORY_CHECK) && + victim_size_sum >= should_be_freed_kb) { + _D("[LMK] victim=%d, max_victims=%d, total_size=%uKB", + victim_cnt, max_victims, victim_size_sum); + killer_status = LOWMEM_RECLAIM_DONE; + break; + } + + tsk = &g_array_index(candidates, struct task_info, i); + + killer_status = lowmem_check_kill_continued(tsk, flags, + lmk_start_threshold_mb); + if (killer_status != LOWMEM_RECLAIM_CONT) + break; + + _I("[LMK] select victims from proc_app_list pid(%d) with oom_score_adj(%d)\n", + tsk->pid, tsk->oom_score_adj); + + ret_kill = lowmem_kill_victim(tsk, flags, i, &victim_size, + oom_popup); + if (ret_kill != RESOURCED_ERROR_NONE) + continue; + victim_cnt++; + victim_size_sum += victim_size; + } + + *status = killer_status; + *total_victim_size = victim_size_sum; + + return victim_cnt; +} diff --git a/src/resource-limiter/memory/lowmem-controller.h b/src/resource-limiter/memory/lowmem-controller.h new file mode 100644 index 0000000..d848f79 --- /dev/null +++ b/src/resource-limiter/memory/lowmem-controller.h @@ -0,0 +1,35 @@ +/** + * resourced + * + * Copyright (c) 2023 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either excontroller or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/** + * @file lowmem-controller.h + * @desc Functions for controller features. + */ + +#ifndef __LOWMEM_CONTROLLER_H__ +#define __LOWMEM_CONTROLLER_H__ + +int lowmem_controller_kill_candidates(GArray *candidates, + unsigned should_be_freed, unsigned int threshold, + int max_victims, int flags, + int *status, unsigned int *total_victim_size, + unsigned lmk_start_threshold_mb, + void(*oom_popup)(void)); + +#endif /* __LOWMEM_CONTROLLER_H__ */ diff --git a/src/resource-limiter/memory/lowmem.c b/src/resource-limiter/memory/lowmem.c index aca7a6b..98dcbfe 100644 --- a/src/resource-limiter/memory/lowmem.c +++ b/src/resource-limiter/memory/lowmem.c @@ -51,6 +51,7 @@ #include "lowmem-system.h" #include "lowmem-limit.h" #include "lowmem-governor.h" +#include "lowmem-controller.h" #include "proc-common.h" #include "procfs.h" #include "freezer.h" @@ -68,10 +69,8 @@ #include "util.h" #include "fd-handler.h" #include "resourced-helper-worker.h" -#include "safe-kill.h" #include "dedup-common.h" -#define MAX_VICTIMS_BETWEEN_CHECK 3 #define MAX_PROACTIVE_HIGH_VICTIMS 4 #define FOREGROUND_VICTIMS 1 #define OOM_KILLER_PRIORITY -20 @@ -282,7 +281,6 @@ static void lmk_act(void); static size_t cur_mem_state = MEM_LEVEL_HIGH; static int num_max_victims = MAX_MEMORY_CGROUP_VICTIMS; -static int num_vict_between_check = MAX_VICTIMS_BETWEEN_CHECK; static unsigned long long totalram_bytes; static unsigned long totalram_kb; @@ -388,96 +386,6 @@ unsigned int lowmem_get_task_mem_usage_rss(const struct task_info *tsk) return total_size_kb; } -static int lowmem_kill_victim(const struct task_info *tsk, - int flags, int memps_log, unsigned int *victim_size) -{ - pid_t pid; - int ret; - char appname[PATH_MAX]; - int sigterm = 0; - struct proc_app_info *pai; - - pid = tsk->pid; - - if (pid <= 0 || pid == getpid()) - return RESOURCED_ERROR_FAIL; - - ret = proc_get_cmdline(pid, appname, sizeof appname); - if (ret == RESOURCED_ERROR_FAIL) - return RESOURCED_ERROR_FAIL; - - if (!strcmp("memps", appname) || - !strcmp("crash-worker", appname) || - !strcmp("system-syspopup", appname)) { - _E("%s(%d) was selected, skip it", appname, pid); - return RESOURCED_ERROR_FAIL; - } - - pai = tsk->pai; - if (pai) { - resourced_proc_status_change(PROC_CGROUP_SET_TERMINATE_REQUEST, - pid, NULL, NULL, PROC_TYPE_NONE); - - if (tsk->oom_score_lru <= OOMADJ_BACKGRD_LOCKED) { - sigterm = 1; - } else if (tsk->oom_score_lru > OOMADJ_BACKGRD_LOCKED && tsk->oom_score_lru < OOMADJ_BACKGRD_UNLOCKED) { - int app_flag = pai->flags; - sigterm = app_flag & PROC_SIGTERM; - } - - if (pai->memory.oom_killed) - sigterm = 0; - - pai->memory.oom_killed = true; - } - - if (sigterm) - safe_kill(pid, SIGTERM); - else - safe_kill(pid, SIGKILL); - - _D("[LMK] we killed, force(%d), %d (%s) score = %d, size: rss = %u KB, sigterm = %d\n", - flags & OOM_FORCE, pid, appname, tsk->oom_score_adj, - tsk->size, sigterm); - *victim_size = tsk->size; - - if (tsk->oom_score_lru > OOMADJ_FOREGRD_UNLOCKED) - return RESOURCED_ERROR_NONE; - - if (oom_popup_enable && !oom_popup) { - lowmem_launch_oompopup(); - oom_popup = true; - } - - return RESOURCED_ERROR_NONE; -} - -/* return LOWMEM_RECLAIM_CONT when killing should be continued */ -static int lowmem_check_kill_continued(struct task_info *tsk, int flags) -{ - unsigned int available_mb; - - /* - * Processes with the priority higher than perceptible are killed - * only when the available memory is less than dynamic oom threshold. - */ - if (tsk->oom_score_lru > OOMADJ_BACKGRD_PERCEPTIBLE) - return LOWMEM_RECLAIM_CONT; - - if (flags & (OOM_FORCE|OOM_SINGLE_SHOT)) { - _I("[LMK] %d is dropped during force kill, flag=%d", - tsk->pid, flags); - return LOWMEM_RECLAIM_DROP; - } - available_mb = proc_get_mem_available(); - if (available_mb > lmk_start_threshold_mb) { - _I("[LMK] available=%d MB, larger than %u MB, do not kill foreground", - available_mb, lmk_start_threshold_mb); - return LOWMEM_RECLAIM_RETRY; - } - return LOWMEM_RECLAIM_CONT; -} - static void lowmem_free_task_info_array(GArray *array) { int i; @@ -517,6 +425,14 @@ static unsigned int is_memory_recovered(unsigned int *avail, unsigned int thres) return should_be_freed_mb; } +static void lowmem_oom_popup_once(void) +{ + if (oom_popup_enable && !oom_popup) { + lowmem_launch_oompopup(); + oom_popup = true; + } +} + /** * @brief Terminate up to max_victims processes after finding them from pai. It depends on proc_app_info lists @@ -536,12 +452,10 @@ static int lowmem_kill_victims(int max_victims, unsigned int *total_size, int *completed, unsigned int threshold) { GSList *proc_app_list = NULL; - int i, ret, victim = 0; - unsigned int victim_size = 0; unsigned int total_victim_size = 0; + int victim_cnt = 0; int status = LOWMEM_RECLAIM_NONE; GArray *candidates = NULL; - int should_be_freed_kb = MBYTE_TO_KBYTE(should_be_freed); proc_app_list = proc_app_list_open(); @@ -556,47 +470,12 @@ static int lowmem_kill_victims(int max_victims, goto leave; } - for (i = 0; i < candidates->len; i++) { - struct task_info *tsk; - - if (i >= max_victims) { - status = LOWMEM_RECLAIM_NEXT_TYPE; - break; - } - - /* - * Available memory is checking only every - * num_vict_between_check process for reducing burden. - */ - if (!(i % num_vict_between_check)) { - if (proc_get_mem_available() > threshold) { - status = LOWMEM_RECLAIM_DONE; - break; - } - } - - if (!(flags & OOM_NOMEMORY_CHECK) && - total_victim_size >= should_be_freed_kb) { - _D("[LMK] victim=%d, max_victims=%d, total_size=%uKB", - victim, max_victims, total_victim_size); - status = LOWMEM_RECLAIM_DONE; - break; - } - - tsk = &g_array_index(candidates, struct task_info, i); - - status = lowmem_check_kill_continued(tsk, flags); - if (status != LOWMEM_RECLAIM_CONT) - break; - - _I("[LMK] select victims from proc_app_list pid(%d) with oom_score_adj(%d)\n", tsk->pid, tsk->oom_score_adj); - - ret = lowmem_kill_victim(tsk, flags, i, &victim_size); - if (ret != RESOURCED_ERROR_NONE) - continue; - victim++; - total_victim_size += victim_size; - } + victim_cnt = lowmem_controller_kill_candidates(candidates, + should_be_freed, threshold, + max_victims, flags, + &status, &total_victim_size, + lmk_start_threshold_mb, + lowmem_oom_popup_once); leave: lowmem_free_task_info_array(candidates); @@ -605,7 +484,7 @@ leave: *completed = status; else *completed = LOWMEM_RECLAIM_NEXT_TYPE; - return victim; + return victim_cnt; } static int calculate_range_of_oom(enum oom_score score, int *min, int *max)