Add unit(in variable) & fix bugs
[platform/core/system/resourced.git] / src / resource-limiter / memory / lowmem-limit.c
index a259a99..f4f92a3 100644 (file)
@@ -74,10 +74,10 @@ static enum mem_limit_type mem_limit;*/
 
 static GHashTable *memory_limit_hash;
 static char *registerpath;
-static unsigned int mem_service_limit;
-static unsigned int mem_widget_limit;
-static unsigned int mem_guiapp_limit;
-static unsigned int mem_bgapp_limit;
+static unsigned long long mem_service_limit_bytes;
+static unsigned long long mem_widget_limit_bytes;
+static unsigned long long mem_guiapp_limit_bytes;
+static unsigned long long mem_bgapp_limit_bytes;
 
 static int mem_service_action = PROC_ACTION_IGNORE;
 static int mem_widget_action = PROC_ACTION_IGNORE;
@@ -150,7 +150,7 @@ static gboolean liveness_check_cb(gpointer data)
 
        if (mle->pids_array == NULL) {
                _E("[MEMORY-LIMIT] pids array should not be NULL");
-               goto mle_timer_init;
+               goto timer_out;
        }
 
        for (int i = 0; i < mle->pids_array->len; i++) {
@@ -166,7 +166,6 @@ static gboolean liveness_check_cb(gpointer data)
 
        g_array_free(mle->pids_array, true);
 
-mle_timer_init:
        mle->pids_array = NULL;
 timer_out:
        return G_SOURCE_REMOVE;
@@ -177,8 +176,8 @@ static bool memory_action_cb(int fd, void *data)
        int result;
        pid_t pid;
        GArray *pids_array = NULL;
-       uint32_t usage;
-       uint64_t dummy_efd;
+       unsigned long long usage_bytes;
+       unsigned long long dummy_efd;
        char *cg_dir = (char *)data;
        struct memory_limit_event *mle;
 
@@ -199,18 +198,18 @@ static bool memory_action_cb(int fd, void *data)
                goto remove_mle;
        }
 
-       result = cgroup_read_node_uint32(cg_dir, MEMCG_SWAP_USAGE, &usage);
+       result = cgroup_read_node_ulonglong(cg_dir, MEMCG_SWAP_USAGE, &usage_bytes);
        if (result < 0) {
-               result = cgroup_read_node_uint32(cg_dir, MEMCG_USAGE, &usage);
+               result = cgroup_read_node_ulonglong(cg_dir, MEMCG_USAGE, &usage_bytes);
                if (result < 0) {
                        _D("[MEMORY-LIMIT] there is no (%s) cgroup any longer, removed it", cg_dir);
                        goto remove_mle;
                }
        }
 
