From: SangYoun Kwak Date: Thu, 30 Mar 2023 08:21:27 +0000 (+0900) Subject: lowmem-controller: Move oom memory action from lowmem to controller X-Git-Tag: accepted/tizen/unified/20230613.170823~7 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=deda1a146f90d3a85acdc79e23e71bf337332d3e;p=platform%2Fcore%2Fsystem%2Fresourced.git lowmem-controller: Move oom memory action from lowmem to controller For modulization, oom memory action is moved from lowmem.c(core) to lowmem-controller.c(controller) and this action will be assigned to lowmem.c by the initializer of controller. Change-Id: Ida6f53bb0af6a4d8ddf438ea14c939c732027bfb Signed-off-by: SangYoun Kwak --- diff --git a/src/resource-limiter/memory/lowmem-controller.c b/src/resource-limiter/memory/lowmem-controller.c index 7e9213ea..676f3fa9 100644 --- a/src/resource-limiter/memory/lowmem-controller.c +++ b/src/resource-limiter/memory/lowmem-controller.c @@ -21,6 +21,7 @@ * @desc Provides controller functionalities to kill procs/apps */ +#include #include #include #include @@ -213,6 +214,39 @@ static int dedup_prepare(void) return RESOURCED_ERROR_NONE; } +static void lowmem_memory_level_send_system_event(int lv) +{ + bundle *b; + const char *bundle_str; + + switch (lv) { + case MEM_LEVEL_HIGH: + case MEM_LEVEL_MEDIUM: + case MEM_LEVEL_LOW: + bundle_str = EVT_VAL_MEMORY_NORMAL; + break; + case MEM_LEVEL_CRITICAL: + bundle_str = EVT_VAL_MEMORY_SOFT_WARNING; + break; + case MEM_LEVEL_OOM: + bundle_str = EVT_VAL_MEMORY_HARD_WARNING; + break; + default: + _E("Invalid state"); + return; + } + + b = bundle_create(); + if (!b) { + _E("Failed to create bundle"); + return; + } + + bundle_add_str(b, EVT_KEY_LOW_MEMORY, bundle_str); + eventsystem_send_system_event(SYS_EVENT_LOW_MEMORY, b); + bundle_free(b); +} + static void swap_activate_act(void) { int ret, status; @@ -308,7 +342,7 @@ static void lowmem_move_memcgroup(int pid, int next_oom_score_adj, struct proc_a } } -int lowmem_control_handler(void *data) +static int lowmem_control_handler(void *data) { struct lowmem_control_data *lowmem_data = (struct lowmem_control_data *)data; @@ -325,6 +359,15 @@ int lowmem_control_handler(void *data) return RESOURCED_ERROR_NONE; } +static void medium_cb(struct lowmem_control *ctl) +{ + if (ctl->status == LOWMEM_RECLAIM_DONE) + lowmem_set_oom_popup(false); + lowmem_change_memory_state(MEM_LEVEL_HIGH, 0); +} + + + /* lowmem actions */ static int high_mem_act(void *data) { @@ -394,6 +437,43 @@ static int critical_mem_act(void *data) return RESOURCED_ERROR_NONE; } +static int oom_mem_act(void *data) +{ + unsigned int available_mb; + int status = VCONFKEY_SYSMAN_LOW_MEMORY_NORMAL; + + if (vconf_get_int(VCONFKEY_SYSMAN_LOW_MEMORY, &status) != 0) + _D("vconf_get_int fail %s", VCONFKEY_SYSMAN_LOW_MEMORY); + + lowmem_memory_level_send_system_event(MEM_LEVEL_OOM); + if (status != VCONFKEY_SYSMAN_LOW_MEMORY_HARD_WARNING) { + if (proc_get_freezer_status() == CGROUP_FREEZER_ENABLED) + resourced_notify(RESOURCED_NOTIFIER_FREEZER_CGROUP_STATE, + (void *)CGROUP_FREEZER_PAUSED); + vconf_set_int(VCONFKEY_SYSMAN_LOW_MEMORY, + VCONFKEY_SYSMAN_LOW_MEMORY_HARD_WARNING); + } + available_mb = proc_get_mem_available(); + + lowmem_change_lowmem_state(MEM_LEVEL_OOM); + + if (available_mb < get_root_memcg_info()->threshold_leave_mb) { + lowmem_queue_new_request(OOM_IN_DEPTH, OOM_SCORE_LOW, + get_root_memcg_info()->threshold_leave_mb, + lowmem_get_num_max_victims(), medium_cb); + } + + resourced_notify(RESOURCED_NOTIFIER_SWAP_COMPACT, + (void *)SWAP_COMPACT_MEM_LEVEL_OOM); + + /** + * Flush resourced memory such as other processes. + * Resourced can use both many fast bins and sqlite3 cache memery. + */ + malloc_trim(0); + + return RESOURCED_ERROR_NONE; +} static int lowmem_controller_initialize(void *data) @@ -411,6 +491,7 @@ static int lowmem_controller_initialize(void *data) lowmem_initialize_controller_ops_action(MEM_LEVEL_MEDIUM, medium_mem_act); lowmem_initialize_controller_ops_action(MEM_LEVEL_LOW, low_mem_act); lowmem_initialize_controller_ops_action(MEM_LEVEL_CRITICAL, critical_mem_act); + lowmem_initialize_controller_ops_action(MEM_LEVEL_OOM, oom_mem_act); register_notifier(RESOURCED_NOTIFIER_MEM_CONTROL, lowmem_control_handler); diff --git a/src/resource-limiter/memory/lowmem-governor.c b/src/resource-limiter/memory/lowmem-governor.c index 2803fdca..7e245053 100644 --- a/src/resource-limiter/memory/lowmem-governor.c +++ b/src/resource-limiter/memory/lowmem-governor.c @@ -33,6 +33,13 @@ static int mem_state_dummy_governor(void *data) return RESOURCED_ERROR_NONE; } +static int oom_mem_governor(void *data) +{ + if (lowmem_worker_is_running()) + return RESOURCED_ERROR_FAIL; + return RESOURCED_ERROR_NONE; +} + static int lowmem_governor_initialize(void *data) { /** @@ -48,6 +55,7 @@ static int lowmem_governor_initialize(void *data) lowmem_initialize_controller_ops_governor(MEM_LEVEL_MEDIUM, mem_state_dummy_governor); lowmem_initialize_controller_ops_governor(MEM_LEVEL_LOW, mem_state_dummy_governor); lowmem_initialize_controller_ops_governor(MEM_LEVEL_CRITICAL, mem_state_dummy_governor); + lowmem_initialize_controller_ops_governor(MEM_LEVEL_OOM, oom_mem_governor); return RESOURCED_ERROR_NONE; } diff --git a/src/resource-limiter/memory/lowmem.c b/src/resource-limiter/memory/lowmem.c index e972d2fe..90ce82d2 100644 --- a/src/resource-limiter/memory/lowmem.c +++ b/src/resource-limiter/memory/lowmem.c @@ -175,31 +175,6 @@ static unsigned lmk_start_threshold_mb; #define LMW_LOOP_WAIT_TIMEOUT_MSEC OOM_TIMER_INTERVAL_SEC*(G_USEC_PER_SEC) #define LMW_RETRY_WAIT_TIMEOUT_MSEC (G_USEC_PER_SEC) -struct lowmem_control { - /* - * For each queued request the following properties - * are required with two exceptions: - * - status is being set by LMK - * - callback is optional - */ - /* Processing flags*/ - unsigned int flags; - /* Indictator for OOM score of targeted processes */ - enum oom_score score; - - /* Desired size to be restored - level to be reached (MB)*/ - unsigned int size_mb; - /* Max number of processes to be considered */ - unsigned int count; - /* Memory reclaim status */ - int status; - /* - * Optional - if set, will be triggered by LMK once the request - * is handled. - */ - void (*callback) (struct lowmem_control *); -}; - struct lowmem_worker { pthread_t worker_thread; GAsyncQueue *queue; @@ -226,12 +201,10 @@ static GArray *lowmem_task_info_proc_array = NULL; #define LOWMEM_WORKER_ACTIVATE(_lmw) g_atomic_int_set(&(_lmw)->active, 1) #define LOWMEM_WORKER_DEACTIVATE(_lmw) g_atomic_int_set(&(_lmw)->active, 0) -#define LOWMEM_WORKER_IS_RUNNING(_lmw) g_atomic_int_get(&(_lmw)->running) #define LOWMEM_WORKER_RUN(_lmw) g_atomic_int_set(&(_lmw)->running, 1) #define LOWMEM_WORKER_IDLE(_lmw) g_atomic_int_set(&(_lmw)->running, 0) #define LOWMEM_NEW_REQUEST() g_slice_new0(struct lowmem_control) - #define LOWMEM_DESTROY_REQUEST(_ctl) \ g_slice_free(typeof(*(_ctl)), _ctl); \ @@ -242,6 +215,11 @@ static GArray *lowmem_task_info_proc_array = NULL; (c)->callback = __cb; \ } +int lowmem_worker_is_running() +{ + return g_atomic_int_get(&(lmw.running)); +} + static void lowmem_queue_request(struct lowmem_worker *lmw, struct lowmem_control *ctl) { @@ -274,10 +252,6 @@ static void lowmem_request_destroy(gpointer data) /*-------------------------------------------------*/ -/* low memory action function for cgroup */ -/* low memory action function */ -static void lmk_act(void); - struct lowmem_controller_ops { int (*governor)(void *data); int (*action)(void *data); @@ -290,6 +264,7 @@ void lowmem_initialize_controller_ops_governor(int mem_state, int (*governor)(vo case MEM_LEVEL_MEDIUM: case MEM_LEVEL_LOW: case MEM_LEVEL_CRITICAL: + case MEM_LEVEL_OOM: lowmem_actions[mem_state].governor = governor; return; default: @@ -302,6 +277,7 @@ void lowmem_initialize_controller_ops_action(int mem_state, int (*action)(void * case MEM_LEVEL_HIGH: case MEM_LEVEL_MEDIUM: case MEM_LEVEL_CRITICAL: + case MEM_LEVEL_OOM: lowmem_actions[mem_state].action = action; return; default: @@ -311,6 +287,10 @@ void lowmem_initialize_controller_ops_action(int mem_state, int (*action)(void * static size_t cur_mem_state = MEM_LEVEL_HIGH; static int num_max_victims = MAX_MEMORY_CGROUP_VICTIMS; +int lowmem_get_num_max_victims() +{ + return num_max_victims; +} static unsigned long long totalram_bytes; static unsigned long totalram_kb; @@ -466,6 +446,11 @@ static unsigned int is_memory_recovered(unsigned int *avail, unsigned int thres) return should_be_freed_mb; } +void lowmem_set_oom_popup(bool popup) +{ + oom_popup = popup; +} + static void lowmem_oom_popup_once(void) { if (oom_popup_enable && !oom_popup) { @@ -995,98 +980,6 @@ void lowmem_trigger_swap(pid_t pid, char *path, bool move) resourced_notify(RESOURCED_NOTIFIER_SWAP_START, path); } -void lowmem_memory_level_send_system_event(int lv) -{ - bundle *b; - const char *str; - - switch (lv) { - case MEM_LEVEL_HIGH: - case MEM_LEVEL_MEDIUM: - case MEM_LEVEL_LOW: - str = EVT_VAL_MEMORY_NORMAL; - break; - case MEM_LEVEL_CRITICAL: - str = EVT_VAL_MEMORY_SOFT_WARNING; - break; - case MEM_LEVEL_OOM: - str = EVT_VAL_MEMORY_HARD_WARNING; - break; - default: - _E("Invalid state"); - return; - } - - b = bundle_create(); - if (!b) { - _E("Failed to create bundle"); - return; - } - - bundle_add_str(b, EVT_KEY_LOW_MEMORY, str); - eventsystem_send_system_event(SYS_EVENT_LOW_MEMORY, b); - bundle_free(b); -} - -static void medium_cb(struct lowmem_control *ctl) -{ - if (ctl->status == LOWMEM_RECLAIM_DONE) - oom_popup = false; - lowmem_change_memory_state(MEM_LEVEL_HIGH, 0); -} - -static void lmk_act(void) -{ - unsigned int available_mb; - int ret; - int status = VCONFKEY_SYSMAN_LOW_MEMORY_NORMAL; - - /* - * Don't trigger reclaim worker - * if it is already running - */ - if (LOWMEM_WORKER_IS_RUNNING(&lmw)) - return; - - ret = vconf_get_int(VCONFKEY_SYSMAN_LOW_MEMORY, &status); - if (ret) - _D("vconf_get_int fail %s", VCONFKEY_SYSMAN_LOW_MEMORY); - - lowmem_memory_level_send_system_event(MEM_LEVEL_OOM); - if (status != VCONFKEY_SYSMAN_LOW_MEMORY_HARD_WARNING) { - if (proc_get_freezer_status() == CGROUP_FREEZER_ENABLED) - resourced_notify(RESOURCED_NOTIFIER_FREEZER_CGROUP_STATE, - (void *)CGROUP_FREEZER_PAUSED); - vconf_set_int(VCONFKEY_SYSMAN_LOW_MEMORY, - VCONFKEY_SYSMAN_LOW_MEMORY_HARD_WARNING); - } - available_mb = proc_get_mem_available(); - - lowmem_change_lowmem_state(MEM_LEVEL_OOM); - - if (available_mb < get_root_memcg_info()->threshold_leave_mb) { - struct lowmem_control *ctl; - - ctl = LOWMEM_NEW_REQUEST(); - if (ctl) { - LOWMEM_SET_REQUEST(ctl, OOM_IN_DEPTH, - OOM_SCORE_LOW, get_root_memcg_info()->threshold_leave_mb, - num_max_victims, medium_cb); - lowmem_queue_request(&lmw, ctl); - } - } - - resourced_notify(RESOURCED_NOTIFIER_SWAP_COMPACT, (void *)SWAP_COMPACT_MEM_LEVEL_OOM); - - /* - * Flush resourced memory such as other processes. - * Resourced can use both many fast bins and sqlite3 cache memery. - */ - malloc_trim(0); - - return; -} - void lowmem_trigger_memory_state_action(int mem_state) { /* @@ -1102,15 +995,13 @@ void lowmem_trigger_memory_state_action(int mem_state) case MEM_LEVEL_MEDIUM: case MEM_LEVEL_LOW: case MEM_LEVEL_CRITICAL: + case MEM_LEVEL_OOM: assert(lowmem_actions[mem_state].governor != NULL); assert(lowmem_actions[mem_state].action != NULL); if (lowmem_actions[mem_state].governor(NULL) < 0) break; lowmem_actions[mem_state].action(NULL); break; - case MEM_LEVEL_OOM: - lmk_act(); - break; default: assert(0); } @@ -1292,6 +1183,26 @@ int lowmem_trigger_reclaim(int flags, int victims, enum oom_score score, int thr return 0; } +int lowmem_queue_new_request(unsigned int flags, enum oom_score score, + unsigned int size_mb, unsigned int count, + void (*callback)(struct lowmem_control *)) +{ + struct lowmem_control *ctl = LOWMEM_NEW_REQUEST(); + + if (!ctl) + return RESOURCED_ERROR_OUT_OF_MEMORY; + + ctl->flags = flags; + ctl->score = score; + ctl->size_mb = size_mb; + ctl->count = count; + ctl->callback = callback; + + lowmem_queue_request(&lmw, ctl); + + return RESOURCED_ERROR_NONE; +} + void lowmem_trigger_swap_reclaim(enum oom_score score, unsigned long long swap_size_bytes) { int size_mb, victims; diff --git a/src/resource-limiter/memory/lowmem.h b/src/resource-limiter/memory/lowmem.h index 136a5112..b189da47 100644 --- a/src/resource-limiter/memory/lowmem.h +++ b/src/resource-limiter/memory/lowmem.h @@ -104,10 +104,41 @@ void lowmem_initialize_controller_ops_governor(int mem_state, int (*governor)(vo void lowmem_initialize_controller_ops_action(int mem_state, int (*action)(void *data)); unsigned int lowmem_get_lowmem_state(); void lowmem_change_lowmem_state(unsigned int mem_state); -void lowmem_memory_level_send_system_event(int lv); bool lowmem_get_memcg_swap_status(); void lowmem_set_memcg_swap_status(bool status); +struct lowmem_control { + /* + * For each queued request the following properties + * are required with two exceptions: + * - status is being set by LMK + * - callback is optional + */ + /* Processing flags*/ + unsigned int flags; + /* Indictator for OOM score of targeted processes */ + enum oom_score score; + + /* Desired size to be restored - level to be reached (MB)*/ + unsigned int size_mb; + /* Max number of processes to be considered */ + unsigned int count; + /* Memory reclaim status */ + int status; + /* + * Optional - if set, will be triggered by LMK once the request + * is handled. + */ + void (*callback) (struct lowmem_control *); +}; + +int lowmem_worker_is_running(); +int lowmem_queue_new_request(unsigned int flags, enum oom_score score, + unsigned int size_mb, unsigned int count, + void (*callback) (struct lowmem_control *)); +void lowmem_set_oom_popup(bool popup); +int lowmem_get_num_max_victims(); + #ifdef __cplusplus } #endif /* __cplusplus */