#include "proc-main.h"
#include "lowmem-handler.h"
#include "proc-process.h"
+#include "swap-common.h"
#include "lowmem-common.h"
#include "resourced.h"
#include "macro.h"
#include "module.h"
+#include "notifier.h"
enum {
MEMGC_OOM_NORMAL,
+ MEMGC_OOM_SOFTSWAP,
MEMGC_OOM_WARNING,
MEMGC_OOM_HIGH,
MEMGC_OOM_CRITICAL,
MEMGC_GROUP_BACKGROUND,
};
+enum {
+ MEM_SWAP_OFF,
+ MEM_SWAP_ENABLE,
+ MEM_SWAP_DECREASE,
+ MEM_SWAP_INCREASE,
+};
+#define MEM_SOFTSWAP_ENABLE 1
#define MEMCG_GROUP_MAX 2
#define MEMINFO_PATH "/proc/meminfo"
#define _SYS_RES_CLEANUP "RES_CLEANUP"
#define BtoMB(x) ((x) / 1024 / 1024)
+#define MBtoB(x) (x<<20)
#define MEMCG_FOREGROUND_LIMIT_RATIO 0.6
#define MEMCG_BACKGROUND_LIMIT_RATIO 0.7
#define MEMCG_FOREGROUND_MIN_LIMIT MBtoB(400)
#define MEMCG_BACKGROUND_MIN_LIMIT UINT_MAX
+/* threshold lv 1 : wakeup softswapd */
#define MEMCG_TRHES_SOFTSWAP_RATIO 0.75
/* threshold lv 2 : lowmem warning */
0, 0, 0, 0, 0},
};
+static const struct module_ops memory_modules_ops;
+static const struct module_ops *lowmem_ops;
+
+unsigned int get_available(void)
+{
+ char buf[PATH_MAX];
+ FILE *fp;
+ char *idx;
+ unsigned int free = 0, cached = 0;
+ unsigned int available = 0;
+
+ fp = fopen(MEMINFO_PATH, "r");
+ if (!fp) {
+ _E("%s open failed, %d", buf, fp);
+ return available;
+ }
+
+ while (fgets(buf, PATH_MAX, fp) != NULL) {
+ if ((idx = strstr(buf, "MemFree:"))) {
+ idx += strlen("MemFree:");
+ while (*idx < '0' || *idx > '9')
+ idx++;
+ free = atoi(idx);
+ } else if ((idx = strstr(buf, "MemAvailable:"))) {
+ idx += strlen("MemAvailable:");
+ while (*idx < '0' || *idx > '9')
+ idx++;
+ available = atoi(idx);
+ break;
+ } else if((idx = strstr(buf, "Cached:"))) {
+ idx += strlen("Cached:");
+ while (*idx < '0' || *idx > '9')
+ idx++;
+ cached = atoi(idx);
+ break;
+ }
+ }
+
+ if (available == 0)
+ available = free + cached;
+ available >>= 10;
+ fclose(fp);
+
+ return available;
+}
+
+void lowmem_dynamic_process_killer(int type)
+{
+ /* This function is not supported */
+}
+
+void change_memory_state(int state, int force)
+{
+ int mem_state;
+
+ if (force) {
+ mem_state = state;
+ } else {
+ mem_state = cur_mem_state;
+ _D("mem_state = %d", mem_state);
+ }
+
+ switch (mem_state) {
+ case MEMNOTIFY_NORMAL:
+ memory_normal_act(NULL);
+ break;
+ case MEMNOTIFY_RECLAIM:
+ memory_reclaim_act(NULL);
+ break;
+ case MEMNOTIFY_LOW:
+ memory_low_act(NULL);
+ break;
+ case MEMNOTIFY_CRITICAL:
+ memory_oom_act(NULL);
+ break;
+ default:
+ assert(0);
+ }
+}
+
static unsigned int _get_total_memory(void)
{
char buf[PATH_MAX];
f = fopen(SET_THRESHOLD_RECLAIM, "w");
if (!f) {
+ _E("Fail to file open : current kernel can't support swap cgroup");
return RESOURCED_ERROR_FAIL;
}
if (BtoMB(total_size) > MEM_LEAVE_THRESHOLD && oom_score_adj < OOMADJ_BACKGRD_UNLOCKED)
continue;
+ proc_remove_process_list(pid);
kill(pid, SIGKILL);
total_size += pid_size[i];
return NULL;
}
-void lowmem_oom_killer_cb(int memcg_idx)
+int lowmem_oom_killer_cb(int memcg_idx, int flags)
{
int memcg_index = memcg_idx;
_lowmem_oom_killer_cb((void *)&memcg_index);
+ return 0;
}
static void lowmem_cgroup_oom_killer(int memcg_index)
if (i==0)
make_memps_log(MEMPS_LOG_FILE, pid, appname);
+ proc_remove_process_list(pid);
kill(pid, SIGTERM);
total_size += pid_size[i];
convert_to_str(mem_state));
}
+static void lowmem_swap_memory(void)
+{
+ pid_t pid;
+ int swap_type;
+
+ if (cur_mem_state == MEMNOTIFY_NORMAL)
+ return;
+
+ swap_type = swap_status(SWAP_GET_TYPE, NULL);
+
+ if (swap_type == SWAP_ON) {
+ while (1)
+ {
+ pid = (pid_t)swap_status(SWAP_GET_CANDIDATE_PID, NULL);
+ if (!pid)
+ break;
+ _I("swap cgroup entered : pid : %d", (int)pid);
+ resourced_notify(RESOURCED_NOTIFIER_SWAP_MOVE_CGROUP, (void*)&pid);
+ }
+ if (swap_status(SWAP_GET_STATUS, NULL) == SWAP_OFF)
+ resourced_notify(RESOURCED_NOTIFIER_SWAP_RESTART, NULL);
+ resourced_notify(RESOURCED_NOTIFIER_SWAP_START, NULL);
+ }
+}
static int memory_reclaim_act(void *data)
{
if (status != VCONFKEY_SYSMAN_LOW_MEMORY_NORMAL)
vconf_set_int(VCONFKEY_SYSMAN_LOW_MEMORY,
VCONFKEY_SYSMAN_LOW_MEMORY_NORMAL);
+ else
+ lowmem_swap_memory();
+
return 0;
}
print_mem_state();
remove_shm();
-
vconf_set_int(VCONFKEY_SYSMAN_LOW_MEMORY,
VCONFKEY_SYSMAN_LOW_MEMORY_SOFT_WARNING);
memcg_class[i].oomlevel = currentoom;
}
-
return ECORE_CALLBACK_RENEW;
}
return RESOURCED_ERROR_FAIL;
}
- /* threshold lv 1 */
+ /* threshold lv 1 : wakeup softswapd */
/* write event fd about threshold lv1 */
thres = memcg_class[i].thres_lv1;
sz = sprintf(buf, "%d %d %d", evfd, mcgfd, thres);
{
char buf[LOWMEM_PATH_MAX] = {0,};
FILE *f;
- int size;
+ int size, background = 0;
+ unsigned long swap_args[1] = {0,};
if (oom_score_adj > OOMADJ_BACKGRD_LOCKED) {
sprintf(buf, "%s/background/cgroup.procs", MEMCG_PATH);
+ background = 1;
}
else if (oom_score_adj >= OOMADJ_FOREGRD_LOCKED &&
oom_score_adj < OOMADJ_BACKGRD_LOCKED)
else
return;
- _I("buf : %s, pid : %d, oom : %d", buf, pid, oom_score_adj);
- f = fopen(buf, "w");
- if (!f) {
- _E("%s open failed", buf);
- return;
+ swap_args[0] = (unsigned long)pid;
+ if (!swap_status(SWAP_CHECK_PID, swap_args) || !background) {
+ _I("buf : %s, pid : %d, oom : %d", buf, pid, oom_score_adj);
+ f = fopen(buf, "w");
+ if (!f) {
+ _E("%s open failed", buf);
+ return;
+ }
+ size = sprintf(buf, "%d", pid);
+ if (fwrite(buf, size, 1, f) != 1)
+ _E("fwrite cgroup tasks : %d\n", pid);
+ fclose(f);
}
- size = sprintf(buf, "%d", pid);
- if (fwrite(buf, size, 1, f) != 1)
- _E("fwrite cgroup tasks : %d\n", pid);
- fclose(f);
+ if (background)
+ lowmem_swap_memory();
}
static void lowmem_cgroup_foregrd_manage(int currentpid)
int lowmem_init(void)
{
- int ret;
+ int ret = RESOURCED_ERROR_NONE;
/* set default memcg value */
ret = init_memcg();
ecore_main_fd_handler_add(lowmem_fd, ECORE_FD_READ,
(Ecore_Fd_Cb)lowmem_cb, NULL, NULL, NULL);
+ _I("lowmem_swaptype : %d", swap_status(SWAP_GET_TYPE, NULL));
+
lowmem_dbus_init();
return 0;
static int resourced_memory_init(void *data)
{
+ lowmem_ops = &memory_modules_ops;
+
return lowmem_init();
}
return RESOURCED_ERROR_NONE;
}
-static struct module_ops memory_modules_ops = {
+int lowmem_control(enum lowmem_control_type type, unsigned long *args)
+{
+ struct lowmem_data_type l_data;
+
+ if (lowmem_ops) {
+ l_data.control_type = type;
+ l_data.args = args;
+ return lowmem_ops->control(&l_data);
+ }
+
+ return RESOURCED_ERROR_NONE;
+}
+
+static const struct module_ops memory_modules_ops = {
.priority = MODULE_PRIORITY_NORMAL,
.name = "lowmem",
.init = resourced_memory_init,