-       if (usage < mle->threshold) {
-               _D("[MEMORY-LIMIT] (%s) cgroup escaped low memory status. usage(%d), threshold(%d)",
-                       cg_dir, usage, mle->threshold);
+       if (usage_bytes < mle->threshold_bytes) {
+               _D("[MEMORY-LIMIT] (%s) cgroup escaped low memory status. usage(%llu) bytes, threshold(%llu) bytes",
+                       cg_dir, usage_bytes, mle->threshold_bytes);
                return true;
        }
 
@@ -273,13 +272,14 @@ remove_mle:
 }
 
 int lowmem_reassign_limit(const char *dir,
-               unsigned int limit, enum proc_action action)
+               unsigned long long limit_bytes, enum proc_action action)
 {
        int fd;
        fd_handler_h fdh = NULL;
        gpointer hash_entry;
        struct memory_limit_event *mle = NULL;
        char buf[MAX_DEC_SIZE(int)] = {0};
+       unsigned long long max_limit_bytes;
 
        if (memory_limit_hash) {
                /* TO DO: currently concurrent processes with same app name are located
@@ -289,7 +289,7 @@ int lowmem_reassign_limit(const char *dir,
                hash_entry = g_hash_table_lookup(memory_limit_hash, dir);
                if (hash_entry) {
                        mle = (struct memory_limit_event *)hash_entry;
-                       if (mle->threshold == limit) {
+                       if (mle->threshold_bytes == limit_bytes) {
                                return RESOURCED_ERROR_NONE;
                        }
                }
@@ -303,11 +303,22 @@ int lowmem_reassign_limit(const char *dir,
                }
        }
 
-       check_oom_and_set_limit(dir, limit * 1.2);
-       snprintf(buf, sizeof(buf), "%d", limit);
+       if (limit_bytes > lowmem_get_totalram()) {
+               max_limit_bytes = lowmem_get_totalram();
+               limit_bytes = lowmem_get_totalram();
+       }
+       else if (limit_bytes * 1.2 > lowmem_get_totalram()) {
+               max_limit_bytes = lowmem_get_totalram();
+       }
+       else
+               max_limit_bytes = limit_bytes * 1.2;
+
+       check_oom_and_set_limit(dir, max_limit_bytes);
+
+       snprintf(buf, sizeof(buf), "%llu", limit_bytes);
 
        if (mle) {
-               mle->threshold = limit;
+               mle->threshold_bytes = limit_bytes;
                memcg_init_eventfd(mle->fd, dir, registerpath, buf);
                return RESOURCED_ERROR_NONE;
        }
@@ -327,7 +338,7 @@ int lowmem_reassign_limit(const char *dir,
                        return RESOURCED_ERROR_OUT_OF_MEMORY;
                }
                mle->action = action;
-               mle->threshold = limit;
+               mle->threshold_bytes = limit_bytes;
                mle->pids_array = NULL;
                add_fd_read_handler(fd, memory_action_cb, mle->path, NULL, &fdh);
                mle->fdh = fdh;
@@ -365,65 +376,72 @@ int lowmem_limit_move_cgroup(struct proc_app_info *pai)
        return RESOURCED_ERROR_NONE;
 }
 
-void lowmem_limit_set_system_service(pid_t pid, unsigned int limit,
+int lowmem_limit_set_system_service(pid_t pid, unsigned long long limit_bytes,
                const char *name, enum proc_action action)
 {
        _cleanup_free_ char *path = NULL;
        int result;
-       unsigned int totalram = lowmem_get_totalram();
+       unsigned long long totalram_bytes = lowmem_get_totalram();
 
-       if (limit < MIN_LIMIT_VALUE || limit > totalram) {
-               _E("[MEMORY-LIMIT] It's meaningless to set memory limit with size (%d)", limit);
-               return;
+       if (limit_bytes < MIN_LIMIT_VALUE || limit_bytes > totalram_bytes) {
+               _E("[MEMORY-LIMIT] It's meaningless to set memory limit with size (%llu) bytes", limit_bytes);
+               return RESOURCED_ERROR_INVALID_PARAMETER;
        }
 
        if (action == PROC_ACTION_IGNORE)
-               return;
+               return RESOURCED_ERROR_NONE;
 
        if (!name) {
                _E("[MEMORY-LIMIT] service name is NULL");
-               return;
+               return RESOURCED_ERROR_FAIL;
        }
 
        result = asprintf(&path, "%s/%s", MEMCG_HIGH_PP_PATH, name);
        if (result < 0) {
                _E("[MEMORY-LIMIT] not enough memory");
-               return;
+               return RESOURCED_ERROR_OUT_OF_MEMORY;
        }
 
        result = cgroup_make_subdir(MEMCG_HIGH_PP_PATH, name, NULL);
        if (result < 0) {
                _E("[MEMORY-LIMIT] Failed to create cgroup subdir '%s/%s'",
                                MEMCG_HIGH_PP_PATH, name);
-               return;
+               return result;
        }
 
-       result = lowmem_reassign_limit(path, limit, action);
+       result = lowmem_reassign_limit(path, limit_bytes, action);
        if (result < 0) {
                _W("[MEMORY-LIMIT] Failed to reassign limit for %s", path);
-               return;
+               return result;
        }
 
        result = cgroup_write_node_uint32(path, MEMCG_MOVE_CHARGE, 3U);
-       if (result < 0)
+       if (result < 0) {
                _W("[MEMORY-LIMIT] Failed to set immigrate mode for %s (non-crucial, continuing)", path);
+               return result;
+       }
 
        cgroup_write_pid_fullpath(path, pid);
+
+       return RESOURCED_ERROR_NONE;
 }
 
-int lowmem_limit_set_app(unsigned int limit, struct proc_app_info *pai,
+int lowmem_limit_set_app(unsigned long long limit_bytes, struct proc_app_info *pai,
                enum proc_action action)
 {
        _cleanup_free_ char *path = NULL;
        GSList *iter = NULL;
        int result;
-       unsigned int totalram = lowmem_get_totalram();
+       unsigned long long totalram_bytes = lowmem_get_totalram();
 
-       if (limit < MIN_LIMIT_VALUE || limit > totalram) {
-               _E("[MEMORY-LIMIT] It's meaningless to set memory limit with size (%d)", limit);
+       if (limit_bytes < MIN_LIMIT_VALUE || limit_bytes > totalram_bytes) {
+               _E("[MEMORY-LIMIT] It's meaningless to set memory limit with size (%llu) bytes", limit_bytes);
                return RESOURCED_ERROR_INVALID_PARAMETER;
        }
 
+       if (action == PROC_ACTION_IGNORE)
+               return RESOURCED_ERROR_NONE;
+
        if (!pai) {
                _E("[MEMORY-LIMIT] process app information is NULL");
                return RESOURCED_ERROR_INVALID_PARAMETER;
@@ -442,7 +460,7 @@ int lowmem_limit_set_app(unsigned int limit, struct proc_app_info *pai,
                return result;
        }
 
-       result = lowmem_reassign_limit(path, limit, action);
+       result = lowmem_reassign_limit(path, limit_bytes, action);
        if (result < 0) {
                _W("[MEMORY-LIMIT] Failed to reassign limit for %s", path);
                return result;
@@ -471,20 +489,25 @@ static int lowmem_limit_app(void *data)
 
        struct proc_limit_status *pls = (struct proc_limit_status *)data;
 
-       error = lowmem_limit_set_app(pls->limit, pls->ps.pai, pls->action);
+       error = lowmem_limit_set_app(pls->limit_bytes, pls->ps.pai, pls->action);
        if (!error)
                pls->ps.pai->memory.memlimit_update_exclude = true;
-       return RESOURCED_ERROR_NONE;
+
+       return error;
 }
 
 static int lowmem_limit_system_service(void *data)
 {
+       int error;
+
        assert(data);
 
        struct proc_limit_status *pls = (struct proc_limit_status *)data;
 
-       lowmem_limit_set_system_service(pls->ps.pid, pls->limit, pls->ps.pci->name, pls->action);
-       return RESOURCED_ERROR_NONE;
+       error = lowmem_limit_set_system_service(pls->ps.pid, pls->limit_bytes,
+                       pls->ps.pci->name, pls->action);
+
+       return error;
 }
 
 static int lowmem_limit_service(void *data)
@@ -496,8 +519,8 @@ static int lowmem_limit_service(void *data)
        if (ps->pai && ps->pai->memory.memlimit_update_exclude)
                return RESOURCED_ERROR_NONE;
 
-       if (mem_service_limit && mem_service_action != PROC_ACTION_IGNORE) {
-               lowmem_limit_set_app(mem_service_limit, ps->pai, mem_service_action);
+       if (mem_service_limit_bytes && mem_service_action != PROC_ACTION_IGNORE) {
+               lowmem_limit_set_app(mem_service_limit_bytes, ps->pai, mem_service_action);
        }
        return RESOURCED_ERROR_NONE;
 }
@@ -511,14 +534,14 @@ static int lowmem_limit_appwidget(void *data)
        if (ps->pai && ps->pai->memory.memlimit_update_exclude)
                return RESOURCED_ERROR_NONE;
 
-       if (mem_guiapp_limit && mem_guiapp_action != PROC_ACTION_IGNORE &&
+       if (mem_guiapp_limit_bytes && mem_guiapp_action != PROC_ACTION_IGNORE &&
            ps->pai->type == PROC_TYPE_GUI) {
-               lowmem_limit_set_app(mem_guiapp_limit, ps->pai, mem_guiapp_action);
+               lowmem_limit_set_app(mem_guiapp_limit_bytes, ps->pai, mem_guiapp_action);
        }
 
-       if (mem_widget_limit && mem_widget_action != PROC_ACTION_IGNORE &&
+       if (mem_widget_limit_bytes && mem_widget_action != PROC_ACTION_IGNORE &&
            ps->pai->type == PROC_TYPE_WIDGET) {
-               lowmem_limit_set_app(mem_widget_limit, ps->pai, mem_widget_action);
+               lowmem_limit_set_app(mem_widget_limit_bytes, ps->pai, mem_widget_action);
        }
 
        return RESOURCED_ERROR_NONE;
@@ -533,7 +556,7 @@ static int lowmem_limit_bgapp(void *data)
        if (ps->pai && ps->pai->memory.memlimit_update_exclude)
                return RESOURCED_ERROR_NONE;
 
-       lowmem_limit_set_app(mem_bgapp_limit, ps->pai, mem_bgapp_action);
+       lowmem_limit_set_app(mem_bgapp_limit_bytes, ps->pai, mem_bgapp_action);
 
        return RESOURCED_ERROR_NONE;
 }
@@ -544,8 +567,8 @@ static int lowmem_limit_fgapp(void *data)
 
        struct proc_status *ps = (struct proc_status *)data;
 
-       if ((mem_guiapp_limit && ps->pai->type == PROC_TYPE_GUI) ||
-           (mem_widget_limit && ps->pai->type == PROC_TYPE_WIDGET))
+       if ((mem_guiapp_limit_bytes && ps->pai->type == PROC_TYPE_GUI) ||
+           (mem_widget_limit_bytes && ps->pai->type == PROC_TYPE_WIDGET))
                return lowmem_limit_appwidget(data);
 
        _E("[MEMORY-LIMIT] Unable to set foreground app limit - app type not supported");
@@ -553,13 +576,16 @@ static int lowmem_limit_fgapp(void *data)
        return RESOURCED_ERROR_NONE;
 }
 
-void lowmem_memory_init(unsigned int service_limit, unsigned int widget_limit,
-               unsigned int guiapp_limit, unsigned int bgapp_limit)
+void lowmem_memory_init(unsigned long long service_limit_bytes, unsigned long long widget_limit_bytes,
+               unsigned long long guiapp_limit_bytes, unsigned long long bgapp_limit_bytes)
 {
-       mem_service_limit = service_limit;
-       mem_widget_limit = widget_limit;
-       mem_guiapp_limit = guiapp_limit;
-       mem_bgapp_limit = bgapp_limit;
+       mem_service_limit_bytes = service_limit_bytes;
+       mem_widget_limit_bytes = widget_limit_bytes;
+       mem_guiapp_limit_bytes = guiapp_limit_bytes;
+       mem_bgapp_limit_bytes = bgapp_limit_bytes;
+
+       _I("[MEMORY-LIMIT] service = %llu bytes, widget = %llu bytes, guiapp = %llu bytes, bgapp = %llu",
+                       mem_service_limit_bytes, mem_widget_limit_bytes, mem_guiapp_limit_bytes, mem_bgapp_limit_bytes);
 }
 
 void lowmem_action_init(int service_action, int widget_action,
@@ -581,9 +607,9 @@ void lowmem_action_init(int service_action, int widget_action,
 void lowmem_limit_init(void)
 {
        int result;
-       unsigned int usage;
+       unsigned long long usage_bytes;
 
-       result = cgroup_read_node_uint32(MEMCG_PATH, MEMCG_SWAP_USAGE, &usage);
+       result = cgroup_read_node_ulonglong(MEMCG_PATH, MEMCG_SWAP_USAGE, &usage_bytes);
        if (result == RESOURCED_ERROR_NONE)
                registerpath = MEMCG_SWAP_USAGE;
        else
@@ -592,14 +618,14 @@ void lowmem_limit_init(void)
        register_notifier(RESOURCED_NOTIFIER_LIMIT_SYSTEM_SERVICE, lowmem_limit_system_service);
        register_notifier(RESOURCED_NOTIFIER_LIMIT_APP, lowmem_limit_app);
 
-       if (mem_service_limit && mem_service_action != PROC_ACTION_IGNORE)
+       if (mem_service_limit_bytes && mem_service_action != PROC_ACTION_IGNORE)
                register_notifier(RESOURCED_NOTIFIER_SERVICE_LAUNCH, lowmem_limit_service);
-       if ((mem_guiapp_limit && mem_guiapp_action != PROC_ACTION_IGNORE) ||
-           (mem_widget_limit && mem_widget_action != PROC_ACTION_IGNORE))
+       if ((mem_guiapp_limit_bytes && mem_guiapp_action != PROC_ACTION_IGNORE) ||
+           (mem_widget_limit_bytes && mem_widget_action != PROC_ACTION_IGNORE))
                register_notifier(RESOURCED_NOTIFIER_APP_LAUNCH, lowmem_limit_appwidget);
-       if (mem_bgapp_limit && mem_bgapp_action != PROC_ACTION_IGNORE) {
-               if (!(mem_guiapp_limit && mem_guiapp_action != PROC_ACTION_IGNORE) ||
-                   !(mem_widget_limit && mem_widget_action != PROC_ACTION_IGNORE)) {
+       if (mem_bgapp_limit_bytes && mem_bgapp_action != PROC_ACTION_IGNORE) {
+               if (!(mem_guiapp_limit_bytes && mem_guiapp_action != PROC_ACTION_IGNORE) ||
+                   !(mem_widget_limit_bytes && mem_widget_action != PROC_ACTION_IGNORE)) {
                        _W("[MEMORY-LIMIT] Background app limit requires that both GUIApp and Widget limits to be set to work properly. Ignoring.");
                } else {
                        register_notifier(RESOURCED_NOTIFIER_APP_BACKGRD, lowmem_limit_bgapp);