#include "resourced.h"
#include "trace.h"
#include "file-helper.h"
+#include "procfs.h"
#include <dirent.h>
#include <errno.h>
cgroup->cgroups = NULL;
}*/
+int cgroup_get_type(int oom_score_adj)
+{
+ if (oom_score_adj == OOMADJ_SERVICE_MIN)
+ return CGROUP_VIP;
+ else if (oom_score_adj >= OOMADJ_SU &&
+ oom_score_adj < OOMADJ_BACKGRD_PERCEPTIBLE)
+ return CGROUP_HIGH;
+ else if (oom_score_adj >= OOMADJ_BACKGRD_PERCEPTIBLE &&
+ oom_score_adj < OOMADJ_BACKGRD_UNLOCKED + OOMADJ_APP_INCREASE)
+ return CGROUP_MEDIUM;
+ else if (oom_score_adj >= OOMADJ_BACKGRD_UNLOCKED + OOMADJ_APP_INCREASE &&
+ oom_score_adj <= OOMADJ_APP_MAX)
+ return CGROUP_LOW;
+ else
+ return CGROUP_ROOT;
+}
+
+int cgroup_get_lowest_oom_score_adj(int type)
+{
+ if (type == CGROUP_VIP)
+ return OOMADJ_SERVICE_MIN;
+ else if (type == CGROUP_HIGH)
+ return OOMADJ_SU;
+ else if (type == CGROUP_MEDIUM)
+ return OOMADJ_BACKGRD_PERCEPTIBLE;
+ else if (type == CGROUP_LOW)
+ return OOMADJ_BACKGRD_UNLOCKED + OOMADJ_APP_INCREASE;
+ else
+ return OOMADJ_SU;
+}
+
+int cgroup_get_highest_oom_score_adj(int type)
+{
+ if (type == CGROUP_VIP)
+ return OOMADJ_SERVICE_MIN;
+ else if (type == CGROUP_HIGH)
+ return OOMADJ_FOREGRD_UNLOCKED;
+ else if (type == CGROUP_MEDIUM)
+ return OOMADJ_BACKGRD_UNLOCKED;
+ else
+ return OOMADJ_APP_MAX;
+}
+
struct cgroup *get_cgroup_tree(int idx)
{
if(idx < CGROUP_ROOT || idx >= CGROUP_END) {
- _E("(%d) cgroup tree is NULL", idx);
+ _E("[DEBUG] (%d) cgroup tree is NULL", idx);
return NULL;
}
else
void set_memcg_info(int idx, struct memcg_info *mi)
{
if(idx < CGROUP_ROOT || idx >= CGROUP_END) {
- _E("(%d) index is out of scope", idx);
+ _E("[DEBUG] (%d) index is out of scope", idx);
}
else
cgroup_tree[idx].memcg_info = mi;
struct memcg_info *get_memcg_info(int idx)
{
if(idx < CGROUP_ROOT || idx >= CGROUP_END) {
- _E("(%d) cgroup tree's memcg info is NULL", idx);
+ _E("[DEBUG] (%d) cgroup tree's memcg info is NULL", idx);
return NULL;
}
else
GSList *get_child_cgroups(int idx)
{
if(idx < CGROUP_ROOT || idx >= CGROUP_END) {
- _E("(%d) cgroup tree's child is NULL", idx);
+ _E("[DEBUG] (%d) cgroup tree's child is NULL", idx);
return NULL;
}
else
int get_parent_cgroup(int idx)
{
if(idx < CGROUP_ROOT || idx >= CGROUP_END) {
- _E("(%d) cgroup range is out of scope", idx);
+ _E("[DEBUG] (%d) cgroup range is out of scope", idx);
return CGROUP_TOP;
}
else {
void set_use_hierarchy(int idx, bool use_hierarchy)
{
if(idx < CGROUP_ROOT || idx >= CGROUP_END) {
- _E("(%d) cgroup range is out of scope", idx);
+ _E("[DEBUG] (%d) cgroup range is out of scope", idx);
}
else {
cgroup_tree[idx].use_hierarchy = use_hierarchy;
bool get_use_hierarchy(int idx)
{
if(idx < CGROUP_ROOT || idx >= CGROUP_END) {
- _E("(%d) cgroup range is out of scope", idx);
+ _E("[DEBUG] (%d) cgroup range is out of scope", idx);
return CGROUP_DEFAULT_USE_HIERARCHY;
}
else {
};
/**
+ * @desc Get cgroup type according to oom_score_adj
+ * @param oom_score_adj - oom_score_adj
+ * @return cgroup type
+ */
+int cgroup_get_type(int oom_score_adj);
+
+/**
+ * @desc Get the highest oom_score_adj of the cgroup type
+ * @param type - cgroup type
+ * @return oom_score_adj
+ */
+int cgroup_get_highest_oom_score_adj(int type);
+
+/**
+ * @desc Get the lowest oom_score_adj of the cgroup type
+ * @param type - cgroup type
+ * @return oom_score_adj
+ */
+int cgroup_get_lowest_oom_score_adj(int type);
+
+/**
* @desc Get one unsigned int32 value from cgroup
* @param cgroup_name - cgroup path
* @param file_name - cgroup content to write
struct lowmem_control_data {
enum lowmem_control_type control_type;
- int args[2];
+ int pid;
+ int oom_score_adj;
+ struct proc_app_info *pai;
};
struct cgroup_memory_stat {
{
struct filemap_node *fn = start;
- assert(keylen < FILEMAP_MAX_KEY_LEN - 1);
+ assert(keylen < sizeof (fn->key) - 1);
assert(start);
fn->keylen = keylen;
struct filemap_info *fi = start;
assert(start);
- assert(keylen < FILEMAP_MAX_KEY_LEN - 1);
- assert(valuelen < FILEMAP_MAX_VALUE_LEN - 1);
+ assert(keylen < sizeof (fi->key) - 1);
+ assert(valuelen < sizeof (fi->value) - 1);
fi->keylen = keylen;
strncpy(fi->key, key, keylen + 1);
bool dont_freeze;
};
+int proc_priority_set_fixed_oom(void *data);
int proc_get_freezer_status(void);
struct proc_app_info *find_app_info(const pid_t pid);
#include "swap-common.h"
#include "smaps.h"
#include "notifier.h"
+#include "lowmem-handler.h"
#define MEM_SWAP_RATIO 0.5
return RESOURCED_ERROR_NONE;
}
-int proc_set_oom_score_adj(int pid, int oom_score_adj)
+int proc_set_oom_score_adj(int pid, int oom_score_adj, struct proc_app_info *pai)
{
FILE *fp;
struct lowmem_control_data lowmem_data;
if (oom_score_adj >= OOMADJ_SU) {
lowmem_data.control_type = LOWMEM_MOVE_CGROUP;
- lowmem_data.args[0] = (int)pid;
- lowmem_data.args[1] = (int)oom_score_adj;
+ lowmem_data.pid = pid;
+ lowmem_data.oom_score_adj = oom_score_adj;
+ lowmem_data.pai = pai;
resourced_notify(RESOURCED_NOTIFIER_MEM_CONTROL, &lowmem_data);
}
ret = proc_get_approx_mem_usage(pid, &total);
if (ret < 0) {
- _E("Failed to get usage : %d", pid);
+ _E("[DEBUG] Failed to get usage : %d", pid);
return ret;
}
ret = proc_get_approx_mem_usage(pid, &total);
if (ret < 0) {
- _E("Failed to get usage : %d", pid);
+ _E("[DEBUG] Failed to get usage : %d", pid);
return ret;
}
extern "C" {
#endif /* __cplusplus */
+#include "proc-common.h"
+
#define OOMADJ_SERVICE_MIN (-900)
#define OOMADJ_SU (0)
#define OOMADJ_INIT (100)
* @desc set oom score adj value to /proc/{pid}/oom_score_adj
* @return negative value if error or pid doesn't exist
*/
-int proc_set_oom_score_adj(int pid, int oom_score_adj);
+int proc_set_oom_score_adj(int pid, int oom_score_adj, struct proc_app_info *pai);
/**
* @desc get smack subject label from /proc/{pid}/attr/current
int type = bmi->logging;
if (type & BLOCK_LOGGING_DLOG)
- _I("pid %d(%s) accessed %s", pid, label, filename);
+ _I("[DEBUG] pid %d(%s) accessed %s", pid, label, filename);
if (type & BLOCK_LOGGING_FILE) {
FILE *f;
if (!bmi || !strlen(bmi->path))
return RESOURCED_ERROR_NO_DATA;
- _D("monitor register : path %s, mode %08x", bmi->path, bmi->mode);
+ _D("[DEBUG] monitor register : path %s, mode %08x", bmi->path, bmi->mode);
bmi->mfd = fanotify_init(FAN_CLOEXEC|FAN_NONBLOCK | FAN_CLASS_CONTENT,
O_RDONLY | O_LARGEFILE | O_CLOEXEC | O_NOATIME);
static GHashTable *oom_fixed_app_list;
static GHashTable *oom_fixed_pid_list;
-static int proc_priority_set_fixed_oom(void *data)
+int proc_priority_set_fixed_oom(void *data)
{
int ret;
int *fixed_oom = NULL;
/* Make another hashtable for fast searching during proc_set_oom_score_adj */
if (fixed_oom) {
- ret = proc_set_oom_score_adj(ps->pid, *fixed_oom);
+ ret = proc_set_oom_score_adj(ps->pid, *fixed_oom, ps->pai);
if (ret != RESOURCED_ERROR_NONE) {
_E("Failed to set the fixed oom for %s", ps->pai->appid);
return ret;
config_parse(PRIORITY_CONF_FILE, load_fixed_oom_config, NULL);
- register_notifier(RESOURCED_NOTIFIER_APP_LAUNCH, proc_priority_set_fixed_oom);
+// register_notifier(RESOURCED_NOTIFIER_APP_LAUNCH, proc_priority_set_fixed_oom);
register_notifier(RESOURCED_NOTIFIER_APP_TERMINATED, proc_priority_remove_pid);
return RESOURCED_ERROR_NONE;
}
g_hash_table_destroy(oom_fixed_app_list);
if (oom_fixed_pid_list)
g_hash_table_destroy(oom_fixed_pid_list);
- unregister_notifier(RESOURCED_NOTIFIER_APP_LAUNCH, proc_priority_set_fixed_oom);
+// unregister_notifier(RESOURCED_NOTIFIER_APP_LAUNCH, proc_priority_set_fixed_oom);
unregister_notifier(RESOURCED_NOTIFIER_APP_TERMINATED, proc_priority_remove_pid);
return RESOURCED_ERROR_NONE;
}
return NULL;
}
-resourced_ret_c proc_set_runtime_exclude_list(const int pid, int type)
+resourced_ret_c proc_set_runtime_exclude_list(const int pid, int type, struct proc_app_info *pai)
{
_cleanup_free_ char *runtime_app_info_path = NULL;
- struct proc_app_info *pai = NULL;
+// struct proc_app_info *pai = NULL;
struct proc_status ps = {0};
int ret;
- pai = find_app_info(pid);
- if (!pai)
+// pai = find_app_info(pid);
+ if (!pai) {
+ _E("[DEBUG] process app info is NULL");
return RESOURCED_ERROR_NO_DATA;
+ }
ps.pid = pid;
ps.pai = pai;
} else {
pai->runtime_exclude = type;
}
- _D("pid %d set proc exclude list, type = %d, exclude = %d",
+ _D("[DEBUG] pid %d set proc exclude list, type = %d, exclude = %d",
pid, type, pai->runtime_exclude);
runtime_app_info_path = proc_get_runtime_app_info_path(pai);
}
}
- proc_set_service_oomscore(svc->main_pid, oom_score_adj);
+ proc_set_service_oomscore(svc->main_pid, oom_score_adj, svc);
/* The svc->memory.oom_score_adj should have been updated by the
* subroutine of proc_set_service_oomscore(). But at this stage,
* the proc_app_info of service app is not added to the app list. As a
* result the subroutine cannot update proc_app_info of a service app.
* Therefore, manually update oom_score_adj of service app. */
- retval = proc_get_oom_score_adj(svc->main_pid, &oom_score_adj);
+/* retval = proc_get_oom_score_adj(svc->main_pid, &oom_score_adj);
if (retval == RESOURCED_ERROR_NONE)
- svc->memory.oom_score_adj = oom_score_adj;
+ svc->memory.oom_score_adj = oom_score_adj;*/
}
static struct proc_program_info *proc_add_program_list(const int type,
ppi->app_list = g_slist_prepend(ppi->app_list, pai);
else {
ppi->svc_list = g_slist_prepend(ppi->svc_list, pai);
- if (!restore)
- proc_set_default_svc_oomscore(ppi, pai);
+/* if (!restore)
+ proc_set_default_svc_oomscore(ppi, pai);*/
}
return ppi;
}
prelaunch = NULL;
if (!streq(pai->appid, appid)) {
- _E("prelaunched app(%s) is not matched with new app info(%s)",
+ _E("[DEBUG] prelaunched app(%s) is not matched with new app info(%s)",
pai->appid, appid);
proc_remove_app_info(pai);
} else {
/* prelaunch */
if (prelaunch) {
- _E("prelaunched app was not gone to launch state, appid(%s)", prelaunch->appid);
+ _E("[DEBUG] prelaunched app was not gone to launch state, appid(%s)", prelaunch->appid);
proc_remove_app_info(prelaunch);
prelaunch = NULL;
}
else
pai->starttime = uptime;
}
+ proc_set_process_memory_state(pai, CGROUP_TOP, NULL, -1);
+ pai->memory.use_mem_limit = false;
+ pai->memory.oom_killed = false;
}
return pai;
}
return RESOURCED_ERROR_NONE;
}
+
+
+
int proc_get_freezer_status()
{
int ret = CGROUP_FREEZER_DISABLED;
child_state == PROC_STATE_FOREGROUND) {
owner->lru_state = PROC_FOREGROUND;
ps.pid = owner->main_pid;
- proc_set_oom_score_adj(owner->main_pid, child_oom);
+ proc_set_oom_score_adj(owner->main_pid, child_oom, owner);
} else {
if (owner_oom <= OOMADJ_BACKGRD_LOCKED)
ps.pid = childpid;
- proc_set_oom_score_adj(childpid, owner_oom);
+ proc_set_oom_score_adj(childpid, owner_oom, owner);
}
if (!ps.pid)
return PROC_STATE_DEFAULT;
}
-/*static const char *convert_status_to_str(int status)
+static const char *convert_status_to_str(int status)
{
static const char *set[] = {"foreground", "active", "backround",
"inactive", "launch", "resume", "terminate",
return "error status";
else
return set[status];
-}*/
-
+}
int resourced_proc_status_change(int status, pid_t pid, char *app_name, char *pkg_name, int apptype)
{
ps.pid = pid;
ps.pai = NULL;
- //_E("status: %s, app_name: %s, pid: %d, oom_score: %d", convert_status_to_str(status), app_name, pid, oom_score_adj);
+ _I("[DEBUG] status: %s, app_name: %s, pid: %d, oom_score: %d", convert_status_to_str(status), app_name, pid, oom_score_adj);
switch (status) {
case PROC_CGROUP_SET_FOREGRD:
if (apptype == PROC_TYPE_WIDGET || apptype == PROC_TYPE_WATCH) {
if (!ps.pai)
ps.pai = proc_add_app_info(app_name, pkg_name, pid, 0, 0, apptype, PROC_STATE_FOREGROUND);
- proc_set_oom_score_adj(pid, OOMADJ_FOREGRD_UNLOCKED);
+ proc_set_oom_score_adj(pid, OOMADJ_FOREGRD_UNLOCKED, ps.pai);
resourced_notify(RESOURCED_NOTIFIER_WIDGET_FOREGRD, &ps);
} else {
if (proc_get_freezer_status() != CGROUP_FREEZER_DISABLED &&
resourced_notify(RESOURCED_NOTIFIER_APP_WAKEUP, &ps);
snprintf(pidbuf, sizeof(pidbuf), "%d", pid);
dbus_proc_handler(PREDEF_FOREGRD, pidbuf);
- ret = proc_set_foregrd(pid, oom_score_adj);
+ ret = proc_set_foregrd(pid, oom_score_adj, ps.pai);
if (ret != 0)
return RESOURCED_ERROR_NO_DATA;
if (ps.pai)
if (!ps.pai)
break;
+ proc_priority_set_fixed_oom(&ps);
+
if (apptype == PROC_TYPE_WIDGET)
- proc_set_oom_score_adj(pid, OOMADJ_BACKGRD_LOCKED);
+ proc_set_oom_score_adj(pid, OOMADJ_BACKGRD_LOCKED, ps.pai);
else
- proc_set_oom_score_adj(pid, OOMADJ_INIT);
+ proc_set_oom_score_adj(pid, OOMADJ_INIT, ps.pai);
if (CHECK_BIT(ps.pai->flags, PROC_VIP_ATTRIBUTE))
- proc_set_oom_score_adj(pid, OOMADJ_SU);
+ proc_set_oom_score_adj(pid, OOMADJ_SU, ps.pai);
if (ps.pai->categories)
- proc_set_runtime_exclude_list(pid, PROC_EXCLUDE);
+ proc_set_runtime_exclude_list(pid, PROC_EXCLUDE, ps.pai);
resourced_notify(RESOURCED_NOTIFIER_APP_LAUNCH, &ps);
if (proc_get_freezer_status() == CGROUP_FREEZER_DISABLED)
break;
ps.pai = proc_add_app_info(app_name, pkg_name, pid, 0, 0, apptype, PROC_STATE_FOREGROUND);
if (!ps.pai)
break;
+
+ proc_set_default_svc_oomscore(ps.pai->program, ps.pai);
+
resourced_notify(RESOURCED_NOTIFIER_SERVICE_LAUNCH, &ps);
if (!(CHECK_BIT(ps.pai->flags, PROC_BGCTRL_APP)) ||
ps.pai->categories)
- proc_set_runtime_exclude_list(pid, PROC_EXCLUDE);
+ proc_set_runtime_exclude_list(pid, PROC_EXCLUDE, ps.pai);
break;
case PROC_CGROUP_SET_RESUME_REQUEST:
/* init oom_score_value */
if (!app_name) {
- _E("resume request: need app name! pid = %d", pid);
+ _E("[DEBUG] resume request: need app name! pid = %d", pid);
return RESOURCED_ERROR_NO_DATA;
}
- _SD("resume request: app %s, pid %d", app_name, pid);
+ _SD("[DEBUG] resume request: app %s, pid %d", app_name, pid);
ps.pai = find_app_info(pid);
if (!ps.pai)
ps.pai->lru_state = PROC_ACTIVE;
if (apptype == PROC_TYPE_GUI && oom_score_adj >= OOMADJ_FAVORITE) {
resourced_notify(RESOURCED_NOTIFIER_APP_RESUME, &ps);
- proc_set_oom_score_adj(pid, OOMADJ_INIT);
+ proc_set_oom_score_adj(pid, OOMADJ_INIT, ps.pai);
}
if (proc_get_freezer_status() == CGROUP_FREEZER_DISABLED)
break;
ps.pai = find_app_info(pid);
if (!ps.pai)
ps.pai = proc_add_app_info(app_name, pkg_name, pid, 0, 0, apptype, PROC_STATE_FOREGROUND);
- proc_set_oom_score_adj(pid, OOMADJ_BACKGRD_PERCEPTIBLE);
+ proc_set_oom_score_adj(pid, OOMADJ_BACKGRD_PERCEPTIBLE, ps.pai);
if (apptype == PROC_TYPE_WATCH)
break;
resourced_notify(RESOURCED_NOTIFIER_WIDGET_BACKGRD, &ps);
} else {
snprintf(pidbuf, sizeof(pidbuf), "%d", pid);
dbus_proc_handler(PREDEF_BACKGRD, pidbuf);
- ret = proc_set_backgrd(pid, oom_score_adj);
+ ps.pai = find_app_info(pid);
+ ret = proc_set_backgrd(pid, oom_score_adj, ps.pai);
if (ret != 0)
break;
if (resourced_freezer_proc_late_control())
break;
- ps.pai = find_app_info(pid);
if (!ps.pai)
ps.pai = proc_add_app_info(app_name, pkg_name, pid, 0, 0, apptype, PROC_STATE_BACKGROUND);
ps.pid = pid;
resourced_notify(RESOURCED_NOTIFIER_APP_ACTIVE, &ps);
break;
case PROC_CGROUP_SET_PROC_EXCLUDE_REQUEST:
- proc_set_runtime_exclude_list(pid, PROC_EXCLUDE);
+ proc_set_runtime_exclude_list(pid, PROC_EXCLUDE, find_app_info(pid));
break;
case PROC_CGROUP_SET_TERMINATED:
ps.pai = find_app_info(pid);
break;
case PROC_CGROUP_SET_SYSTEM_SERVICE:
if (oom_score_adj < OOMADJ_BACKGRD_PERCEPTIBLE)
- proc_set_oom_score_adj(pid, OOMADJ_BACKGRD_PERCEPTIBLE);
+ proc_set_oom_score_adj(pid, OOMADJ_BACKGRD_PERCEPTIBLE, NULL);
resourced_notify(RESOURCED_NOTIFIER_SYSTEM_SERVICE, &ps);
break;
default:
void resourced_proc_dump(int type, const char *path);
-resourced_ret_c proc_set_runtime_exclude_list(const int pid, int type);
+resourced_ret_c proc_set_runtime_exclude_list(const int pid, int type, struct proc_app_info *pai);
struct proc_app_info *proc_add_app_info(const char *appid, const char *pkgid, pid_t pid, int flags,
int categories, enum application_type type, enum proc_state state);
pai = find_app_info(pid);
if (!pai) {
- _D("There is no appid %d", pid);
+ _D("[DEBUG] There is no appid %d", pid);
goto response;
}
pai = find_app_info_by_appid(appid);
if (!pai) {
- _E("There is no appid %s", appid);
+ _E("[DEBUG] There is no appid %s", appid);
goto failure;
}
pai = find_app_info_by_appid(appid);
if (!pai || !pai->main_pid) {
- _E("There is no appid %s", appid);
+ _E("[DEBUG] There is no appid %s", appid);
goto failure;
}
pe.pid = pid;
pe.type = PROC_EXCLUDE;
resourced_notify(RESOURCED_NOTIFIER_CONTROL_EXCLUDE, &pe);
- proc_set_runtime_exclude_list(pe.pid, pe.type);
+ proc_set_runtime_exclude_list(pe.pid, pe.type, find_app_info(pe.pid));
} else if (!strncmp(str, "in", 2)) {
pe.pid = pid;
pe.type = PROC_INCLUDE;
resourced_notify(RESOURCED_NOTIFIER_CONTROL_EXCLUDE, &pe);
- proc_set_runtime_exclude_list(pe.pid, pe.type);
+ proc_set_runtime_exclude_list(pe.pid, pe.type, find_app_info(pe.pid));
}
} else
return;
ps.pai = find_app_info_by_appid(appid);
if (!ps.pai) {
- _E("no entry of %s in app list", appid);
+ _E("[DEBUG] no entry of %s in app list", appid);
return;
}
ps.pid = ps.pai->main_pid;
pe.pid = ps.pid;
pe.type = PROC_EXCLUDE;
resourced_notify(RESOURCED_NOTIFIER_CONTROL_EXCLUDE, &pe);
- proc_set_runtime_exclude_list(pe.pid, pe.type);
+ proc_set_runtime_exclude_list(pe.pid, pe.type, ps.pai);
} else if (!strncmp(str, "in", 2)) {
pe.pid = ps.pid;
pe.type = PROC_INCLUDE;
resourced_notify(RESOURCED_NOTIFIER_CONTROL_EXCLUDE, &pe);
- proc_set_runtime_exclude_list(pe.pid, pe.type);
+ proc_set_runtime_exclude_list(pe.pid, pe.type, ps.pai);
}
} else
return;
ret = proc_get_cmdline(pid, appname, sizeof appname);
if (ret != RESOURCED_ERROR_NONE) {
- _E("ERROR : invalid pid(%d)", pid);
+ _E("[DEBUG] ERROR : invalid pid(%d)", pid);
return;
}
return;
if (current_lcd_state == LCD_STATE_OFF) {
- _E("Receive watchdog signal to pid: %d(%s) but don't show ANR popup in LCD off state\n", pid, appname);
+ _E("[DEBUG] Receive watchdog signal to pid: %d(%s) but don't show ANR popup in LCD off state\n", pid, appname);
return;
}
- _E("Receive watchdog signal to app %s, pid %d\n", appname, pid);
+ _E("[DEBUG] Receive watchdog signal to app %s, pid %d\n", appname, pid);
ps.pai = find_app_info(pid);
ps.pid = pid;
resourced_notify(RESOURCED_NOTIFIER_APP_ANR, &ps);
EXPORT_TEST void booting_done_signal_handler(GVariant *params)
{
- _I("booting done");
+ _I("[DEBUG] booting done");
modules_init_late(NULL);
resourced_notify(RESOURCED_NOTIFIER_BOOTING_DONE, NULL);
}
PROC_BACKGROUND_ACTIVE,
};
-int proc_set_service_oomscore(const pid_t pid, const int oom_score)
+int proc_set_service_oomscore(const pid_t pid, const int oom_score, struct proc_app_info *pai)
{
int service_oom;
if (oom_score > 0 && oom_score != OOMADJ_SERVICE_DEFAULT)
service_oom = oom_score - OOMADJ_SERVICE_GAP;
else
service_oom = OOMADJ_SERVICE_DEFAULT;
- return proc_set_oom_score_adj(pid, service_oom);
+ return proc_set_oom_score_adj(pid, service_oom, pai);
}
-static void proc_set_oom_score_childs(GSList *childs, int oom_score_adj)
+static void proc_set_oom_score_childs(struct proc_app_info *pai, int oom_score_adj)
{
GSList *iter;
- if (!childs)
+ if(!pai)
return;
- gslist_for_each_item(iter, childs) {
- proc_set_oom_score_adj(GPOINTER_TO_PID(iter->data), oom_score_adj);
+ if (!pai->childs)
+ return;
+
+ gslist_for_each_item(iter, pai->childs) {
+ proc_set_oom_score_adj(GPOINTER_TO_PID(iter->data), oom_score_adj, pai);
}
}
gslist_for_each_item(iter, svcs) {
struct proc_app_info *svc = (struct proc_app_info *)(iter->data);
svc->state = state;
- proc_set_service_oomscore(svc->main_pid, oom_score_adj);
+ proc_set_service_oomscore(svc->main_pid, oom_score_adj, svc);
}
}
return min_oom_score;
}
-static int proc_backgrd_manage(int currentpid, int active, int oom_score_adj)
+static int proc_backgrd_manage(int currentpid, int active, int oom_score_adj, struct proc_app_info *pai)
{
pid_t pid = -1;
int flag = RESOURCED_NOTIFIER_APP_BACKGRD;
int freeze_val = 0;
GSList *iter;
struct proc_program_info *ppi;
- struct proc_app_info *pai = find_app_info(currentpid);
+// struct proc_app_info *pai = find_app_info(currentpid);
int is_favorite = 0;
if (proc_get_freezer_status() != CGROUP_FREEZER_DISABLED)
freeze_val = resourced_freezer_proc_late_control();
if (!pai) {
- _E("can't find app info about pid %d", currentpid);
+ _E("[DEBUG] can't find app info about pid %d", currentpid);
return RESOURCED_ERROR_INVALID_PARAMETER;
}
new_oom = cur_oom + OOMADJ_FAVORITE_APP_INCREASE;
_D("FAVORITE : process %d set score %d (beford %d)",
pid, new_oom, cur_oom);
- proc_set_oom_score_adj(pid, new_oom);
- proc_set_oom_score_childs(spi->childs, new_oom);
+ proc_set_oom_score_adj(pid, new_oom, spi);
+ proc_set_oom_score_childs(spi, new_oom);
}
} else {
if (spi->lru_state >= PROC_BACKGROUND &&
new_oom = cur_oom + OOMADJ_APP_INCREASE;
_D("BACKGRD : process %d set score %d (before %d)",
pid, new_oom, cur_oom);
- proc_set_oom_score_adj(pid, new_oom);
- proc_set_oom_score_childs(spi->childs, new_oom);
+ proc_set_oom_score_adj(pid, new_oom, spi);
+ proc_set_oom_score_childs(spi, new_oom);
}
}
fclose(fp);
}
set_oom:
- proc_set_oom_score_adj(pai->main_pid, oom_score_adj);
+ proc_set_oom_score_adj(pai->main_pid, oom_score_adj, pai);
/* change oom score about child pids */
- proc_set_oom_score_childs(pai->childs, oom_score_adj);
+ proc_set_oom_score_childs(pai, oom_score_adj);
/* change oom score about grouped service processes */
ppi = pai->program;
return RESOURCED_ERROR_NONE;
}
-static int proc_foregrd_manage(int pid, int oom_score_adj)
+static int proc_foregrd_manage(int pid, int oom_score_adj, struct proc_app_info *pai)
{
int ret = 0;
struct proc_program_info *ppi;
- struct proc_app_info *pai;
+// struct proc_app_info *pai;
- pai = find_app_info(pid);
+// pai = find_app_info(pid);
if (!pai) {
- proc_set_oom_score_adj(pid, oom_score_adj);
+ _E("[DEBUG] process app info is NULL");
+ proc_set_oom_score_adj(pid, oom_score_adj, pai);
return RESOURCED_ERROR_NO_DATA;
}
- proc_set_oom_score_adj(pai->main_pid, oom_score_adj);
+ proc_set_oom_score_adj(pai->main_pid, oom_score_adj, pai);
/* change oom score about child pids */
- proc_set_oom_score_childs(pai->childs, oom_score_adj);
+ proc_set_oom_score_childs(pai, oom_score_adj);
pai->lru_state = PROC_FOREGROUND;
return count;
}
-int proc_set_foregrd(pid_t pid, int oom_score_adj)
+int proc_set_foregrd(pid_t pid, int oom_score_adj, struct proc_app_info *pai)
{
int ret = 0;
break;
case OOMADJ_FOREGRD_LOCKED:
case OOMADJ_BACKGRD_LOCKED:
- ret = proc_foregrd_manage(pid, OOMADJ_FOREGRD_LOCKED);
+ ret = proc_foregrd_manage(pid, OOMADJ_FOREGRD_LOCKED, pai);
break;
case OOMADJ_BACKGRD_UNLOCKED:
case OOMADJ_INIT:
- ret = proc_foregrd_manage(pid, OOMADJ_FOREGRD_UNLOCKED);
+ ret = proc_foregrd_manage(pid, OOMADJ_FOREGRD_UNLOCKED, pai);
break;
default:
if (oom_score_adj > OOMADJ_BACKGRD_UNLOCKED ||
(oom_score_adj >= OOMADJ_FAVORITE &&
oom_score_adj <= OOMADJ_FAVORITE_APP_MAX))
- ret = proc_foregrd_manage(pid, OOMADJ_FOREGRD_UNLOCKED);
+ ret = proc_foregrd_manage(pid, OOMADJ_FOREGRD_UNLOCKED, pai);
else
ret = -1;
break;
return ret;
}
-int proc_set_backgrd(int pid, int oom_score_adj)
+int proc_set_backgrd(int pid, int oom_score_adj, struct proc_app_info *pai)
{
int ret = 0;
ret = -1;
break;
case OOMADJ_FOREGRD_LOCKED:
- ret = proc_backgrd_manage(pid, PROC_BACKGROUND_ACTIVE, OOMADJ_BACKGRD_LOCKED);
+ ret = proc_backgrd_manage(pid, PROC_BACKGROUND_ACTIVE, OOMADJ_BACKGRD_LOCKED, pai);
break;
case OOMADJ_FOREGRD_UNLOCKED:
case OOMADJ_INIT:
- ret = proc_backgrd_manage(pid, PROC_BACKGROUND_INACTIVE, OOMADJ_BACKGRD_UNLOCKED);
+ ret = proc_backgrd_manage(pid, PROC_BACKGROUND_INACTIVE, OOMADJ_BACKGRD_UNLOCKED, pai);
break;
default:
if (oom_score_adj > OOMADJ_BACKGRD_UNLOCKED)
break;
case OOMADJ_INIT:
case OOMADJ_FOREGRD_UNLOCKED:
- ret = proc_set_oom_score_adj(pid, OOMADJ_FOREGRD_LOCKED);
+ ret = proc_set_oom_score_adj(pid, OOMADJ_FOREGRD_LOCKED, find_app_info(pid));
break;
case OOMADJ_BACKGRD_UNLOCKED:
pai = find_app_info(pid);
if (pai)
pai->lru_state = PROC_ACTIVE;
- ret = proc_set_oom_score_adj(pid, OOMADJ_BACKGRD_LOCKED);
+ ret = proc_set_oom_score_adj(pid, OOMADJ_BACKGRD_LOCKED, pai);
break;
case OOMADJ_PREVIOUS_BACKGRD:
- ret = proc_set_oom_score_adj(pid, OOMADJ_PREVIOUS_DEFAULT);
+ ret = proc_set_oom_score_adj(pid, OOMADJ_PREVIOUS_DEFAULT, find_app_info(pid));
break;
default:
if (oom_score_adj > OOMADJ_BACKGRD_UNLOCKED) {
pai = find_app_info(pid);
if (pai)
pai->lru_state = PROC_ACTIVE;
- ret = proc_set_oom_score_adj(pid, OOMADJ_BACKGRD_LOCKED);
+ ret = proc_set_oom_score_adj(pid, OOMADJ_BACKGRD_LOCKED, pai);
} else
ret = -1;
break;
ret = -1;
break;
case OOMADJ_FOREGRD_LOCKED:
- ret = proc_set_oom_score_adj(pid, OOMADJ_FOREGRD_UNLOCKED);
+ ret = proc_set_oom_score_adj(pid, OOMADJ_FOREGRD_UNLOCKED, find_app_info(pid));
break;
case OOMADJ_BACKGRD_LOCKED:
pai = find_app_info(pid);
ps.pid = pid;
ps.pai = pai;
pai->lru_state = PROC_BACKGROUND;
- ret = proc_set_oom_score_adj(pid, OOMADJ_BACKGRD_UNLOCKED);
+ ret = proc_set_oom_score_adj(pid, OOMADJ_BACKGRD_UNLOCKED, pai);
resourced_notify(RESOURCED_NOTIFIER_APP_BACKGRD, &ps);
struct proc_program_info *const ppi = pai->program;
if (ppi && proc_get_svc_state(ppi) == PROC_STATE_BACKGROUND)
extern "C" {
#endif /* __cplusplus */
+#include "proc-common.h"
+
enum proc_sweep_type {
PROC_SWEEP_EXCLUDE_ACTIVE,
PROC_SWEEP_INCLUDE_ACTIVE,
int proc_sweep_memory(enum proc_sweep_type type, pid_t callpid);
-int proc_set_foregrd(int pid, int oom_score_adj);
-int proc_set_backgrd(int pid, int oom_score_adj);
+int proc_set_foregrd(int pid, int oom_score_adj, struct proc_app_info *pai);
+int proc_set_backgrd(int pid, int oom_score_adj, struct proc_app_info *pai);
int proc_set_active(int pid, int oom_score_adj);
int proc_set_inactive(int pid, int oom_score_adj);
-int proc_set_service_oomscore(const pid_t pid, const int oom_score);
+int proc_set_service_oomscore(const pid_t pid, const int oom_score, struct proc_app_info *pai);
#ifdef __cplusplus
}
#include "memory-cgroup.h"
#include "procfs.h"
#include "util.h"
+#include "proc-common.h"
static void lowmem_dbus_oom_set_threshold(GVariant *params)
{
static void lowmem_dbus_oom_trigger(GVariant *params)
{
lowmem_trigger_reclaim(OOM_NOMEMORY_CHECK,
- MAX_MEMORY_CGROUP_VICTIMS, LMK_OLDEST, 0);
+ MAX_MEMORY_CGROUP_VICTIMS, CGROUP_LOW, 0);
}
static void lowmem_dbus_set_perceptible(GVariant *params)
g_variant_get(params, gtype, &pid);
ret_unless(pid > 0);
- proc_set_oom_score_adj(pid, OOMADJ_BACKGRD_PERCEPTIBLE);
+ proc_set_oom_score_adj(pid, OOMADJ_BACKGRD_PERCEPTIBLE, NULL);
}
static void lowmem_dbus_set_platform(GVariant *params)
ret_unless(pid > 0);
ret_unless(limit > 0);
- lowmem_limit_set(pid, limit);
+ lowmem_limit_set(pid, limit, NULL);
}
static const struct d_bus_signal dbus_signals[] = {
#define MAX_MEMORY_CGROUP_VICTIMS 10
-enum lmk_type {
- LMK_MEMORY, /* Kill all range of apps OOMADJ_INIT ~ OOMADJ_APP_MAX */
- LMK_FOREGROUND, /* Kill foreground apps OOMADJ_INIT ~ OOMADJ_BACKGRD_PERCEPTIBLE */
- LMK_ACTIVE, /* Kill active apps OOMADJ_PREVIOUS_DEFAULT ~ OOMADJ_BACKGRD_LOCKED */
- LMK_RECENTLY_USE, /* Kill recently use apps OOMADJ_FAVORITE ~ OOMADJ_RECENTLY_USED */
- LMK_OLDEST/* Kill only oldest inactive processes OOMADJ_BACKGRD_OLD ~ OOMADJ_APP_MAX */
-};
+/*enum lmk_type {
+ LMK_MEMORY, // Kill all range of apps OOMADJ_INIT ~ OOMADJ_APP_MAX
+ LMK_FOREGROUND, // Kill foreground apps OOMADJ_INIT ~ OOMADJ_BACKGRD_PERCEPTIBLE
+ LMK_ACTIVE, // Kill active apps OOMADJ_PREVIOUS_DEFAULT ~ OOMADJ_BACKGRD_LOCKED
+ LMK_RECENTLY_USE, // Kill recently use apps OOMADJ_FAVORITE ~ OOMADJ_RECENTLY_USED
+ LMK_OLDEST// Kill only oldest inactive processes OOMADJ_BACKGRD_OLD ~ OOMADJ_APP_MAX
+};*/
struct task_info {
/*
*/
int oom_score_lru;
int size;
+ struct proc_app_info *pai;
};
/**
*/
void make_memps_log(enum mem_log path, pid_t pid, char *victim_name);
+
void lowmem_dbus_init(void);
-int lowmem_trigger_reclaim(int flags, int victims, enum lmk_type type, int threshold);
-void lowmem_trigger_swap_reclaim(enum lmk_type type, int swap_size);
+int lowmem_trigger_reclaim(int flags, int victims, enum cgroup_type type, int threshold);
+void lowmem_trigger_swap_reclaim(enum cgroup_type type, int swap_size);
void lowmem_change_memory_state(int state, int force);
//void lowmem_memcg_set_threshold(int idx, int level, int value);
//void lowmem_memcg_set_leave_threshold(int idx, int value);
void lowmem_trigger_swap(pid_t pid, int memcg_idx);
void lowmem_limit_init(void);
void lowmem_limit_exit(void);
-void lowmem_limit_set(pid_t pid, unsigned int limit);
+void lowmem_limit_set(pid_t pid, unsigned int limit, struct proc_app_info *pai);
int lowmem_limit_move_cgroup(struct proc_app_info *pai);
void lowmem_reassign_limit(const char *dir, unsigned int limit);
unsigned int lowmem_get_task_mem_usage_rss(const struct task_info *tsk);
exec_cmd(ARRAY_SIZE(argv), argv);
}
- make_memps_log(MEMLOG_MEMPS_MEMLIMIT, mlog->pid, mlog->appname);
+// make_memps_log(MEMLOG_MEMPS_MEMLIMIT, mlog->pid, mlog->appname);
return RESOURCED_ERROR_NONE;
}
return RESOURCED_ERROR_NONE;
}
-void lowmem_limit_set(pid_t pid, unsigned int limit)
+void lowmem_limit_set(pid_t pid, unsigned int limit, struct proc_app_info *pai)
{
char *cgpath, appname[PROC_NAME_MAX];
- struct proc_app_info *pai = NULL;
_cleanup_free_ char *path = NULL;
GSList *iter = NULL;
int ret;
return;
}
- pai = find_app_info(pid);
+ /* If process app info is NULL, try to find out it one more time */
+ if (!pai)
+ pai = find_app_info(pid);
+
if (pai) {
cgpath = pai->appid;
} else {
ret = proc_get_cmdline(pid, appname, sizeof appname);
if (ret < 0) {
- _E("Failed to get cmdline basename of pid(%d)", pid);
+ _E("[DEBUG] Failed to get cmdline basename of pid(%d)", pid);
return;
}
cgpath = appname;
ret = asprintf(&path, "%s/%s", MEMCG_HIGH_PP_PATH, cgpath);
if (ret < 0) {
- _E("not enough memory");
+ _E("[DEBUG] not enough memory");
return;
}
+ _I("[DEBUG] path=%s/%s", MEMCG_HIGH_PP_PATH, cgpath);
+
ret = cgroup_make_subdir(MEMCG_HIGH_PP_PATH, cgpath, NULL);
if (ret < 0) {
- _E("Failed to create cgroup subdir '%s/%s'",
+ _E("[DEBUG] Failed to create cgroup subdir '%s/%s'",
MEMCG_HIGH_PP_PATH, cgpath);
return;
}
lowmem_reassign_limit(path, MBYTE_TO_BYTE(limit));
- ret = cgroup_write_pid_fullpath(path, pid);
- if (ret < 0) {
- return;
- }
-/* ret = cgroup_write_node_uint32(path, CGROUP_FILE_NAME, pid);
- if (ret < 0) {
- _E("Failed to write pid(%d) to '%s/%s'", pid, path, CGROUP_FILE_NAME);
- return;
- }*/
-
ret = cgroup_write_node_uint32(path, MEMCG_MOVE_CHARGE, 3U);
if (ret < 0)
- _W("Failed to set immigrate mode for %s (non-crucial, continuing)", path);
+ _W("[DEBUG] Failed to set immigrate mode for %s (non-crucial, continuing)", path);
- if (!pai)
+ if (!pai) {
+ cgroup_write_pid_fullpath(path, pid);
return;
+ }
pai->memory.use_mem_limit = true;
- if (!pai->childs)
- return;
-
- gslist_for_each_item(iter, pai->childs) {
- pid_t child = GPOINTER_TO_PID(iter->data);
-
- cgroup_write_pid_fullpath(path, child);
-/* ret = cgroup_write_node_uint32(path, CGROUP_FILE_NAME, child);
- if (ret < 0)
- _E("Failed to write pid(%d) to '%s/%s', ignoring for other children",
- child, path, CGROUP_FILE_NAME);*/
+ cgroup_write_pid_fullpath(path, pai->main_pid);
+ if (pai->childs) {
+ gslist_for_each_item(iter, pai->childs)
+ cgroup_write_pid_fullpath(path, GPOINTER_TO_PID(iter->data));
}
}
struct proc_status *ps = (struct proc_status *)data;
- if (mem_service_limit)
- lowmem_limit_set(ps->pid, mem_service_limit);
+ if (mem_service_limit) {
+ lowmem_limit_set(ps->pid, mem_service_limit, ps->pai);
+ }
return RESOURCED_ERROR_NONE;
}
struct proc_status *ps = (struct proc_status *)data;
if (mem_guiapp_limit && ps->pai->type == PROC_TYPE_GUI)
- lowmem_limit_set(ps->pid, mem_guiapp_limit);
+ lowmem_limit_set(ps->pid, mem_guiapp_limit, ps->pai);
if (mem_widget_limit && ps->pai->type == PROC_TYPE_WIDGET)
- lowmem_limit_set(ps->pid, mem_widget_limit);
+ lowmem_limit_set(ps->pid, mem_widget_limit, ps->pai);
return RESOURCED_ERROR_NONE;
}
struct proc_status *ps = (struct proc_status *)data;
- lowmem_limit_set(ps->pid, mem_bgapp_limit);
+ lowmem_limit_set(ps->pid, mem_bgapp_limit, ps->pai);
return RESOURCED_ERROR_NONE;
}
(mem_widget_limit && ps->pai->type == PROC_TYPE_WIDGET))
return lowmem_limit_appwidget(data);
- _E("Unable to set foreground app limit - app type not supported");
+ _E("[DEBUG] Unable to set foreground app limit - app type not supported");
return RESOURCED_ERROR_NONE;
}
/* Processing flags*/
unsigned int flags;
/* Indictator for OOM score of targeted processes */
- enum lmk_type type;
+// enum lmk_type type;
+ enum cgroup_type type;
+
/* Desired size to be restored - level to be reached (MB)*/
unsigned int size;
/* Max number of processes to be considered */
/*-------------------------------------------------*/
/* low memory action function for cgroup */
-static void memory_cgroup_medium_act(enum lmk_type type, struct memcg_info *mi);
+static void memory_cgroup_medium_act(enum cgroup_type type, struct memcg_info *mi);
/* low memory action function */
static void normal_act(void);
static void swap_act(void);
static GPtrArray *vip_apps;
-static const char *convert_type_to_str(int type)
+static const char *convert_cgroup_type_to_str(int type)
+{
+ static const char *type_table[] =
+ {"/", "VIP", "High", "Medium", "Lowest"};
+ if (type >= CGROUP_ROOT && type <= CGROUP_LOW)
+ return type_table[type];
+ else
+ return "Error";
+}
+
+/*static const char *convert_type_to_str(int type)
{
static const char *type_table[] =
{"memory", "foreground", "active", "recently_use", "oldest"};
if(type >= LMK_MEMORY && type <= LMK_OLDEST)
return type_table[type];
return "error type";
-}
+}*/
static const char *convert_status_to_str(int status)
{
// make_memps_log(MEMLOG_MEMPS, pid, appname);
- pai = find_app_info(pid);
+// pai = find_app_info(pid);
+ pai = tsk->pai;
if (pai) {
resourced_proc_status_change(PROC_CGROUP_SET_TERMINATE_REQUEST,
else
safe_kill(pid, SIGKILL);
- _D("we killed, force(%d), %d (%s) score = %d, size: rss = %u, sigterm = %d\n",
+ _D("[LMK] we killed, force(%d), %d (%s) score = %d, size: rss = %u, sigterm = %d\n",
flags & OOM_FORCE, pid, appname, tsk->oom_score_adj,
tsk->size, sigterm);
*victim_size = tsk->size;
return should_be_freed;
}
-static int lowmem_get_pids_proc(GArray *pids, bool add_app)
+//static int lowmem_get_pids_proc(GArray *pids, bool add_app)
+static int lowmem_get_pids_proc(GArray *pids)
{
DIR *dp;
struct dirent *dentry;
continue;
}
+ /* VIP pids should be excluded from the LMK list */
+ if (cgroup_get_type(oom) == CGROUP_VIP)
+ continue;
+
/*
* Check whether this array includes applications or not.
* If it doesn't require to get applications
* and pid has been already included in pai,
* skip to append.
*/
- if (!add_app && find_app_info(pid))
+/* if (!add_app && find_app_info(pid))
+ continue;*/
+ if (oom > OOMADJ_SU && oom <= OOMADJ_APP_MAX)
continue;
/*
tsk.oom_score_lru = oom;
tsk.pids = NULL;
tsk.size = lowmem_get_task_mem_usage_rss(&tsk);
+ tsk.pai = NULL;
g_array_append_val(pids, tsk);
}
ti.pid = pai->main_pid;
ti.pgid = getpgid(ti.pid);
ti.oom_score_adj = oom_score_adj;
+ ti.pai = pai;
/*
* Before oom_score_adj of favourite (oom_score = 270) applications is
* It can find malicious system process even though it has low oom score.
*/
if (start_oom == OOMADJ_SU)
- lowmem_get_pids_proc(candidates, false);
+ //lowmem_get_pids_proc(candidates, false);
+ lowmem_get_pids_proc(candidates);
if (start_oom <= OOMADJ_BACKGRD_LOCKED || start_oom >= OOMADJ_BACKGRD_OLD)
g_array_sort(candidates, (GCompareFunc)compare_victims_point);
if (status != LOWMEM_RECLAIM_CONT)
break;
- _I("[LMK] select victims from proc_app_list pid(%d)\n", tsk->pid);
+ _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)
return victim;
}
-static void calualate_range_of_oom(enum lmk_type lmk, int *min, int *max)
+static int calculate_range_of_oom(enum cgroup_type type, int *min, int *max)
+{
+ if (type == CGROUP_VIP || type >= CGROUP_END || type <= CGROUP_TOP) {
+ _E("[DEBUG] cgroup type (%d) is out of scope", type);
+ return RESOURCED_ERROR_FAIL;
+ }
+
+ *max = cgroup_get_highest_oom_score_adj(type);
+ *min = cgroup_get_lowest_oom_score_adj(type);
+
+ return RESOURCED_ERROR_NONE;
+}
+
+/*static void calualate_range_of_oom(enum lmk_type lmk, int *min, int *max)
{
if (lmk == LMK_OLDEST) {
*max = OOMADJ_APP_MAX;
} else if (lmk == LMK_FOREGROUND) {
*max = OOMADJ_BACKGRD_PERCEPTIBLE;
*min = OOMADJ_SU;
- } else { /* lmk == LMK_MEMORY */
+ } else {
*max = OOMADJ_APP_MAX;
*min = OOMADJ_SU;
}
-}
+}*/
static void lowmem_handle_request(struct lowmem_control *ctl)
{
unsigned int total_size = 0;
unsigned int current_size = 0;
unsigned int reclaim_size, shortfall = 0;
- enum lmk_type lmk_type = ctl->type;
+// enum lmk_type lmk_type = ctl->type;
+ enum cgroup_type cgroup_type = ctl->type;
available = proc_get_mem_available();
reclaim_size = ctl->size > available
retry:
/* Prepare LMK to start doing it's job. Check preconditions. */
- calualate_range_of_oom(lmk_type, &start_oom, &end_oom);
+// calualate_range_of_oom(lmk_type, &start_oom, &end_oom);
+ if (calculate_range_of_oom(cgroup_type, &start_oom, &end_oom))
+ goto done;
+
lmk_start_threshold = get_root_memcg_info()->threshold[LOWMEM_MEDIUM];
shortfall = is_memory_recovered(&available, ctl->size);
goto done;
}
_D("[LMK] before reclaim: available=%uMB, type=%s",
- available, convert_type_to_str(lmk_type));
+ available, convert_cgroup_type_to_str(cgroup_type));
/* precaution */
current_size = 0;
(Make sluggish or kill same victims continuously)
Thus, otherwise, just return in first operation and wait some period.
*/
- if (lmk_type == LMK_OLDEST) {
- //_D("[LMK] Oldest wasn't enough, lets try in RECENTLY USED.");
- lmk_type = LMK_RECENTLY_USE;
+ if (cgroup_type == CGROUP_LOW) {
+ cgroup_type = CGROUP_MEDIUM;
goto retry;
- } else if (lmk_type == LMK_RECENTLY_USE) {
- /* We tried in inactive processes and didn't succed, try immediatly in active */
- //_D("[LMK] Recenlty used wasn't enough, lets try in Active.");
- lmk_type = LMK_ACTIVE;
-
- /*
- * In case of force reclaim, leave threshold is harger than original threshold as margin.
- * So it should be reduced when trying to kill applications in ACTIVE group
- * in order to prevent aggresive killing of perceptible applications.
- */
- if (ctl->flags & OOM_FORCE)
- max_victim_cnt = MAX_PROACTIVE_LOW_VICTIMS;
- goto retry;
- } else if ((lmk_type == LMK_ACTIVE) && (ctl->flags & OOM_IN_DEPTH)) {
- /* We tried in inactive processes and didn't succed, try immediatly in active */
- //_D("[LMK] Recenlty used wasn't enough, lets try in foreground.");
- lmk_type = LMK_FOREGROUND;
+ } else if ((cgroup_type == CGROUP_MEDIUM) && (ctl->flags & OOM_IN_DEPTH)) {
+ cgroup_type = CGROUP_HIGH;
if(ctl->flags & OOM_FORCE)
max_victim_cnt = FOREGROUND_VICTIMS;
goto retry;
- } else if ((lmk_type == LMK_FOREGROUND) && (ctl->flags & OOM_IN_DEPTH)) {
- /*
- * We tried in INACTIVE and ACTIVE but still didn't succeed
- * so it's time to try in /proc. Before doing it wait some time.
- */
+ } else if ((cgroup_type == CGROUP_HIGH) && (ctl->flags & OOM_IN_DEPTH)) {
status = LOWMEM_RECLAIM_RETRY;
- ctl->type = LMK_MEMORY;
- //_D("[LMK] We would need to kill from /proc wait some time and try again");
+ ctl->type = CGROUP_ROOT;
}
- else if (lmk_type == LMK_MEMORY) {
+ else if (cgroup_type == CGROUP_ROOT) {
status = LOWMEM_RECLAIM_RETRY;
}
done:
void lowmem_trigger_swap(pid_t pid, int memcg_idx)
{
+ int error;
+ int oom_score_adj;
+ int lowest_oom_score_adj;
struct memcg_info *mi;
struct swap_status_msg msg;
mi = get_memcg_info(memcg_idx);
// mi = memcg_tree[memcg_idx]->info;
- _D("name : %s, pid : %d", mi->name, pid);
- cgroup_write_pid_fullpath(mi->name, pid);
+ _D("[DEBUG] name : %s, pid : %d", mi->name, pid);
+
+ error = proc_get_oom_score_adj(pid, &oom_score_adj);
+ if (error) {
+ _E("[DEBUG] Cannot get oom_score_adj of pid (%d)", pid);
+ return;
+ }
+
+ lowest_oom_score_adj = cgroup_get_lowest_oom_score_adj(memcg_idx);
+
+ if (oom_score_adj < lowest_oom_score_adj)
+ oom_score_adj = lowest_oom_score_adj;
+
+ proc_set_oom_score_adj(pid, oom_score_adj, NULL);
+
+ //cgroup_write_pid_fullpath(mi->name, pid);
//cgroup_write_node_uint32(mi->name, CGROUP_FILE_NAME, pid);
msg.type = memcg_idx;
msg.memcg_info = mi;
change_lowmem_state(LOWMEM_MEDIUM);
if (available < get_root_memcg_info()->threshold_leave) {
- struct lowmem_control *ctl = LOWMEM_NEW_REQUEST();
+ struct lowmem_control *ctl;
+ ctl = LOWMEM_NEW_REQUEST();
if (ctl) {
LOWMEM_SET_REQUEST(ctl, OOM_IN_DEPTH,
- LMK_OLDEST, get_root_memcg_info()->threshold_leave,
+ CGROUP_LOW, get_root_memcg_info()->threshold_leave,
num_max_victims, medium_cb);
lowmem_queue_request(&lmw, ctl);
}
g_array_free(pids_array, true);
}
-static void memory_cgroup_medium_act(enum lmk_type type, struct memcg_info *mi)
+static void memory_cgroup_medium_act(enum cgroup_type type, struct memcg_info *mi)
{
struct lowmem_control *ctl;
}*/
-
-static void lowmem_move_memcgroup(int pid, int oom_score_adj)
+static void lowmem_move_memcgroup(int pid, int next_oom_score_adj, struct proc_app_info *pai)
{
- struct proc_app_info *pai = find_app_info(pid);
+ int cur_oom_score_adj;
+ int cur_memcg_idx;
struct memcg_info *mi;
- int ret, memcg_idx, should_swap = 0;
+ int next_memcg_idx = cgroup_get_type(next_oom_score_adj);
- if (!pai)
+ if(next_memcg_idx < CGROUP_VIP || next_memcg_idx > CGROUP_LOW) {
+ _E("[DEBUG] cgroup type (%d) should not be called", next_memcg_idx);
return;
+ }
+ mi = get_memcg_info(next_memcg_idx);
- if (oom_score_adj >= OOMADJ_BACKGRD_PERCEPTIBLE &&
- oom_score_adj < OOMADJ_BACKGRD_UNLOCKED) {
- /* We'd like lowmem a chance to do a bit more with some
- * long-lived processes such as background-locked or
- * favourite apps. This is ideally done with a separate
- * memcg because:
- * - Page reclamation in resourced is by design done
- * on a per-cgroup basis, not per-process
- * - The only way to control per-process memory is to
- * abort the individual process, which means LMK.
- * The favourites and most background-locked processes
- * are the final candidates of LMK (ACTIVE or MEMORY)
- * and their memory consumption is most of the time
- * unhandled by resourced.
- * - Bg-locked and fav processes are not even candidates
- * for swap since swap is only available for bg-unlocked
- * processes (the swap module doesn't even care about
- * clean pages as it sets move_charge_at_immigrate=1).
- * - The only remaining practice left for us would be to
- * control the Apps memcg, but that is undesirable since
- * active processes can share it.
- * Therefore, we distinguish between active and background
- * non-unlocked processes to enable optional advanced page
- * management in userspace. A separate memcg won't affect
- * the other aspects of lowmem and swap if there is no set
- * action for it. */
- if (pai->memory.memcg_idx == CGROUP_MEDIUM)
- return;
- memcg_idx = CGROUP_MEDIUM;
-// mi = memcg_tree[memcg_idx]->info;
- mi = get_memcg_info(memcg_idx);
- } else if (oom_score_adj > OOMADJ_BACKGRD_UNLOCKED + OOMADJ_APP_INCREASE) {
- if (oom_score_adj != pai->memory.oom_score_adj)
- proc_set_process_memory_state(pai, pai->memory.memcg_idx,
- pai->memory.memcg_info, oom_score_adj);
- return;
- } else if (oom_score_adj >= OOMADJ_INIT) {
- memcg_idx = CGROUP_HIGH;
-// mi = memcg_tree[memcg_idx]->info;
- mi = get_memcg_info(memcg_idx);
-
- if (oom_score_adj >= OOMADJ_FAVORITE)
- should_swap = 1;
- } else
+ if (!mi) {
return;
+ }
- /*
- * Check whether this application has memory limit cgroup or not.
- * If it is moved to memory limit cgroup,
- * it is no necessary to control memcg any longer.
- * Stop other operation and return.
- */
- if (memcg_idx == CGROUP_HIGH) {
- ret = lowmem_limit_move_cgroup(pai);
- if (!ret) {
-// memcg_idx = MEMCG_LIMIT;
-// mi = memcg_tree[memcg_idx]->info;
- mi = get_memcg_info(memcg_idx);
- proc_set_process_memory_state(pai, memcg_idx, mi, oom_score_adj);
+ if (!pai) {
+ pai = find_app_info(pid);
+ if (!pai) {
+ cgroup_write_pid_fullpath(mi->name, pid);
return;
}
}
- cgroup_write_pid_fullpath(mi->name, pid);
- //cgroup_write_node_uint32(mi->name, CGROUP_FILE_NAME, pid);
- proc_set_process_memory_state(pai, memcg_idx, mi, oom_score_adj);
- /*
- * We should first move process to cgroup and then start reclaim on that
- * cgroup.
- */
- if (should_swap)
-// lowmem_swap_memory(memcg_idx, memcg_tree[memcg_idx]->info);
- lowmem_swap_memory(memcg_idx, mi);
+ /* parent pid */
+ if (pai->main_pid == pid) {
+ cur_oom_score_adj = pai->memory.oom_score_adj;
+ cur_memcg_idx = cgroup_get_type(cur_oom_score_adj);
+
+ /* -1 means that this pid is not yet registered at the memory cgroup
+ * plz, reference proc_create_app_info function
+ */
+ if (cur_oom_score_adj != -1) {
+ /* VIP processes should not be asked to move. */
+ if (cur_memcg_idx <= CGROUP_VIP) {
+ _E("[DEBUG] current cgroup (%s) cannot be VIP or Root", convert_cgroup_type_to_str(cur_memcg_idx));
+ return;
+ }
+ }
+ //DEBUG
+ _I("[DEBUG] app (%s) memory cgroup move from %s to %s", pai->appid, convert_cgroup_type_to_str(cur_memcg_idx), convert_cgroup_type_to_str(next_memcg_idx));
+
+ if (cur_oom_score_adj == next_oom_score_adj) {
+ _D("[DEBUG] next oom_score_adj (%d) is same with current one", next_oom_score_adj);
+ return;
+ }
+
+ proc_set_process_memory_state(pai, next_memcg_idx, mi, next_oom_score_adj);
+
+ if (!lowmem_limit_move_cgroup(pai))
+ return;
+
+ if(cur_memcg_idx == next_memcg_idx)
+ return;
+
+ cgroup_write_pid_fullpath(mi->name, pid);
+ if (next_memcg_idx == CGROUP_LOW)
+ lowmem_swap_memory(next_memcg_idx, mi);
+ }
+ /* child pid */
+ else {
+ if (pai->memory.use_mem_limit)
+ return;
+
+ cgroup_write_pid_fullpath(mi->name, pid);
+ }
}
static int lowmem_activate_worker(void)
prev_available = available;
}
-static void lowmem_press_cgroup_handler(enum lmk_type type, struct memcg_info *mi)
+static void lowmem_press_cgroup_handler(enum cgroup_type type, struct memcg_info *mi)
{
unsigned int usage, threshold;
int ret;
static bool lowmem_press_eventfd_handler(int fd, void *data)
{
- int i;
- struct cgroup *cgroup;
+// struct cgroup *cgroup;
struct memcg_info *mi;
- GSList *iter = NULL;
- enum lmk_type lmk_type = LMK_MEMORY;
+// GSList *iter = NULL;
+ enum cgroup_type type = CGROUP_ROOT;
// FIXME: probably shouldn't get ignored
if (lowmem_press_eventfd_read(fd) < 0)
- _E("Failed to read lowmem press event, %m\n");
+ _E("[DEBUG] Failed to read lowmem press event, %m\n");
- for (i = CGROUP_ROOT; i < CGROUP_END; i++) {
- if (!get_memcg_info(i))
-// if (!memcg_tree[i] || !memcg_tree[i]->info)
- if (!get_cgroup_tree(i) || !get_memcg_info(i))
+ for (type = CGROUP_ROOT; type < CGROUP_END; type++) {
+ if (!get_cgroup_tree(type) || !get_memcg_info(type))
continue;
- mi = get_memcg_info(i);
-// mi = memcg_tree[i]->info;
+ mi = get_memcg_info(type);
if (fd == mi->evfd) {
/* call low memory handler for this memcg */
- if (i == CGROUP_ROOT)
+ if (type == CGROUP_ROOT)
lowmem_press_root_cgroup_handler();
else {
- if (i == CGROUP_HIGH)
- lmk_type = LMK_ACTIVE;
- else if (i == CGROUP_LOW)
- lmk_type = LMK_OLDEST;
- lowmem_press_cgroup_handler(lmk_type, mi);
+ lowmem_press_cgroup_handler(type, mi);
}
return true;
}
- /* ToDo: iterate child memcgs */
// gslist_for_each_item(iter, memcg_tree[i]->cgroups)
- gslist_for_each_item(iter, get_child_cgroups(i))
+/* gslist_for_each_item(iter, get_child_cgroups(type))
{
cgroup = (struct cgroup *)(iter->data);
mi = cgroup->memcg_info;
-// mi = (struct memcg_info *)(iter->data);
if (fd == mi->evfd) {
- if (i == CGROUP_HIGH)
- lmk_type = LMK_ACTIVE;
- else if (i == CGROUP_LOW)
- lmk_type = LMK_OLDEST;
- lowmem_press_cgroup_handler(lmk_type, mi);
- _D("lowmem cgroup handler is called for %s",
+ lowmem_press_cgroup_handler(type, mi);
+ _D("[DEBUG] lowmem cgroup handler is called for %s",
mi->name);
return true;
}
- }
+ }*/
}
return true;
unsigned int i;
for (i = CGROUP_ROOT; i < CGROUP_END; i++) {
-// if (!memcg_tree[i]->use_hierarchy)
if (!get_use_hierarchy(i))
continue;
-// lowmem_press_register_eventfd(memcg_tree[i]->info);
lowmem_press_register_eventfd(get_memcg_info(i));
}
return RESOURCED_ERROR_NONE;
lowmem_change_memory_state(LOWMEM_NORMAL, 0);
}
-int lowmem_trigger_reclaim(int flags, int victims, enum lmk_type type, int threshold)
+int lowmem_trigger_reclaim(int flags, int victims, enum cgroup_type type, int threshold)
{
struct lowmem_control *ctl = LOWMEM_NEW_REQUEST();
flags |= OOM_FORCE | OOM_IN_DEPTH | OOM_SINGLE_SHOT;
victims = victims > 0 ? victims : MAX_MEMORY_CGROUP_VICTIMS;
- type = type > 0 ? type : LMK_OLDEST;
+ type = type > 0 ? type : CGROUP_LOW;
threshold = threshold > 0 ? threshold : get_root_memcg_info()->threshold_leave;
lowmem_change_memory_state(LOWMEM_LOW, 1);
return 0;
}
-void lowmem_trigger_swap_reclaim(enum lmk_type type, int swap_size)
+void lowmem_trigger_swap_reclaim(enum cgroup_type type, int swap_size)
{
int size, victims;
? MAX_PROACTIVE_HIGH_VICTIMS : num_max_victims;
size = get_root_memcg_info()->threshold_leave + BYTE_TO_MBYTE(swap_size);
- _I("reclaim from swap module, type : %d, size : %d, victims: %d", type, size, victims);
+ _I("[DEBUG] reclaim from swap module, type : %d, size : %d, victims: %d", type, size, victims);
lowmem_trigger_reclaim(0, victims, type, size);
}
_D("history based proactive LMK : avg rss %u, available %u required = %u MB",
rss, before, size);
- lowmem_trigger_reclaim(0, victims, LMK_OLDEST, size);
+ //lowmem_trigger_reclaim(0, victims, LMK_OLDEST, size);
+ lowmem_trigger_reclaim(0, victims, CGROUP_LOW, size);
return;
}
*/
_D("Run threshold based proactive LMK: memory level to reach: %u\n",
proactive_leave + THRESHOLD_MARGIN);
- lowmem_trigger_reclaim(0, victims, LMK_OLDEST, proactive_leave + THRESHOLD_MARGIN);
+ //lowmem_trigger_reclaim(0, victims, LMK_OLDEST, proactive_leave + THRESHOLD_MARGIN);
+ lowmem_trigger_reclaim(0, victims, CGROUP_LOW, proactive_leave + THRESHOLD_MARGIN);
}
unsigned int lowmem_get_proactive_thres(void)
return RESOURCED_ERROR_NONE;
}
-static int lowmem_control_handler(void *data)
+int lowmem_control_handler(void *data)
{
struct lowmem_control_data *lowmem_data;
lowmem_data = (struct lowmem_control_data *)data;
switch (lowmem_data->control_type) {
case LOWMEM_MOVE_CGROUP:
- lowmem_move_memcgroup((pid_t)lowmem_data->args[0],
- (int)lowmem_data->args[1]);
+ lowmem_move_memcgroup((pid_t)lowmem_data->pid,
+ lowmem_data->oom_score_adj, lowmem_data->pai);
break;
default:
break;
continue;
if (pid > 0) {
- proc_set_oom_score_adj(pid, OOMADJ_SERVICE_MIN);
+ proc_set_oom_score_adj(pid, OOMADJ_SERVICE_MIN, NULL);
break;
}
}
static int dedup_scanning_once(enum ksm_scan_mode mode)
{
int ret;
- _D("Invoke scanning once to KSM (mode: %d)", mode);
+ _D("[DEDUP] Invoke scanning once to KSM (mode: %d)", mode);
ret = dedup_check_and_scanning_once(mode);
return ret;
}
if (mode != KSM_SCAN_NONE) {
- _I("dedup: %d-th %s deduplication triggering", nr_dedup++,
+ _I("[DEDUP] dedup: %d-th %s deduplication triggering", nr_dedup++,
(mode == KSM_SCAN_FULL ? "FULL" : "PARTIAL"));
if (!dedup_on_lowmem) {
dedup_scanning_once(KSM_SCAN_FULL);
static gboolean dedup_activate_timer_cb(gpointer data)
{
dedup_activating_timer = NULL;
- _D("dedup activating callback called");
+ _D("[DEDUP] dedup activating callback called");
dedup_activate_in_module();
return false;
}
if (dedup_at_boot_enable) {
/* if dedup_at_boot_enable is disabled,
* other daemon should activate dedup */
- _D("dedup booting done is called");
+ _D("[DEDUP] dedup booting done is called");
if (dedup_at_boot_delay > 0)
dedup_activating_timer =
g_timeout_source_new_seconds(dedup_at_boot_delay);
dedup_partial_scan_interval /= 1000;
dedup_full_scan_interval /= 1000;
- _I("deduplication mode: %s", dedup_mode == DEDUP_MODE_PERIODIC ?
+ _I("[DEDUP] deduplication mode: %s", dedup_mode == DEDUP_MODE_PERIODIC ?
"kernel-managed" : "resourced-triggered");
- _I("deduplication on boot: %s", dedup_at_boot_enable ? "true" : "false");
- _I("scanning is invoked by %s", dedup_on_lowmem ?
+ _I("[DEDUP] deduplication on boot: %s", dedup_at_boot_enable ? "true" : "false");
+ _I("[DEDUP] scanning is invoked by %s", dedup_on_lowmem ?
"LOWMEM event" : "periodic timer");
- _I("full scan interval: %d sec", dedup_full_scan_interval);
+ _I("[DEDUP] full scan interval: %d sec", dedup_full_scan_interval);
_I("stat monitoring interval: %d sec", dedup_stat_interval);
- _I("ksm pages to scan: %d", arg_ksm_pages_to_scan);
- _I("ksm sleep time: %d", arg_ksm_sleep);
- _I("ksm full scan interval: %d", arg_ksm_full_scan_interval);
- _I("ksm scan boost: %d", arg_ksm_scan_boost);
+ _I("[DEDUP] ksm pages to scan: %d", arg_ksm_pages_to_scan);
+ _I("[DEDUP] ksm sleep time: %d", arg_ksm_sleep);
+ _I("[DEDUP] ksm full scan interval: %d", arg_ksm_full_scan_interval);
+ _I("[DEDUP] ksm scan boost: %d", arg_ksm_scan_boost);
return 0;
}
* It means that there are many background processes or
* some process makes memory leak.
* So, it requires to trigger proactive oom killer
- * with LMK_MEMORY type.
+ * with CGROUP_ROOT type.
*/
- lowmem_trigger_swap_reclaim(LMK_MEMORY, swap_size);
+ lowmem_trigger_swap_reclaim(CGROUP_ROOT, swap_size);
return -ENOSPC;
}
SWAP_OP_ACTIVATE,
SWAP_OP_RECLAIM,
SWAP_OP_COMPACT,
- SWAP_OP_MOVE_TO_SWAP_AND_RECLAIM,
+// SWAP_OP_MOVE_TO_SWAP_AND_RECLAIM,
SWAP_OP_END,
};
static int swap_move_to_cgroup_by_pid(enum cgroup_type type, pid_t pid)
{
- int ret;
- struct cgroup *cgroup_swap = NULL;
- struct memcg_info *mi;
+ int error;
+ int oom_score_adj;
+ int lowest_oom_score_adj;
struct proc_app_info *pai = find_app_info(pid);
GSList *iter_child = NULL;
- cgroup_swap = get_cgroup_tree((int)type);
- if(!cgroup_swap)
+ error = proc_get_oom_score_adj(pid, &oom_score_adj);
+ if (error) {
+ _E("[DEBUG] Cannot get oom_score_adj of pid (%d)", pid);
return RESOURCED_ERROR_FAIL;
-/* ret = lowmem_get_memcg(type, &memcg_swap);
- if (ret != RESOURCED_ERROR_NONE)
- return RESOURCED_ERROR_FAIL;*/
+ }
+
+ lowest_oom_score_adj = cgroup_get_lowest_oom_score_adj(type);
+
+ if (oom_score_adj < lowest_oom_score_adj)
+ oom_score_adj = lowest_oom_score_adj;
- mi = cgroup_swap->memcg_info;
if (!pai)
+ return proc_set_oom_score_adj(pid, oom_score_adj, pai);
+
+ proc_set_oom_score_adj(pai->main_pid, oom_score_adj, pai);
+
+ if (!pai->childs)
+ return RESOURCED_ERROR_NONE;
+
+ gslist_for_each_item(iter_child, pai->childs) {
+ pid_t child = GPOINTER_TO_PID(iter_child->data);
+ error = proc_set_oom_score_adj(child, oom_score_adj, pai);
+ }
+
+/* if (!pai)
return cgroup_write_pid_fullpath(mi->name, pid);
ret = cgroup_write_pid_fullpath(mi->name, pai->main_pid);
ret = cgroup_write_pid_fullpath(mi->name, child);
}
pai->memory.memcg_idx = CGROUP_LOW;
- pai->memory.memcg_info = mi;
- return ret;
+ pai->memory.memcg_info = mi;*/
+ return error;
}
-static int swap_move_to_cgroup(struct memcg_info *info, GArray *candidates)
+/*static int swap_move_to_cgroup(struct memcg_info *info, GArray *candidates)
{
int index;
+ int error = RESOURCED_ERROR_NONE;
+ int oom_score_adj;
+ int lowest_oom_score_adj;
struct swap_task tsk;
struct proc_app_info *pai = NULL;
GSList *iter_child = NULL;
for (index = 0; index < candidates->len; index++) {
tsk = g_array_index(candidates, struct swap_task, index);
pai = tsk.pai;
- cgroup_write_pid_fullpath(info->name, pai->main_pid);
+
+ if (!pai) {
+ _E("[DEBUG] Cannot find out proc_app_info");
+ continue;
+ }
+
+ error = proc_get_oom_score_adj(pai->main_pid, &oom_score_adj);
+ if (error) {
+ _E("[DEBUG] Cannot get oom_score_adj of pid (%d)", pai->main_pid);
+ continue;
+ }
+
+ lowest_oom_score_adj = cgroup_get_lowest_oom_score_adj(CGROUP_LOW);
+
+ if (oom_score_adj < lowest_oom_score_adj)
+ oom_score_adj = lowest_oom_score_adj;
+
+ proc_set_oom_score_adj(pai->main_pid, oom_score_adj, pai);
+ if (!pai->childs)
+ continue;
+
gslist_for_each_item(iter_child, pai->childs) {
pid_t child = GPOINTER_TO_PID(iter_child->data);
- cgroup_write_pid_fullpath(info->name, child);
+ error = proc_set_oom_score_adj(child, oom_score_adj, pai);
}
- pai->memory.memcg_idx = CGROUP_LOW;
- pai->memory.memcg_info = info;
}
- return RESOURCED_ERROR_NONE;
-}
+ return error;
+}*/
-static int swap_sort_by_oom(const struct swap_task *ta,
+/*static int swap_sort_by_oom(const struct swap_task *ta,
const struct swap_task *tb)
{
- /* sort by oom score adj */
+ // sort by oom score adj
assert(ta != NULL);
assert(tb != NULL);
return ((int)(tb->pai->memory.oom_score_adj) -
(int)(ta->pai->memory.oom_score_adj));
-}
+}*/
-static int swap_sort_by_vmrss(const struct swap_task *ta,
+/*static int swap_sort_by_vmrss(const struct swap_task *ta,
const struct swap_task *tb)
{
- /* sort by task memory usage */
+ // sort by task memory usage
assert(ta != NULL);
assert(tb != NULL);
return ((int)(tb->size) - (int)(ta->size));
-}
+}*/
-static int swap_reduce_victims(GArray *candidates, int max)
+/*static int swap_reduce_victims(GArray *candidates, int max)
{
int index;
struct swap_task tsk;
tsk = g_array_index(candidates, struct swap_task, index);
pai = tsk.pai;
- /* Measuring VmRSS is OK as it's anonymous + swapcache */
+ // Measuring VmRSS is OK as it's anonymous + swapcache
if (proc_get_approx_mem_usage(pai->main_pid, &usage) < 0)
continue;
}
}
}
- /* sort by oom_score_adj value, older are better candidates */
+ // sort by oom_score_adj value, older are better candidates
g_array_sort(candidates, (GCompareFunc)swap_sort_by_oom);
- /* sort by memory usage, swapping bigger will free more memory */
+ // sort by memory usage, swapping bigger will free more memory
g_array_sort(candidates, (GCompareFunc)swap_sort_by_vmrss);
- /* limit the number of potential candidates, after sort by oom */
+ // limit the number of potential candidates, after sort by oom
g_array_remove_range(candidates, max, candidates->len - max);
return RESOURCED_ERROR_NONE;
-}
+}*/
static int swap_use_hard_limit(char *memcg)
{
return swap_start_reclaim(info->name);
}
-static int swap_move_inactive_to_swap(struct swap_status_msg *msg)
+/*static int swap_move_inactive_to_swap(struct swap_status_msg *msg)
{
GSList *proc_app_list = NULL;
GSList *iter;
int ret, max_victims;
struct swap_task victim;
GArray *candidates = NULL;
-// struct memcg *memcg_swap = NULL;
struct cgroup *cgroup_swap = NULL;
struct proc_app_info *pai = NULL;
victim.pai = pai;
g_array_append_val(candidates, victim);
}
- /*
- * Let's consider 50% of inactive apps to be swappable at once.
- */
max_victims = candidates->len >> 1;
if (max_victims == 0) {
ret = RESOURCED_ERROR_NO_DATA;
cgroup_swap = get_cgroup_tree(CGROUP_LOW);
if(!cgroup_swap)
goto out;
-/* ret = lowmem_get_memcg(CGROUP_LOW, &memcg_swap);
- if (ret != RESOURCED_ERROR_NONE)
- goto out;*/
- /*
- * change swap info from inactive cgroup to swap group
- * for using same structure to move and swap it
- */
+
msg->memcg_info = cgroup_swap->memcg_info;
msg->type = CGROUP_LOW;
ret = swap_move_to_cgroup(msg->memcg_info, candidates);
g_array_free(candidates, TRUE);
return ret;
-}
+}*/
static int gen_urandom_string(char *buf, size_t len)
{
static void *swap_thread_main(void * data)
{
- int is_empty, ret;
+ int is_empty;
struct swap_thread_bundle *bundle;
setpriority(PRIO_PROCESS, 0, SWAP_PRIORITY);
swap_compact_in_module();
break;
/* Move inactive procesess to swap, and reclaim after that. */
- case SWAP_OP_MOVE_TO_SWAP_AND_RECLAIM:
+/* case SWAP_OP_MOVE_TO_SWAP_AND_RECLAIM:
ret = swap_move_inactive_to_swap(&(bundle->msg));
- /* Check if any process was moved to swap. */
if (ret == RESOURCED_ERROR_NONE)
swap_reclaim_memcg(bundle->msg);
- break;
+ break;*/
case SWAP_OP_END:
default:
_D("wrong swap thread operation selected");
return RESOURCED_ERROR_NONE;
}
- _E("pthread_mutex_trylock fail: %d, errno: %d", ret, errno);
+ _E("[DEBUG] pthread_mutex_trylock fail: %d, errno: %d", ret, errno);
return RESOURCED_ERROR_FAIL;
}
bundle->op = SWAP_OP_RECLAIM;
memcpy(&(bundle->msg), data, sizeof(struct swap_status_msg));
- if (bundle->msg.type == CGROUP_HIGH) {
- /*
- * Background tasks are concerned special way, we select
- * tasks and move them to Swap cgroup. They are not there already.
- */
- bundle->op = SWAP_OP_MOVE_TO_SWAP_AND_RECLAIM;
+ if (bundle->msg.type <= CGROUP_HIGH) {
+ _E("[DEBUG] swap op should be done on CGROUP Medium or Lowest");
+ return RESOURCED_ERROR_FAIL;
}
ret = swap_communicate_thread(bundle);
return ret;
*/
if (lowmem_fragmentated()) {
if (zram_compact) {
- lowmem_trigger_swap_reclaim(LMK_MEMORY, zram_control.zram_reclaim_bytes);
+ lowmem_trigger_swap_reclaim(CGROUP_ROOT, zram_control.zram_reclaim_bytes);
zram_compact = false;
} else {
swap_zram_compact();
if (!swap_total)
swap_total = proc_get_swap_total();
- r = memcg_get_swap_usage(MEMCG_LOW_PATH, &swap_usage);
+ r = memcg_get_swap_usage(MEMCG_LOW_GROUP_PATH, &swap_usage);
if (r)
return r;
swapcg_usage_ratio = (float)(swap_usage / (swap_total - swap_available) *100);
if (swapcg_usage_ratio > SWAPCG_CHECK_RATIO)
- type = LMK_OLDEST;
+ type = CGROUP_LOW;
else
- type = LMK_MEMORY;
+ type = CGROUP_ROOT;
lowmem_trigger_swap_reclaim(type, zram_control.zram_reclaim_bytes);
zram_compact = false;
* So, it requires to trigger proactive oom killer.
*/
- lowmem_trigger_swap_reclaim(LMK_MEMORY, swap_size);
+ lowmem_trigger_swap_reclaim(CGROUP_ROOT, swap_size);
return -ENOSPC;
}
check_expected_ptr(data);
}
-resourced_ret_c __wrap_proc_set_runtime_exclude_list(const int pid, int type)
+resourced_ret_c __wrap_proc_set_runtime_exclude_list(const int pid, int type, struct proc_app_info *pai)
{
check_expected(pid);
check_expected(type);
+ check_expected(pai);
return mock_type(resourced_ret_c);
}
expect_value(__wrap_proc_set_runtime_exclude_list, pid, pe.pid);
expect_value(__wrap_proc_set_runtime_exclude_list, type, pe.type);
+ expect_value(__wrap_proc_set_runtime_exclude_list, pai, &pai);
will_return(__wrap_proc_set_runtime_exclude_list, RESOURCED_ERROR_NONE);
proc_dbus_exclude_appid_signal_handler(params);
g_variant_unref(params);
expect_value(__wrap_proc_set_runtime_exclude_list, pid, pe.pid);
expect_value(__wrap_proc_set_runtime_exclude_list, type, pe.type);
+ expect_value(__wrap_proc_set_runtime_exclude_list, pai, &pai);
will_return(__wrap_proc_set_runtime_exclude_list, RESOURCED_ERROR_NONE);
proc_dbus_exclude_appid_signal_handler(params);
g_variant_unref(params);
expect_value(__wrap_proc_set_runtime_exclude_list, pid, pe.pid);
expect_value(__wrap_proc_set_runtime_exclude_list, type, pe.type);
+ expect_value(__wrap_proc_set_runtime_exclude_list, pai, &pai);
will_return(__wrap_proc_set_runtime_exclude_list, RESOURCED_ERROR_NONE);
proc_dbus_exclude_appid_signal_handler(params);
expect_value(__wrap_proc_set_runtime_exclude_list, pid, pe.pid);
expect_value(__wrap_proc_set_runtime_exclude_list, type, pe.type);
+ expect_value(__wrap_proc_set_runtime_exclude_list, pai, &pai);
will_return(__wrap_proc_set_runtime_exclude_list, RESOURCED_ERROR_NONE);
proc_dbus_exclude_appid_signal_handler(params);
static void test_proc_dbus_exclude_signal_handler(void **state)
{
(void) state; /*unused*/
+ struct proc_app_info pai = {};
GVariant *params = g_variant_new("(si)", NULL, 0);
__real_proc_dbus_exclude_signal_handler(params);
expect_value(__wrap_resourced_notify, status, RESOURCED_NOTIFIER_CONTROL_EXCLUDE);
expect_check(__wrap_resourced_notify, data, check_data_in_resourced_notify_exclude, &((struct proc_exclude){.pid = 1416, .type = PROC_EXCLUDE}));
+
+ expect_value(__wrap_find_app_info, pid, 1416);
+ will_return(__wrap_find_app_info, &pai);
+
expect_value(__wrap_proc_set_runtime_exclude_list, pid, 1416);
expect_value(__wrap_proc_set_runtime_exclude_list, type, PROC_EXCLUDE);
+ expect_value(__wrap_proc_set_runtime_exclude_list, pai, &pai);
will_return(__wrap_proc_set_runtime_exclude_list, RESOURCED_ERROR_NONE);
__real_proc_dbus_exclude_signal_handler(params);
expect_value(__wrap_resourced_notify, status, RESOURCED_NOTIFIER_CONTROL_EXCLUDE);
expect_memory(__wrap_resourced_notify, data, &((struct proc_exclude){.pid = 3213, .type = PROC_INCLUDE}), sizeof(struct proc_exclude));
+ expect_value(__wrap_find_app_info, pid, 3213);
+ will_return(__wrap_find_app_info, &pai);
+
+
expect_value(__wrap_proc_set_runtime_exclude_list, pid, 3213);
expect_value(__wrap_proc_set_runtime_exclude_list, type, PROC_INCLUDE);
+ expect_value(__wrap_proc_set_runtime_exclude_list, pai, &pai);
will_return(__wrap_proc_set_runtime_exclude_list, RESOURCED_ERROR_NONE);
__real_proc_dbus_exclude_signal_handler(params);
check_expected(value);
}
-int LowmemDbusEnv::lowmem_trigger_reclaim(int flags, int victims, enum lmk_type type, int threshold)
+int LowmemDbusEnv::lowmem_trigger_reclaim(int flags, int victims, enum cgroup_type type, int threshold)
{
check_expected(flags);
check_expected(victims);
check_expected(memcg_idx);
}
-void LowmemDbusEnv::lowmem_limit_set(pid_t pid, unsigned int limit)
+void LowmemDbusEnv::lowmem_limit_set(pid_t pid, unsigned int limit, struct proc_app_info *pai)
{
check_expected(pid);
check_expected(limit);
+ check_expected(pai);
}
void LowmemDbusEnv::trigger_signal_oom_set_threshold(GVariant *gv)
void memcg_set_threshold(int type, int level, int value);
void memcg_set_leave_threshold(int type, int value);
- int lowmem_trigger_reclaim(int flags, int victims, enum lmk_type type, int threshold);
+ int lowmem_trigger_reclaim(int flags, int victims, enum cgroup_type type, int threshold);
int proc_set_oom_score_adj(int pid, int oom_score_adj);
void lowmem_trigger_swap(pid_t pid, int memcg_idx);
- void lowmem_limit_set(pid_t pid, unsigned int limit);
+ void lowmem_limit_set(pid_t pid, unsigned int limit, struct proc_app_info *pai);
// events
void trigger_signal_oom_set_threshold(GVariant *gv);
MOCK_DBUS(void, memcg_set_threshold, (int type, int level, int value), (type, level, value))
MOCK_DBUS(void, memcg_set_leave_threshold, (int type, int value), (type, value))
-MOCK_DBUS(int, lowmem_trigger_reclaim, (int flags, int victims, enum lmk_type type, int threshold),
+MOCK_DBUS(int, lowmem_trigger_reclaim, (int flags, int victims, enum cgroup_type type, int threshold),
(flags, victims, type, threshold))
MOCK_DBUS(int, proc_set_oom_score_adj, (int pid, int oom_score_adj), (pid, oom_score_adj))
MOCK_DBUS(void, lowmem_trigger_swap, (pid_t pid, int memcg_idx), (pid, memcg_idx))
-MOCK_DBUS(void, lowmem_limit_set, (pid_t pid, unsigned int limit), (pid, limit))
+MOCK_DBUS(void, lowmem_limit_set, (pid_t pid, unsigned int limit, struct proc_app_info *pai),
+ (pid, limit, pai))
{
expect_value(lowmem_trigger_reclaim, flags, OOM_NOMEMORY_CHECK);
expect_value(lowmem_trigger_reclaim, victims, MAX_MEMORY_CGROUP_VICTIMS);
- expect_value(lowmem_trigger_reclaim, type, LMK_OLDEST);
+ expect_value(lowmem_trigger_reclaim, type, CGROUP_LOW);
expect_value(lowmem_trigger_reclaim, threshold, 0);
env.trigger_signal_oom_trigger(g_variant_new("()"));
if (pid > 0 && limit > 0) {
expect_value(lowmem_limit_set, pid, pid);
expect_value(lowmem_limit_set, limit, limit);
+ expect_value(lowmem_limit_set, pai, NULL);
}
env.trigger_signal_oom_set_memlimit(g_variant_new("(iu)", pid, limit));