tizen 2.3 release
[kernel/api/system-resource.git] / src / memory / lowmem-handler.c
index f76bf73..6dd6466 100644 (file)
 #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,
@@ -64,7 +67,14 @@ enum {
        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"
@@ -85,6 +95,7 @@ enum {
 #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
@@ -92,6 +103,7 @@ enum {
 #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 */
@@ -190,6 +202,86 @@ static struct memcg_class memcg_class[MEMCG_GROUP_MAX] = {
                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];
@@ -491,6 +583,7 @@ static int lowmem_set_threshold(void)
        f = fopen(SET_THRESHOLD_RECLAIM, "w");
 
        if (!f) {
+               _E("Fail to file open : current kernel can't support swap cgroup");
                return RESOURCED_ERROR_FAIL;
        }
 
@@ -593,6 +686,7 @@ void *_lowmem_oom_killer_cb(void *data)
                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];
@@ -619,10 +713,11 @@ void *_lowmem_oom_killer_cb(void *data)
        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)
@@ -676,6 +771,7 @@ 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];
@@ -716,6 +812,30 @@ static void print_lowmem_state(unsigned int mem_state)
                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)
 {
@@ -729,6 +849,9 @@ 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;
 }
 
@@ -738,7 +861,6 @@ static int memory_low_act(void *data)
        print_mem_state();
        remove_shm();
 
-
        vconf_set_int(VCONFKEY_SYSMAN_LOW_MEMORY,
                      VCONFKEY_SYSMAN_LOW_MEMORY_SOFT_WARNING);
 
@@ -859,7 +981,6 @@ static Eina_Bool lowmem_cb(void *data, Ecore_Fd_Handler *fd_handler)
                memcg_class[i].oomlevel = currentoom;
        }
 
-
        return ECORE_CALLBACK_RENEW;
 }
 
@@ -905,7 +1026,7 @@ static int setup_eventfd(void)
                        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);
@@ -1046,10 +1167,12 @@ static void lowmem_move_memcgroup(int pid, int oom_score_adj)
 {
        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)
@@ -1057,16 +1180,21 @@ static void lowmem_move_memcgroup(int pid, int oom_score_adj)
        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)
@@ -1154,7 +1282,7 @@ static int lowmem_fd_start(void)
 
 int lowmem_init(void)
 {
-       int ret;
+       int ret = RESOURCED_ERROR_NONE;
 
        /* set default memcg value */
        ret = init_memcg();
@@ -1186,6 +1314,8 @@ int lowmem_init(void)
        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;
@@ -1226,6 +1356,8 @@ static int resourced_memory_control(void *data)
 
 static int resourced_memory_init(void *data)
 {
+       lowmem_ops = &memory_modules_ops;
+
        return lowmem_init();
 }
 
@@ -1234,7 +1366,20 @@ static int resourced_memory_finalize(void *data)
        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,