Add unit(in variable) & fix bugs
[platform/core/system/resourced.git] / src / resource-limiter / memory / vmpressure-lowmem-handler.c
1 /*
2  * resourced
3  *
4  * Copyright (c) 2012 - 2019 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 /*
20  * @file vmpressure-lowmem-handler.c
21  *
22  * @desc lowmem handler using memcgroup
23  *
24  * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
25  *
26  */
27
28 #include <stdio.h>
29 #include <fcntl.h>
30 #include <assert.h>
31 #include <limits.h>
32 #include <vconf.h>
33 #include <unistd.h>
34 #include <time.h>
35 #include <limits.h>
36 #include <dirent.h>
37 #include <sys/time.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <sys/shm.h>
41 #include <sys/sysinfo.h>
42 #include <sys/time.h>
43 #include <sys/resource.h>
44 #include <ctype.h>
45 #include <bundle.h>
46 #include <eventsystem.h>
47 #include <malloc.h>
48
49 #include "trace.h"
50 #include "cgroup.h"
51 #include "lowmem-handler.h"
52 #include "proc-common.h"
53 #include "procfs.h"
54 #include "freezer.h"
55 #include "resourced.h"
56 #include "macro.h"
57 #include "notifier.h"
58 #include "config-parser.h"
59 #include "module.h"
60 #include "swap-common.h"
61 #include "cgroup.h"
62 #include "memory-cgroup.h"
63 #include "heart-common.h"
64 #include "proc-main.h"
65 #include "dbus-handler.h"
66 #include "util.h"
67 #include "fd-handler.h"
68 #include "resourced-helper-worker.h"
69 #include "safe-kill.h"
70 #include "dedup-common.h"
71
72 #define LOWMEM_THRES_INIT               0
73
74 #define MEMPS_EXEC_PATH                 "usr/bin/memps"
75 #define MEM_CONF_FILE                   RD_CONFIG_FILE(limiter)
76 #define MEM_SECTION             "Memory"
77 #define MEM_VIP_SECTION                 "VIP_PROCESS"
78 #define MEM_VIP_PREDEFINE               "PREDEFINE"
79 #define MEM_POPUP_SECTION               "POPUP"
80 #define MEM_POPUP_STRING                "oom_popup"
81 #define MEM_BG_RECLAIM_SECTION  "BackgroundReclaim"
82 #define MEM_BG_RECLAIM_STRING   "AfterScreenDim"
83 #define MEM_LOGGING_SECTION             "Logging"
84
85 #define BUF_MAX                         1024
86 #define MAX_VICTIMS_BETWEEN_CHECK       3
87 #define MAX_PROACTIVE_LOW_VICTIMS       2
88 #define MAX_PROACTIVE_HIGH_VICTIMS      4
89 #define FOREGROUND_VICTIMS              1
90 #define OOM_TIMER_INTERVAL              2
91 #define OOM_KILLER_PRIORITY             -20
92 #define THRESHOLD_MARGIN                10 /* MB */
93
94 #define MEM_SIZE_64                     64  /* MB */
95 #define MEM_SIZE_256                    256 /* MB */
96 #define MEM_SIZE_448                    448 /* MB */
97 #define MEM_SIZE_512                    512 /* MB */
98 #define MEM_SIZE_768                    768 /* MB */
99 #define MEM_SIZE_1024                   1024 /* MB */
100 #define MEM_SIZE_2048                   2048 /* MB */
101
102 /* thresholds for 64M RAM*/
103 #define PROACTIVE_64_THRES                      10 /* MB */
104 #define PROACTIVE_64_LEAVE                      30 /* MB */
105 #define CGROUP_ROOT_64_THRES_DEDUP              16 /* MB */
106 #define CGROUP_ROOT_64_THRES_SWAP               15 /* MB */
107 #define CGROUP_ROOT_64_THRES_LOW                8  /* MB */
108 #define CGROUP_ROOT_64_THRES_MEDIUM             5  /* MB */
109 #define CGROUP_ROOT_64_THRES_LEAVE              8  /* MB */
110 #define CGROUP_ROOT_64_NUM_VICTIMS              1
111
112 /* thresholds for 256M RAM */
113 #define PROACTIVE_256_THRES                     50 /* MB */
114 #define PROACTIVE_256_LEAVE                     80 /* MB */
115 #define CGROUP_ROOT_256_THRES_DEDUP     60 /* MB */
116 #define CGROUP_ROOT_256_THRES_SWAP              40 /* MB */
117 #define CGROUP_ROOT_256_THRES_LOW               20 /* MB */
118 #define CGROUP_ROOT_256_THRES_MEDIUM            10 /* MB */
119 #define CGROUP_ROOT_256_THRES_LEAVE             20 /* MB */
120 #define CGROUP_ROOT_256_NUM_VICTIMS             2
121
122 /* threshold for 448M RAM */
123 #define PROACTIVE_448_THRES                     80 /* MB */
124 #define PROACTIVE_448_LEAVE                     100 /* MB */
125 #define CGROUP_ROOT_448_THRES_DEDUP     120 /* MB */
126 #define CGROUP_ROOT_448_THRES_SWAP              100 /* MB */
127 #define CGROUP_ROOT_448_THRES_LOW               60  /* MB */
128 #define CGROUP_ROOT_448_THRES_MEDIUM            50  /* MB */
129 #define CGROUP_ROOT_448_THRES_LEAVE             70  /* MB */
130 #define CGROUP_ROOT_448_NUM_VICTIMS             5
131
132 /* threshold for 512M RAM */
133 #define PROACTIVE_512_THRES                     100 /* MB */
134 #define PROACTIVE_512_LEAVE                     80 /* MB */
135 #define CGROUP_ROOT_512_THRES_DEDUP     140 /* MB */
136 #define CGROUP_ROOT_512_THRES_SWAP              100 /* MB */
137 #define CGROUP_ROOT_512_THRES_LOW               70  /* MB */
138 #define CGROUP_ROOT_512_THRES_MEDIUM            60  /* MB */
139 #define CGROUP_ROOT_512_THRES_LEAVE             80  /* MB */
140 #define CGROUP_ROOT_512_NUM_VICTIMS             5
141
142 /* threshold for 768 RAM */
143 #define PROACTIVE_768_THRES                     100 /* MB */
144 #define PROACTIVE_768_LEAVE                     130 /* MB */
145 #define CGROUP_ROOT_768_THRES_DEDUP     180 /* MB */
146 #define CGROUP_ROOT_768_THRES_SWAP              150 /* MB */
147 #define CGROUP_ROOT_768_THRES_LOW               90  /* MB */
148 #define CGROUP_ROOT_768_THRES_MEDIUM            80  /* MB */
149 #define CGROUP_ROOT_768_THRES_LEAVE             100  /* MB */
150 #define CGROUP_ROOT_768_NUM_VICTIMS             5
151
152 /* threshold for more than 1024M RAM */
153 #define PROACTIVE_1024_THRES                    230 /* MB */
154 #define PROACTIVE_1024_LEAVE                    150 /* MB */
155 #define CGROUP_ROOT_1024_THRES_DEDUP            400 /* MB */
156 #define CGROUP_ROOT_1024_THRES_SWAP             300 /* MB */
157 #define CGROUP_ROOT_1024_THRES_LOW              120 /* MB */
158 #define CGROUP_ROOT_1024_THRES_MEDIUM           100 /* MB */
159 #define CGROUP_ROOT_1024_THRES_LEAVE            150 /* MB */
160 #define CGROUP_ROOT_1024_NUM_VICTIMS            5
161
162 /* threshold for more than 2048M RAM */
163 #define PROACTIVE_2048_THRES                    200 /* MB */
164 #define PROACTIVE_2048_LEAVE                    500 /* MB */
165 #define CGROUP_ROOT_2048_THRES_DEDUP            400 /* MB */
166 #define CGROUP_ROOT_2048_THRES_SWAP             300 /* MB */
167 #define CGROUP_ROOT_2048_THRES_LOW              200 /* MB */
168 #define CGROUP_ROOT_2048_THRES_MEDIUM           160 /* MB */
169 #define CGROUP_ROOT_2048_THRES_LEAVE            300 /* MB */
170 #define CGROUP_ROOT_2048_NUM_VICTIMS            10
171
172 /* threshold for more than 3072M RAM */
173 #define PROACTIVE_3072_THRES                    300 /* MB */
174 #define PROACTIVE_3072_LEAVE                    700 /* MB */
175 #define CGROUP_ROOT_3072_THRES_DEDUP            600 /* MB */
176 #define CGROUP_ROOT_3072_THRES_SWAP             500 /* MB */
177 #define CGROUP_ROOT_3072_THRES_LOW              400 /* MB */
178 #define CGROUP_ROOT_3072_THRES_MEDIUM           250 /* MB */
179 #define CGROUP_ROOT_3072_THRES_LEAVE            500 /* MB */
180 #define CGROUP_ROOT_3072_NUM_VICTIMS            10
181
182 static unsigned proactive_threshold_mb;
183 static unsigned proactive_leave_mb;
184 static unsigned lmk_start_threshold_mb;
185
186 static char *event_level = MEMCG_DEFAULT_EVENT_LEVEL;
187
188 /**
189  * Resourced Low Memory Killer
190  * NOTE: planned to be moved to a separate file.
191  */
192 /*-------------------------------------------------*/
193 #define OOM_TIMER_INTERVAL_SEC  2
194 #define LMW_LOOP_WAIT_TIMEOUT_MSEC      OOM_TIMER_INTERVAL_SEC*(G_USEC_PER_SEC)
195 #define LMW_RETRY_WAIT_TIMEOUT_MSEC     (G_USEC_PER_SEC)
196
197 struct lowmem_control {
198         /*
199          * For each queued request the following properties
200          * are required with two exceptions:
201          *  - status is being set by LMK
202          *  - callback is optional
203          */
204         /* Processing flags*/
205         unsigned int flags;
206         /* Indictator for OOM score of targeted processes */
207         enum cgroup_type type;
208
209         /* Desired size to be restored - level to be reached (MB)*/
210         unsigned int size_mb;
211         /* Max number of processes to be considered */
212         unsigned int count;
213         /* Memory reclaim status */
214         int status;
215         /*
216          * Optional - if set, will be triggered by LMK once the request
217          * is handled.
218          */
219         void (*callback) (struct lowmem_control *);
220 };
221
222 struct lowmem_worker {
223         pthread_t       worker_thread;
224         GAsyncQueue     *queue;
225         int             active;
226         int             running;
227 };
228
229 static struct lowmem_worker lmw;
230
231 //static int memlog_enabled;
232 //static int memlog_nr_max = DEFAULT_MEMLOG_NR_MAX;
233 /* remove logfiles to reduce to this threshold.
234  * it is about five-sixths of the memlog_nr_max. */
235 //static int memlog_remove_batch_thres = (DEFAULT_MEMLOG_NR_MAX * 5) / 6;
236 //static char *memlog_path = DEFAULT_MEMLOG_PATH;
237 //static char *memlog_prefix[MEMLOG_MAX];
238
239 #define LOWMEM_WORKER_IS_ACTIVE(_lmw)   g_atomic_int_get(&(_lmw)->active)
240 #define LOWMEM_WORKER_ACTIVATE(_lmw)    g_atomic_int_set(&(_lmw)->active, 1)
241 #define LOWMEM_WORKER_DEACTIVATE(_lmw)  g_atomic_int_set(&(_lmw)->active, 0)
242
243 #define LOWMEM_WORKER_IS_RUNNING(_lmw)  g_atomic_int_get(&(_lmw)->running)
244 #define LOWMEM_WORKER_RUN(_lmw) g_atomic_int_set(&(_lmw)->running, 1)
245 #define LOWMEM_WORKER_IDLE(_lmw)        g_atomic_int_set(&(_lmw)->running, 0)
246
247 #define LOWMEM_NEW_REQUEST() g_slice_new0(struct lowmem_control)
248
249 #define LOWMEM_DESTROY_REQUEST(_ctl)            \
250         g_slice_free(typeof(*(_ctl)), _ctl);    \
251
252 #define LOWMEM_SET_REQUEST(c, __flags, __type, __size, __count, __cb)   \
253 {                                                                       \
254         (c)->flags      = __flags; (c)->type    = __type;               \
255         (c)->size_mb= __size;  (c)->count       = __count;              \
256         (c)->callback   = __cb;                                         \
257 }
258
259 #define BUFF_MAX        255
260 #define APP_ATTR_PATH "/proc/%d/attr/current"
261
262 static int get_privilege(pid_t pid, char *name, size_t len)
263 {
264         char path[PATH_MAX];
265         char attr[BUFF_MAX];
266         size_t attr_len;
267         FILE *fp;
268
269         snprintf(path, sizeof(path), APP_ATTR_PATH, pid);
270
271         fp = fopen(path, "r");
272         if (!fp)
273                 return -errno;
274
275         attr_len = fread(attr, 1, sizeof(attr) - 1, fp);
276         fclose(fp);
277         if (attr_len <= 0)
278                 return -ENOENT;
279
280         attr[attr_len] = '\0';
281
282         snprintf(name, len, "%s", attr);
283         return 0;
284 }
285
286 static int is_app(pid_t pid)
287 {
288         char attr[BUFF_MAX];
289         size_t len;
290         int ret;
291
292         ret = get_privilege(pid, attr, sizeof(attr));
293         if (ret < 0) {
294                 _E("Failed to get privilege of PID(%d).", pid);
295                 return -1;
296         }
297
298         len = strlen(attr) + 1;
299
300         if (!strncmp("System", attr, len))
301                 return 0;
302
303         if (!strncmp("User", attr, len))
304                 return 0;
305
306         if (!strncmp("System::Privileged", attr, len))
307                 return 0;
308
309         return 1;
310 }
311
312
313 static void lowmem_queue_request(struct lowmem_worker *lmw,
314                                 struct lowmem_control *ctl)
315 {
316         if (LOWMEM_WORKER_IS_ACTIVE(lmw))
317                 g_async_queue_push(lmw->queue, ctl);
318 }
319
320 /* internal */
321 static void lowmem_drain_queue(struct lowmem_worker *lmw)
322 {
323         struct lowmem_control *ctl;
324
325         g_async_queue_lock(lmw->queue);
326         while ((ctl = g_async_queue_try_pop_unlocked(lmw->queue))) {
327                 if (ctl->callback)
328                         ctl->callback(ctl);
329                 LOWMEM_DESTROY_REQUEST(ctl);
330         }
331         g_async_queue_unlock(lmw->queue);
332 }
333
334 static void lowmem_request_destroy(gpointer data)
335 {
336         struct lowmem_control *ctl = (struct lowmem_control*) data;
337
338         if (ctl->callback)
339                 ctl->callback(ctl);
340         LOWMEM_DESTROY_REQUEST(ctl);
341 }
342
343 /*-------------------------------------------------*/
344
345 /* low memory action function for cgroup */
346 /* low memory action function */
347 static void high_mem_act(void);
348 static void swap_activate_act(void);
349 static void swap_compact_act(void);
350 static void lmk_act(void);
351
352
353 static size_t cur_mem_state = MEM_LEVEL_HIGH;
354 static int num_max_victims = MAX_MEMORY_CGROUP_VICTIMS;
355 static int num_vict_between_check = MAX_VICTIMS_BETWEEN_CHECK;
356
357 static unsigned long long totalram_bytes;
358 static unsigned long totalram_kb;
359
360 static struct module_ops memory_modules_ops;
361 static const struct module_ops *lowmem_ops;
362 static bool oom_popup_enable;
363 static bool oom_popup;
364 static bool memcg_swap_status;
365 static int fragmentation_size;
366
367 static const char *convert_cgroup_type_to_str(int type)
368 {
369         static const char *type_table[] =
370         {"/", "VIP", "High", "Medium", "Lowest"};
371         if (type >= CGROUP_ROOT && type <= CGROUP_LOW)
372                 return type_table[type];
373         else
374                 return "Error";
375 }
376
377 static const char *convert_status_to_str(int status)
378 {
379         static const char *status_table[] =
380         {"none", "done", "drop", "cont", "retry", "next_type"};
381         if(status >= LOWMEM_RECLAIM_NONE && status <= LOWMEM_RECLAIM_NEXT_TYPE)
382                 return status_table[status];
383         return "error status";
384 }
385
386 static const char *convert_memstate_to_str(int mem_state)
387 {
388         static const char *state_table[] = {"mem high", "mem medium",
389                 "mem low", "mem critical", "mem oom",};
390         if (mem_state >= 0 && mem_state < MEM_LEVEL_MAX)
391                 return state_table[mem_state];
392         return "";
393 }
394
395 static int lowmem_launch_oompopup(void)
396 {
397         GVariantBuilder *const gv_builder = g_variant_builder_new(G_VARIANT_TYPE("a{ss}"));
398         g_variant_builder_add(gv_builder, "{ss}", "_SYSPOPUP_CONTENT_", "lowmemory_oom");
399
400         GVariant *const params = g_variant_new("(a{ss})", gv_builder);
401         g_variant_builder_unref(gv_builder);
402
403         int ret = d_bus_call_method_sync_gvariant(SYSTEM_POPUP_BUS_NAME,
404                 SYSTEM_POPUP_PATH_SYSTEM, SYSTEM_POPUP_IFACE_SYSTEM,
405                 "PopupLaunch", params);
406
407         g_variant_unref(params);
408
409         return ret;
410 }
411
412 static inline void get_total_memory(void)
413 {
414         struct sysinfo si;
415         if (totalram_bytes)
416                 return;
417
418         if (!sysinfo(&si)) {
419                 totalram_bytes = (unsigned long long)si.totalram * si.mem_unit;
420                 totalram_kb = BYTE_TO_KBYTE(totalram_bytes);
421
422                 register_totalram_bytes(totalram_bytes);
423         }
424         else {
425                 _E("Failed to get total ramsize from the kernel");
426         }
427 }
428
429 unsigned int lowmem_get_task_mem_usage_rss(const struct task_info *tsk)
430 {
431         unsigned int size_kb = 0, total_size_kb = 0;
432         int index, ret;
433         pid_t pid;
434
435         /*
436          * If pids are allocated only when there are multiple processes with
437          * the same pgid e.g., browser and web process. Mostly, single process
438          * is used.
439          */
440         if (tsk->pids == NULL) {
441                 ret = proc_get_ram_usage(tsk->pid, &size_kb);
442
443                 /* If there is no proc entry for given pid the process
444                  * should be abandoned during further processing
445                  */
446                 if (ret < 0)
447                         _D("failed to get rss memory usage of %d", tsk->pid);
448
449                 return size_kb;
450         }
451
452         for (index = 0; index < tsk->pids->len; index++) {
453                 pid = g_array_index(tsk->pids, pid_t, index);
454                 ret = proc_get_ram_usage(pid, &size_kb);
455                 if (ret != RESOURCED_ERROR_NONE)
456                         continue;
457                 total_size_kb += size_kb;
458         }
459
460         return total_size_kb;
461 }
462
463 static int lowmem_kill_victim(const struct task_info *tsk,
464                 int flags, int memps_log, unsigned int *victim_size)
465 {
466         pid_t pid;
467         int ret;
468         char appname[PATH_MAX];
469         int sigterm = 0;
470         struct proc_app_info *pai;
471
472         pid = tsk->pid;
473
474         if (pid <= 0 || pid == getpid())
475                 return RESOURCED_ERROR_FAIL;
476
477         ret = proc_get_cmdline(pid, appname, sizeof appname);
478         if (ret == RESOURCED_ERROR_FAIL)
479                 return RESOURCED_ERROR_FAIL;
480
481         if (!strcmp("memps", appname) ||
482             !strcmp("crash-worker", appname) ||
483             !strcmp("system-syspopup", appname)) {
484                 _E("%s(%d) was selected, skip it", appname, pid);
485                 return RESOURCED_ERROR_FAIL;
486         }
487
488         pai = tsk->pai;
489         if (pai) {
490                 resourced_proc_status_change(PROC_CGROUP_SET_TERMINATE_REQUEST,
491                         pid, NULL, NULL, PROC_TYPE_NONE);
492
493                 if (tsk->oom_score_lru <= OOMADJ_BACKGRD_LOCKED) {
494                         sigterm = 1;
495                 } else if (tsk->oom_score_lru > OOMADJ_BACKGRD_LOCKED && tsk->oom_score_lru < OOMADJ_BACKGRD_UNLOCKED) {
496                         int app_flag = pai->flags;
497                         sigterm = app_flag & PROC_SIGTERM;
498                 }
499
500                 if (pai->memory.oom_killed)
501                         sigterm = 0;
502
503                 pai->memory.oom_killed = true;
504         }
505
506         if (sigterm)
507                 safe_kill(pid, SIGTERM);
508         else
509                 safe_kill(pid, SIGKILL);
510
511         _D("[LMK] we killed, force(%d), %d (%s) score = %d, size: rss = %u KB, sigterm = %d\n",
512            flags & OOM_FORCE, pid, appname, tsk->oom_score_adj,
513            tsk->size, sigterm);
514         *victim_size = tsk->size;
515
516         if (tsk->oom_score_lru > OOMADJ_FOREGRD_UNLOCKED)
517                 return RESOURCED_ERROR_NONE;
518
519         if (oom_popup_enable && !oom_popup) {
520                 lowmem_launch_oompopup();
521                 oom_popup = true;
522         }
523
524         return RESOURCED_ERROR_NONE;
525 }
526
527 /* return LOWMEM_RECLAIM_CONT when killing should be continued */
528 static int lowmem_check_kill_continued(struct task_info *tsk, int flags)
529 {
530         unsigned int available_mb;
531
532         /*
533          * Processes with the priority higher than perceptible are killed
534          * only when the available memory is less than dynamic oom threshold.
535          */
536         if (tsk->oom_score_lru > OOMADJ_BACKGRD_PERCEPTIBLE)
537                 return LOWMEM_RECLAIM_CONT;
538
539         if (flags & (OOM_FORCE|OOM_SINGLE_SHOT)) {
540                 _I("[LMK] %d is dropped during force kill, flag=%d",
541                         tsk->pid, flags);
542                 return LOWMEM_RECLAIM_DROP;
543         }
544         available_mb = proc_get_mem_available();
545         if (available_mb > lmk_start_threshold_mb) {
546                 _I("[LMK] available=%d MB, larger than %u MB, do not kill foreground",
547                         available_mb, lmk_start_threshold_mb);
548                 return LOWMEM_RECLAIM_RETRY;
549         }
550         return LOWMEM_RECLAIM_CONT;
551 }
552
553 static int compare_victims(const struct task_info *ta, const struct task_info *tb)
554 {
555         unsigned int pa, pb;
556
557         assert(ta != NULL);
558         assert(tb != NULL);
559         /*
560          * followed by kernel badness point calculation using heuristic.
561          * oom_score_adj is normalized by its unit, which varies -1000 ~ 1000.
562          */
563         pa = ta->oom_score_lru * (totalram_kb / 2000) + ta->size;
564         pb = tb->oom_score_lru * (totalram_kb / 2000) + tb->size;
565
566         return pb - pa;
567 }
568
569 static void lowmem_free_task_info_array(GArray *array)
570 {
571         int i;
572
573         for (i = 0; i < array->len; i++) {
574                 struct task_info *tsk;
575
576                 tsk = &g_array_index(array, struct task_info, i);
577                 if (tsk->pids)
578                         g_array_free(tsk->pids, true);
579         }
580
581         g_array_free(array, true);
582 }
583
584 static inline int is_dynamic_process_killer(int flags)
585 {
586         return (flags & OOM_FORCE) && !(flags & OOM_NOMEMORY_CHECK);
587 }
588
589 static unsigned int is_memory_recovered(unsigned int *avail, unsigned int thres)
590 {
591         unsigned int available = proc_get_mem_available();
592         unsigned int should_be_freed_mb = 0;
593
594         if (available < thres)
595                 should_be_freed_mb = thres - available;
596         /*
597          * free THRESHOLD_MARGIN more than real should be freed,
598          * because launching app is consuming up the memory.
599          */
600         if (should_be_freed_mb > 0)
601                 should_be_freed_mb += THRESHOLD_MARGIN;
602
603         *avail = available;
604
605         return should_be_freed_mb;
606 }
607
608 static int lowmem_get_pids_proc(GArray *pids)
609 {
610         DIR *dp;
611         struct dirent *dentry;
612
613         dp = opendir("/proc");
614         if (!dp) {
615                 _E("fail to open /proc");
616                 return RESOURCED_ERROR_FAIL;
617         }
618         while ((dentry = readdir(dp)) != NULL) {
619                 struct task_info tsk;
620                 pid_t pid = 0, pgid = 0;
621                 int oom = 0;
622
623                 if (!isdigit(dentry->d_name[0]))
624                         continue;
625
626                 pid = (pid_t)atoi(dentry->d_name);
627                 if (pid < 1)
628                         /* skip invalid pids or kernel processes */
629                         continue;
630
631                 pgid = getpgid(pid);
632                 if (pgid < 1)
633                         continue;
634
635                 if(is_app(pid) != 1)
636                         continue;
637
638                 if (proc_get_oom_score_adj(pid, &oom) < 0) {
639                         _D("pid(%d) was already terminated", pid);
640                         continue;
641                 }
642
643                 /* VIP pids should be excluded from the LMK list */
644                 if (cgroup_get_type(oom) == CGROUP_VIP)
645                         continue;
646
647                 /*
648                  * Check whether this array includes applications or not.
649                  * If it doesn't require to get applications
650                  * and pid has been already included in pai,
651                  * skip to append.
652                  */
653                 if (oom > OOMADJ_SU && oom <= OOMADJ_APP_MAX)
654                         continue;
655
656                 /*
657                  * Currently, for tasks in the memory cgroup,
658                  * do not consider multiple tasks with one pgid.
659                  */
660                 tsk.pid = pid;
661                 tsk.pgid = pgid;
662                 tsk.oom_score_adj = oom;
663                 tsk.oom_score_lru = oom;
664                 tsk.pids = NULL;
665                 tsk.size = lowmem_get_task_mem_usage_rss(&tsk);
666                 tsk.pai = NULL;
667
668                 g_array_append_val(pids, tsk);
669         }
670
671         closedir(dp);
672         return RESOURCED_ERROR_NONE;
673 }
674
675 /**
676  * @brief Terminate up to max_victims processes after finding them from pai.
677         It depends on proc_app_info lists
678         and it also reference systemservice cgroup
679         because some processes in this group don't have proc_app_info.
680  *
681  * @max_victims:            max number of processes to be terminated
682  * @start_oom:      find victims from start oom adj score value
683  * @end_oom: find victims to end oom adj score value
684  * @should_be_freed: amount of memory to be reclaimed (in MB)
685  * @total_size[out]: total size of possibly reclaimed memory (required)
686  * @completed:      final outcome (optional)
687  * @threshold:          desired value of memory available
688  */
689 static int lowmem_kill_victims(int max_victims,
690         int start_oom, int end_oom, unsigned should_be_freed, int flags,
691         unsigned int *total_size, int *completed, unsigned int threshold)
692 {
693         int total_count = 0;
694         GSList *proc_app_list = NULL;
695         int i, ret, victim = 0;
696         unsigned int victim_size = 0;
697         unsigned int total_victim_size = 0;
698         int status = LOWMEM_RECLAIM_NONE;
699         GArray *candidates = NULL;
700         GSList *iter, *iterchild;
701         struct proc_app_info *pai = NULL;
702         int oom_score_adj;
703         int should_be_freed_kb = MBYTE_TO_KBYTE(should_be_freed);
704
705         candidates = g_array_new(false, false, sizeof(struct task_info));
706
707         proc_app_list = proc_app_list_open();
708         gslist_for_each_item(iter, proc_app_list) {
709                 struct task_info ti;
710
711                 total_count++;
712                 pai = (struct proc_app_info *)iter->data;
713                 if (!pai->main_pid)
714                         continue;
715
716                 oom_score_adj = pai->memory.oom_score_adj;
717                 if (oom_score_adj > end_oom || oom_score_adj < start_oom)
718                         continue;
719
720                 if ((flags & OOM_REVISE) && pai->memory.oom_killed)
721                         continue;
722
723                 ti.pid = pai->main_pid;
724                 ti.pgid = getpgid(ti.pid);
725                 ti.oom_score_adj = oom_score_adj;
726                 ti.pai = pai;
727
728                 /*
729                  * Before oom_score_adj of favourite (oom_score = 270) applications is
730                  * independent of lru_state, now we consider lru_state, while
731                  * killing favourite process.
732                  */
733
734                 if (oom_score_adj == OOMADJ_FAVORITE && pai->lru_state >= PROC_BACKGROUND)
735                         ti.oom_score_lru = OOMADJ_FAVORITE + OOMADJ_FAVORITE_APP_INCREASE * pai->lru_state;
736                 else
737                         ti.oom_score_lru = oom_score_adj;
738
739                 if (pai->childs) {
740                         ti.pids = g_array_new(false, false, sizeof(pid_t));
741                         g_array_append_val(ti.pids, ti.pid);
742                         gslist_for_each_item(iterchild, pai->childs) {
743                                 pid_t child = GPOINTER_TO_PID(iterchild->data);
744                                 g_array_append_val(ti.pids, child);
745                         }
746                 } else
747                         ti.pids = NULL;
748
749                 g_array_append_val(candidates, ti);
750         }
751
752         proc_app_list_close();
753
754         if (!candidates->len) {
755                 status = LOWMEM_RECLAIM_NEXT_TYPE;
756                 goto leave;
757         }
758         else {
759                 _D("[LMK] candidate ratio=%d/%d", candidates->len, total_count);
760         }
761
762         for (i = 0; i < candidates->len; i++) {
763                 struct task_info *tsk;
764
765                 tsk = &g_array_index(candidates, struct task_info, i);
766                 tsk->size = lowmem_get_task_mem_usage_rss(tsk);                 /* KB */
767         }
768
769         /*
770          * In case of start_oom == OOMADJ_SU,
771          * we're going to try to kill some of processes in /proc
772          * to handle low memory situation.
773          * It can find malicious system process even though it has low oom score.
774          */
775         if (start_oom == OOMADJ_SU)
776                 lowmem_get_pids_proc(candidates);
777
778         g_array_sort(candidates, (GCompareFunc)compare_victims);
779
780         for (i = 0; i < candidates->len; i++) {
781                 struct task_info *tsk;
782
783                 if (i >= max_victims) {
784                         status = LOWMEM_RECLAIM_NEXT_TYPE;
785                         break;
786                 }
787
788                 /*
789                  * Available memory is checking only every
790                  * num_vict_between_check process for reducing burden.
791                  */
792                 if (!(i % num_vict_between_check)) {
793                         if (proc_get_mem_available() > threshold) {
794                                 status = LOWMEM_RECLAIM_DONE;
795                                 break;
796                         }
797                 }
798
799                 if (!(flags & OOM_NOMEMORY_CHECK) &&
800                     total_victim_size >= should_be_freed_kb) {
801                         _D("[LMK] victim=%d, max_victims=%d, total_size=%uKB",
802                                 victim, max_victims, total_victim_size);
803                         status = LOWMEM_RECLAIM_DONE;
804                         break;
805                 }
806
807                 tsk = &g_array_index(candidates, struct task_info, i);
808
809                 status = lowmem_check_kill_continued(tsk, flags);
810                 if (status != LOWMEM_RECLAIM_CONT)
811                         break;
812
813                 _I("[LMK] select victims from proc_app_list pid(%d) with oom_score_adj(%d)\n", tsk->pid, tsk->oom_score_adj);
814
815                 ret = lowmem_kill_victim(tsk, flags, i, &victim_size);
816                 if (ret != RESOURCED_ERROR_NONE)
817                         continue;
818                 victim++;
819                 total_victim_size += victim_size;
820         }
821
822 leave:
823         lowmem_free_task_info_array(candidates);
824         *total_size = total_victim_size;
825         if(*completed != LOWMEM_RECLAIM_CONT)
826                 *completed = status;
827         else
828                 *completed = LOWMEM_RECLAIM_NEXT_TYPE;
829         return victim;
830 }
831
832 static int calculate_range_of_oom(enum cgroup_type type, int *min, int *max)
833 {
834         if (type == CGROUP_VIP || type >= CGROUP_END || type <= CGROUP_TOP) {
835                 _E("cgroup type (%d) is out of scope", type);
836                 return RESOURCED_ERROR_FAIL;
837         }
838
839         *max = cgroup_get_highest_oom_score_adj(type);
840         *min = cgroup_get_lowest_oom_score_adj(type);
841
842         return RESOURCED_ERROR_NONE;
843 }
844
845 static void lowmem_handle_request(struct lowmem_control *ctl)
846 {
847         int start_oom, end_oom;
848         int count = 0, victim_cnt = 0;
849         int max_victim_cnt = ctl->count;
850         int status = LOWMEM_RECLAIM_NONE;
851         unsigned int available_mb = 0;
852         unsigned int total_size_mb = 0;
853         unsigned int current_size = 0;
854         unsigned int reclaim_size_mb, shortfall_mb = 0;
855         enum cgroup_type cgroup_type = ctl->type;
856
857         available_mb = proc_get_mem_available();
858         reclaim_size_mb = ctl->size_mb  > available_mb                  /* MB */
859                      ? ctl->size_mb - available_mb : 0;
860
861         if (!reclaim_size_mb) {
862                 status = LOWMEM_RECLAIM_DONE;
863                 goto done;
864         }
865
866 retry:
867         /* Prepare LMK to start doing it's job. Check preconditions. */
868         if (calculate_range_of_oom(cgroup_type, &start_oom, &end_oom))
869                 goto done;
870
871         lmk_start_threshold_mb = get_root_memcg_info()->threshold_mb[MEM_LEVEL_OOM];
872         shortfall_mb = is_memory_recovered(&available_mb, ctl->size_mb);
873
874         if (!shortfall_mb || !reclaim_size_mb) {
875                 status = LOWMEM_RECLAIM_DONE;
876                 goto done;
877         }
878
879         /* precaution */
880         current_size = 0;
881         victim_cnt = lowmem_kill_victims(max_victim_cnt, start_oom, end_oom,
882                             reclaim_size_mb, ctl->flags, &current_size, &status, ctl->size_mb);
883
884         if (victim_cnt) {
885                 current_size = KBYTE_TO_MBYTE(current_size);
886                 reclaim_size_mb -= reclaim_size_mb > current_size
887                         ? current_size : reclaim_size_mb;
888                 total_size_mb += current_size;
889                 count += victim_cnt;
890                 _I("[LMK] current: kill %d victims,  reclaim_size=%uMB from %d to %d status=%s",
891                                 victim_cnt, current_size,
892                                 start_oom, end_oom, convert_status_to_str(status));
893         }
894
895         if ((status == LOWMEM_RECLAIM_DONE) ||
896             (status == LOWMEM_RECLAIM_DROP) ||
897             (status == LOWMEM_RECLAIM_RETRY))
898                 goto done;
899
900         /*
901          * If it doesn't finish reclaiming memory in first operation,
902                 - if flags has OOM_IN_DEPTH,
903                    try to find victims again in the active cgroup.
904                    otherwise, just return because there is no more victims in the desired cgroup.
905                 - if flags has OOM_REVISE,
906                    it means that resourced can't find victims from proc_app_list.
907                    So, it should search victims or malicious process from /proc.
908                    But searching /proc leads to abnormal behaviour.
909                    (Make sluggish or kill same victims continuously)
910                    Thus, otherwise, just return in first operation and wait some period.
911          */
912         if (cgroup_type == CGROUP_LOW) {
913                 cgroup_type = CGROUP_MEDIUM;
914                 goto retry;
915         } else if ((cgroup_type == CGROUP_MEDIUM) && (ctl->flags & OOM_IN_DEPTH)) {
916                 cgroup_type = CGROUP_HIGH;
917                 if(ctl->flags & OOM_FORCE)
918                         max_victim_cnt = FOREGROUND_VICTIMS;
919                 goto retry;
920         } else if ((cgroup_type == CGROUP_HIGH) && (ctl->flags & OOM_IN_DEPTH)) {
921                 status = LOWMEM_RECLAIM_RETRY;
922                 ctl->type = CGROUP_ROOT;
923         }
924         else if (cgroup_type == CGROUP_ROOT) {
925                 status = LOWMEM_RECLAIM_RETRY;
926         }
927 done:
928         _I("[LMK] Done: killed %d processes reclaimed=%uMB remaining=%uMB shortfall=%uMB status=%s",
929                 count, total_size_mb, reclaim_size_mb, shortfall_mb, convert_status_to_str(status));
930
931         /* After we finish reclaiming it's worth to remove oldest memps logs */
932         ctl->status = status;
933 }
934
935 static void *lowmem_reclaim_worker(void *arg)
936 {
937         struct lowmem_worker *lmw = (struct lowmem_worker *)arg;
938
939         setpriority(PRIO_PROCESS, 0, OOM_KILLER_PRIORITY);
940
941         g_async_queue_ref(lmw->queue);
942
943         while (1) {
944                 int try_count = 0;
945                 struct lowmem_control *ctl;
946
947                 LOWMEM_WORKER_IDLE(lmw);
948                 /* Wait on any wake-up call */
949                 ctl = g_async_queue_pop(lmw->queue);
950
951                 if (ctl->flags & OOM_DROP)
952                         LOWMEM_DESTROY_REQUEST(ctl);
953
954                 if (!LOWMEM_WORKER_IS_ACTIVE(lmw) || !ctl)
955                         break;
956
957                 LOWMEM_WORKER_RUN(lmw);
958 process_again:
959                 _D("[LMK] %d tries", ++try_count);
960                 lowmem_handle_request(ctl);
961                 /**
962                  * Case the process failed to reclaim requested amount of memory
963                  * or still under have memory pressure - try the timeout wait.
964                  * There is a chance this will get woken-up in a better reality.
965                  */
966                 if (ctl->status == LOWMEM_RECLAIM_RETRY &&
967                     !(ctl->flags & OOM_SINGLE_SHOT)) {
968                         unsigned int available_mb = proc_get_mem_available();
969
970                         if (available_mb >= ctl->size_mb) {
971                                 _I("[LMK] Memory restored: requested=%uMB available=%uMB\n",
972                                         ctl->size_mb, available_mb);
973                                 ctl->status = LOWMEM_RECLAIM_DONE;
974                                 if (ctl->callback)
975                                         ctl->callback(ctl);
976                                 LOWMEM_DESTROY_REQUEST(ctl);
977                                 LOWMEM_WORKER_IDLE(lmw);
978                                 continue;
979                         }
980
981                         if (LOWMEM_WORKER_IS_ACTIVE(lmw)) {
982                                 g_usleep(LMW_RETRY_WAIT_TIMEOUT_MSEC);
983                                 ctl->flags |= OOM_REVISE;
984                                 goto process_again;
985                         }
986                 }
987
988                 /*
989                  * The ctl callback would check available size again.
990                  * And it is last point in reclaiming worker.
991                  * Resourced sent SIGKILL signal to victim processes
992                  * so it should wait for a some seconds until each processes returns memory.
993                  */
994                 g_usleep(LMW_LOOP_WAIT_TIMEOUT_MSEC);
995                 if (ctl->callback)
996                         ctl->callback(ctl);
997
998                 /* The lmk becomes the owner of all queued requests .. */
999                 LOWMEM_DESTROY_REQUEST(ctl);
1000                 LOWMEM_WORKER_IDLE(lmw);
1001         }
1002         g_async_queue_unref(lmw->queue);
1003         pthread_exit(NULL);
1004 }
1005
1006 static void change_lowmem_state(unsigned int mem_state)
1007 {
1008         cur_mem_state = mem_state;
1009         lmk_start_threshold_mb = get_root_memcg_info()->threshold_mb[MEM_LEVEL_OOM];
1010
1011         resourced_notify(RESOURCED_NOTIFIER_MEM_LEVEL_CHANGED,
1012                 (void *)&cur_mem_state);
1013 }
1014
1015 /* only app can call this function
1016  * that is, service cannot call the function
1017  */
1018 static void lowmem_swap_memory(char *path)
1019 {
1020         unsigned int available_mb;
1021
1022         if (cur_mem_state == MEM_LEVEL_HIGH)
1023                 return;
1024
1025         if (swap_get_state() != SWAP_ON)
1026                 return;
1027
1028         available_mb = proc_get_mem_available();
1029         if (cur_mem_state != MEM_LEVEL_LOW &&
1030             available_mb <= get_root_memcg_info()->threshold_mb[MEM_LEVEL_LOW])
1031                 swap_activate_act();
1032
1033         resourced_notify(RESOURCED_NOTIFIER_SWAP_START, path);
1034         memcg_swap_status = true;
1035 }
1036
1037 void lowmem_trigger_swap(pid_t pid, char *path, bool move)
1038 {
1039         int error;
1040         int oom_score_adj;
1041         int lowest_oom_score_adj;
1042
1043         if (!path) {
1044                 _E("[SWAP] Unknown memory cgroup path to swap");
1045                 return;
1046         }
1047
1048         /* In this case, corresponding process will be moved to memory CGROUP_LOW.
1049          */
1050         if (move) {
1051                 error = proc_get_oom_score_adj(pid, &oom_score_adj);
1052                 if (error) {
1053                         _E("[SWAP] Cannot get oom_score_adj of pid (%d)", pid);
1054                         return;
1055                 }
1056
1057                 lowest_oom_score_adj = cgroup_get_lowest_oom_score_adj(CGROUP_LOW);
1058
1059                 if (oom_score_adj < lowest_oom_score_adj) {
1060                         oom_score_adj = lowest_oom_score_adj;
1061                         /* End of this funciton, 'lowmem_swap_memory()' funciton will be called */
1062                         proc_set_oom_score_adj(pid, oom_score_adj, find_app_info(pid));
1063                         return;
1064                 }
1065         }
1066
1067         /* Correponding process is already managed per app or service.
1068          * In addition, if some process is already located in the CGROUP_LOW, then just do swap
1069          */
1070         resourced_notify(RESOURCED_NOTIFIER_SWAP_START, path);
1071 }
1072
1073 static void memory_level_send_system_event(int lv)
1074 {
1075         bundle *b;
1076         const char *str;
1077
1078         switch (lv) {
1079                 case MEM_LEVEL_HIGH:
1080                 case MEM_LEVEL_MEDIUM:
1081                 case MEM_LEVEL_LOW:
1082                         str = EVT_VAL_MEMORY_NORMAL;
1083                         break;
1084                 case MEM_LEVEL_CRITICAL:
1085                         str = EVT_VAL_MEMORY_SOFT_WARNING;
1086                         break;
1087                 case MEM_LEVEL_OOM:
1088                         str = EVT_VAL_MEMORY_HARD_WARNING;
1089                         break;
1090                 default:
1091                         _E("Invalid state");
1092                         return;
1093         }
1094
1095         b = bundle_create();
1096         if (!b) {
1097                 _E("Failed to create bundle");
1098                 return;
1099         }
1100
1101         bundle_add_str(b, EVT_KEY_LOW_MEMORY, str);
1102         eventsystem_send_system_event(SYS_EVENT_LOW_MEMORY, b);
1103         bundle_free(b);
1104 }
1105
1106 static void high_mem_act(void)
1107 {
1108         int ret, status;
1109
1110         ret = vconf_get_int(VCONFKEY_SYSMAN_LOW_MEMORY, &status);
1111         if (ret)
1112                 _D("vconf_get_int fail %s", VCONFKEY_SYSMAN_LOW_MEMORY);
1113         if (status != VCONFKEY_SYSMAN_LOW_MEMORY_NORMAL) {
1114                 vconf_set_int(VCONFKEY_SYSMAN_LOW_MEMORY,
1115                               VCONFKEY_SYSMAN_LOW_MEMORY_NORMAL);
1116                 memory_level_send_system_event(MEM_LEVEL_HIGH);
1117         }
1118
1119         change_lowmem_state(MEM_LEVEL_HIGH);
1120
1121         if (swap_get_state() == SWAP_ON && memcg_swap_status) {
1122                 resourced_notify(RESOURCED_NOTIFIER_SWAP_UNSET_LIMIT, get_memcg_info(CGROUP_LOW));
1123                 memcg_swap_status = false;
1124         }
1125         if (proc_get_freezer_status() == CGROUP_FREEZER_PAUSED)
1126                 resourced_notify(RESOURCED_NOTIFIER_FREEZER_CGROUP_STATE,
1127                         (void *)CGROUP_FREEZER_ENABLED);
1128 }
1129
1130 static void swap_activate_act(void)
1131 {
1132         int ret, status;
1133
1134         ret = vconf_get_int(VCONFKEY_SYSMAN_LOW_MEMORY, &status);
1135         if (ret)
1136                 _E("vconf get failed %s", VCONFKEY_SYSMAN_LOW_MEMORY);
1137
1138         if (status != VCONFKEY_SYSMAN_LOW_MEMORY_NORMAL) {
1139                 vconf_set_int(VCONFKEY_SYSMAN_LOW_MEMORY,
1140                                 VCONFKEY_SYSMAN_LOW_MEMORY_NORMAL);
1141                 memory_level_send_system_event(MEM_LEVEL_LOW);
1142         }
1143         change_lowmem_state(MEM_LEVEL_LOW);
1144         if (proc_get_freezer_status() == CGROUP_FREEZER_PAUSED)
1145                 resourced_notify(RESOURCED_NOTIFIER_FREEZER_CGROUP_STATE,
1146                         (void *)CGROUP_FREEZER_ENABLED);
1147
1148         if (swap_get_state() != SWAP_ON)
1149                 resourced_notify(RESOURCED_NOTIFIER_SWAP_ACTIVATE, NULL);
1150 }
1151
1152 static void dedup_act(enum ksm_scan_mode mode)
1153 {
1154         int ret, status;
1155         int data;
1156
1157         if (dedup_get_state() != DEDUP_ONE_SHOT)
1158                 return;
1159
1160         if (proc_get_freezer_status() == CGROUP_FREEZER_PAUSED)
1161                 resourced_notify(RESOURCED_NOTIFIER_FREEZER_CGROUP_STATE,
1162                                 (void *)CGROUP_FREEZER_ENABLED);
1163
1164         if (mode == KSM_SCAN_PARTIAL) {
1165                 ret = vconf_get_int(VCONFKEY_SYSMAN_LOW_MEMORY, &status);
1166                 if (ret)
1167                         _E("vconf get failed %s", VCONFKEY_SYSMAN_LOW_MEMORY);
1168
1169                 if (status != VCONFKEY_SYSMAN_LOW_MEMORY_NORMAL) {
1170                         vconf_set_int(VCONFKEY_SYSMAN_LOW_MEMORY,
1171                                         VCONFKEY_SYSMAN_LOW_MEMORY_NORMAL);
1172                         memory_level_send_system_event(MEM_LEVEL_MEDIUM);
1173                 }
1174                 change_lowmem_state(MEM_LEVEL_MEDIUM);
1175
1176                 data = KSM_SCAN_PARTIAL;
1177                 resourced_notify(RESOURCED_NOTIFIER_DEDUP_SCAN, &data);
1178         } else if (mode == KSM_SCAN_FULL) {
1179                 data = KSM_SCAN_FULL;
1180                 resourced_notify(RESOURCED_NOTIFIER_DEDUP_SCAN, &data);
1181         }
1182 }
1183
1184 static void swap_compact_act(void)
1185 {
1186         change_lowmem_state(MEM_LEVEL_CRITICAL);
1187         resourced_notify(RESOURCED_NOTIFIER_SWAP_COMPACT, (void *)SWAP_COMPACT_MEM_LEVEL_CRITICAL);
1188         memory_level_send_system_event(MEM_LEVEL_CRITICAL);
1189 }
1190
1191 static void medium_cb(struct lowmem_control *ctl)
1192 {
1193         if (ctl->status == LOWMEM_RECLAIM_DONE)
1194                 oom_popup = false;
1195         lowmem_change_memory_state(MEM_LEVEL_HIGH, 0);
1196 }
1197
1198 static void lmk_act(void)
1199 {
1200         unsigned int available_mb;
1201         int ret;
1202         int status = VCONFKEY_SYSMAN_LOW_MEMORY_NORMAL;
1203
1204         /*
1205          * Don't trigger reclaim worker
1206          * if it is already running
1207          */
1208         if (LOWMEM_WORKER_IS_RUNNING(&lmw))
1209                 return;
1210
1211         ret = vconf_get_int(VCONFKEY_SYSMAN_LOW_MEMORY, &status);
1212         if (ret)
1213                 _D("vconf_get_int fail %s", VCONFKEY_SYSMAN_LOW_MEMORY);
1214
1215         memory_level_send_system_event(MEM_LEVEL_OOM);
1216         if (status != VCONFKEY_SYSMAN_LOW_MEMORY_HARD_WARNING) {
1217                 if (proc_get_freezer_status() == CGROUP_FREEZER_ENABLED)
1218                         resourced_notify(RESOURCED_NOTIFIER_FREEZER_CGROUP_STATE,
1219                                 (void *)CGROUP_FREEZER_PAUSED);
1220                 vconf_set_int(VCONFKEY_SYSMAN_LOW_MEMORY,
1221                               VCONFKEY_SYSMAN_LOW_MEMORY_HARD_WARNING);
1222         }
1223         available_mb = proc_get_mem_available();
1224
1225         change_lowmem_state(MEM_LEVEL_OOM);
1226
1227         if (available_mb < get_root_memcg_info()->threshold_leave_mb) {
1228                 struct lowmem_control *ctl;
1229
1230                 ctl = LOWMEM_NEW_REQUEST();
1231                 if (ctl) {
1232                         LOWMEM_SET_REQUEST(ctl, OOM_IN_DEPTH,
1233                                 CGROUP_LOW, get_root_memcg_info()->threshold_leave_mb,
1234                                 num_max_victims, medium_cb);
1235                         lowmem_queue_request(&lmw, ctl);
1236                 }
1237         }
1238
1239         resourced_notify(RESOURCED_NOTIFIER_SWAP_COMPACT, (void *)SWAP_COMPACT_MEM_LEVEL_OOM);
1240
1241         /*
1242          * Flush resourced memory such as other processes.
1243          * Resourced can use both many fast bins and sqlite3 cache memery.
1244          */
1245         malloc_trim(0);
1246
1247         return;
1248 }
1249
1250 static void lowmem_trigger_memory_state_action(int mem_state)
1251 {
1252         /*
1253          * Check if the state we want to set is different from current
1254          * But it should except this condition if mem_state is already medium.
1255          * Otherwise, recalim worker couldn't run any more.
1256          */
1257         if (mem_state != MEM_LEVEL_OOM && cur_mem_state == mem_state)
1258                 return;
1259
1260         switch (mem_state) {
1261         case MEM_LEVEL_HIGH:
1262                 high_mem_act();
1263                 break;
1264         case MEM_LEVEL_MEDIUM:
1265                 dedup_act(KSM_SCAN_PARTIAL);
1266                 break;
1267         case MEM_LEVEL_LOW:
1268                 swap_activate_act();
1269                 break;
1270         case MEM_LEVEL_CRITICAL:
1271                 dedup_act(KSM_SCAN_FULL);
1272                 swap_compact_act();
1273                 break;
1274         case MEM_LEVEL_OOM:
1275                 lmk_act();
1276                 break;
1277         default:
1278                 assert(0);
1279         }
1280 }
1281
1282 static unsigned int check_mem_state(unsigned int available_mb)
1283 {
1284         int mem_state;
1285         for (mem_state = MEM_LEVEL_MAX - 1; mem_state > MEM_LEVEL_HIGH; mem_state--) {
1286                 if (mem_state != MEM_LEVEL_OOM &&
1287                                 available_mb <= get_root_memcg_info()->threshold_mb[mem_state])
1288                         break;
1289                 else if (mem_state == MEM_LEVEL_OOM && available_mb <= lmk_start_threshold_mb)
1290                         break;
1291         }
1292
1293         return mem_state;
1294 }
1295
1296 /* setup memcg parameters depending on total ram size. */
1297 static void setup_memcg_params(void)
1298 {
1299         unsigned long total_ramsize_mb;
1300
1301         get_total_memory();
1302         total_ramsize_mb = BYTE_TO_MBYTE(totalram_bytes);
1303
1304         _D("Total: %lu MB", total_ramsize_mb);
1305         if (total_ramsize_mb <= MEM_SIZE_64) {
1306                 /* set thresholds for ram size 64M */
1307                 proactive_threshold_mb = PROACTIVE_64_THRES;
1308                 proactive_leave_mb = PROACTIVE_64_LEAVE;
1309                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_MEDIUM, CGROUP_ROOT_64_THRES_DEDUP);
1310                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_LOW, CGROUP_ROOT_64_THRES_SWAP);
1311                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_CRITICAL, CGROUP_ROOT_64_THRES_LOW);
1312                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_OOM, CGROUP_ROOT_64_THRES_MEDIUM);
1313                 memcg_set_leave_threshold(CGROUP_ROOT, CGROUP_ROOT_64_THRES_LEAVE);
1314                 num_max_victims = CGROUP_ROOT_64_NUM_VICTIMS;
1315         } else if (total_ramsize_mb <= MEM_SIZE_256) {
1316                 /* set thresholds for ram size 256M */
1317                 proactive_threshold_mb = PROACTIVE_256_THRES;
1318                 proactive_leave_mb = PROACTIVE_256_LEAVE;
1319                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_MEDIUM, CGROUP_ROOT_256_THRES_DEDUP);
1320                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_LOW, CGROUP_ROOT_256_THRES_SWAP);
1321                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_CRITICAL, CGROUP_ROOT_256_THRES_LOW);
1322                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_OOM, CGROUP_ROOT_256_THRES_MEDIUM);
1323                 memcg_set_leave_threshold(CGROUP_ROOT, CGROUP_ROOT_256_THRES_LEAVE);
1324                 num_max_victims = CGROUP_ROOT_256_NUM_VICTIMS;
1325         } else if (total_ramsize_mb <= MEM_SIZE_448) {
1326                 /* set thresholds for ram size 448M */
1327                 proactive_threshold_mb = PROACTIVE_448_THRES;
1328                 proactive_leave_mb = PROACTIVE_448_LEAVE;
1329                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_MEDIUM, CGROUP_ROOT_448_THRES_DEDUP);
1330                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_LOW, CGROUP_ROOT_448_THRES_SWAP);
1331                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_CRITICAL, CGROUP_ROOT_448_THRES_LOW);
1332                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_OOM, CGROUP_ROOT_448_THRES_MEDIUM);
1333                 memcg_set_leave_threshold(CGROUP_ROOT, CGROUP_ROOT_448_THRES_LEAVE);
1334                 num_max_victims = CGROUP_ROOT_448_NUM_VICTIMS;
1335         } else if (total_ramsize_mb <= MEM_SIZE_512) {
1336                 /* set thresholds for ram size 512M */
1337                 proactive_threshold_mb = PROACTIVE_512_THRES;
1338                 proactive_leave_mb = PROACTIVE_512_LEAVE;
1339                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_MEDIUM, CGROUP_ROOT_512_THRES_DEDUP);
1340                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_LOW, CGROUP_ROOT_512_THRES_SWAP);
1341                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_CRITICAL, CGROUP_ROOT_512_THRES_LOW);
1342                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_OOM, CGROUP_ROOT_512_THRES_MEDIUM);
1343                 memcg_set_leave_threshold(CGROUP_ROOT, CGROUP_ROOT_512_THRES_LEAVE);
1344                 num_max_victims = CGROUP_ROOT_512_NUM_VICTIMS;
1345         }  else if (total_ramsize_mb <= MEM_SIZE_768) {
1346                 /* set thresholds for ram size 512M */
1347                 proactive_threshold_mb = PROACTIVE_768_THRES;
1348                 proactive_leave_mb = PROACTIVE_768_LEAVE;
1349                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_MEDIUM, CGROUP_ROOT_768_THRES_DEDUP);
1350                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_LOW, CGROUP_ROOT_768_THRES_SWAP);
1351                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_CRITICAL, CGROUP_ROOT_768_THRES_LOW);
1352                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_OOM, CGROUP_ROOT_768_THRES_MEDIUM);
1353                 memcg_set_leave_threshold(CGROUP_ROOT, CGROUP_ROOT_768_THRES_LEAVE);
1354                 num_max_victims = CGROUP_ROOT_768_NUM_VICTIMS;
1355         } else if (total_ramsize_mb <= MEM_SIZE_1024) {
1356                 /* set thresholds for ram size more than 1G */
1357                 proactive_threshold_mb = PROACTIVE_1024_THRES;
1358                 proactive_leave_mb = PROACTIVE_1024_LEAVE;
1359                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_MEDIUM, CGROUP_ROOT_1024_THRES_DEDUP);
1360                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_LOW, CGROUP_ROOT_1024_THRES_SWAP);
1361                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_CRITICAL, CGROUP_ROOT_1024_THRES_LOW);
1362                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_OOM, CGROUP_ROOT_1024_THRES_MEDIUM);
1363                 memcg_set_leave_threshold(CGROUP_ROOT, CGROUP_ROOT_1024_THRES_LEAVE);
1364                 num_max_victims = CGROUP_ROOT_1024_NUM_VICTIMS;
1365         } else if (total_ramsize_mb <= MEM_SIZE_2048) {
1366                 proactive_threshold_mb = PROACTIVE_2048_THRES;
1367                 proactive_leave_mb = PROACTIVE_2048_LEAVE;
1368                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_MEDIUM, CGROUP_ROOT_2048_THRES_DEDUP);
1369                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_LOW, CGROUP_ROOT_2048_THRES_SWAP);
1370                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_CRITICAL, CGROUP_ROOT_2048_THRES_LOW);
1371                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_OOM, CGROUP_ROOT_2048_THRES_MEDIUM);
1372                 memcg_set_leave_threshold(CGROUP_ROOT, CGROUP_ROOT_2048_THRES_LEAVE);
1373                 num_max_victims = CGROUP_ROOT_2048_NUM_VICTIMS;
1374         } else {
1375                 proactive_threshold_mb = PROACTIVE_3072_THRES;
1376                 proactive_leave_mb = PROACTIVE_3072_LEAVE;
1377                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_MEDIUM, CGROUP_ROOT_3072_THRES_DEDUP);
1378                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_LOW, CGROUP_ROOT_3072_THRES_SWAP);
1379                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_CRITICAL, CGROUP_ROOT_3072_THRES_LOW);
1380                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_OOM, CGROUP_ROOT_3072_THRES_MEDIUM);
1381                 memcg_set_leave_threshold(CGROUP_ROOT, CGROUP_ROOT_3072_THRES_LEAVE);
1382                 num_max_victims = CGROUP_ROOT_3072_NUM_VICTIMS;
1383         }
1384 }
1385
1386 static void lowmem_move_memcgroup(int pid, int next_oom_score_adj, struct proc_app_info *pai)
1387 {
1388         int cur_oom_score_adj;
1389         int cur_memcg_idx;
1390         struct memcg_info *mi;
1391         int next_memcg_idx = cgroup_get_type(next_oom_score_adj);
1392
1393         if(next_memcg_idx < CGROUP_VIP || next_memcg_idx > CGROUP_LOW) {
1394                 _E("cgroup type (%d) should not be called", next_memcg_idx);
1395                 return;
1396         }
1397         mi = get_memcg_info(next_memcg_idx);
1398
1399         if (!mi) {
1400                 return;
1401         }
1402
1403         if (!pai) {
1404                 cgroup_write_pid_fullpath(mi->name, pid);
1405                 return;
1406         }
1407
1408         /* parent pid */
1409         if (pai->main_pid == pid) {
1410                 cur_oom_score_adj = pai->memory.oom_score_adj;
1411                 cur_memcg_idx = cgroup_get_type(cur_oom_score_adj);
1412
1413                 /* This pid is not yet registered at the memory cgroup.
1414                  * plz, reference proc_create_app_info function
1415                  */
1416                 if (cur_oom_score_adj != OOMADJ_APP_MAX + 10) {
1417                         /* VIP processes should not be asked to move. */
1418                         if (cur_memcg_idx <= CGROUP_VIP) {
1419                                 _E("[MEMORY-CGROUP] current cgroup (%s) cannot be VIP or Root", convert_cgroup_type_to_str(cur_memcg_idx));
1420                                 return;
1421                         }
1422                 }
1423
1424                 _I("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));
1425
1426                 if (cur_oom_score_adj == next_oom_score_adj) {
1427                         _D("next oom_score_adj (%d) is same with current one", next_oom_score_adj);
1428                         return;
1429                 }
1430
1431                 proc_set_process_memory_state(pai, next_memcg_idx, mi, next_oom_score_adj);
1432
1433                 if (!lowmem_limit_move_cgroup(pai))
1434                         return;
1435
1436                 if(cur_memcg_idx == next_memcg_idx)
1437                         return;
1438
1439                 cgroup_write_pid_fullpath(mi->name, pid);
1440                 if (next_memcg_idx == CGROUP_LOW)
1441                         lowmem_swap_memory(get_memcg_info(CGROUP_LOW)->name);
1442         }
1443         /* child pid */
1444         else {
1445                 if (pai->memory.use_mem_limit)
1446                         return;
1447
1448                 cgroup_write_pid_fullpath(mi->name, pid);
1449         }
1450 }
1451
1452 static int lowmem_activate_worker(void)
1453 {
1454         int ret = RESOURCED_ERROR_NONE;
1455
1456         if (LOWMEM_WORKER_IS_ACTIVE(&lmw)) {
1457                 return ret;
1458         }
1459
1460         lmw.queue = g_async_queue_new_full(lowmem_request_destroy);
1461         if (!lmw.queue) {
1462                 _E("Failed to create request queue\n");
1463                 return RESOURCED_ERROR_FAIL;
1464         }
1465         LOWMEM_WORKER_ACTIVATE(&lmw);
1466         ret = pthread_create(&lmw.worker_thread, NULL,
1467                 (void *)lowmem_reclaim_worker, (void *)&lmw);
1468         if (ret) {
1469                 LOWMEM_WORKER_DEACTIVATE(&lmw);
1470                 _E("Failed to create LMK thread: %d\n", ret);
1471         } else {
1472                 pthread_detach(lmw.worker_thread);
1473                 ret = RESOURCED_ERROR_NONE;
1474         }
1475         return ret;
1476 }
1477
1478 static void lowmem_deactivate_worker(void)
1479 {
1480         struct lowmem_control *ctl;
1481
1482         if (!LOWMEM_WORKER_IS_ACTIVE(&lmw))
1483                 return;
1484
1485         LOWMEM_WORKER_DEACTIVATE(&lmw);
1486         lowmem_drain_queue(&lmw);
1487
1488         ctl = LOWMEM_NEW_REQUEST();
1489         if (!ctl) {
1490                 _E("Critical - g_slice alloc failed - Lowmem cannot be deactivated");
1491                 return;
1492         }
1493         ctl->flags = OOM_DROP;
1494         g_async_queue_push(lmw.queue, ctl);
1495         g_async_queue_unref(lmw.queue);
1496 }
1497
1498 static int lowmem_press_eventfd_read(int fd)
1499 {
1500         unsigned long long dummy_state;
1501
1502         return read(fd, &dummy_state, sizeof(dummy_state));
1503 }
1504
1505 static void lowmem_press_root_cgroup_handler(void)
1506 {
1507         static unsigned int prev_available_mb;
1508         unsigned int available_mb;
1509         int mem_state;
1510
1511         available_mb = proc_get_mem_available();
1512         if (prev_available_mb == available_mb)
1513                 return;
1514
1515         mem_state = check_mem_state(available_mb);
1516         lowmem_trigger_memory_state_action(mem_state);
1517         prev_available_mb = available_mb;
1518 }
1519
1520 static bool lowmem_press_eventfd_handler(int fd, void *data)
1521 {
1522         struct memcg_info *mi;
1523         enum cgroup_type type = CGROUP_ROOT;
1524
1525         // FIXME: probably shouldn't get ignored
1526         if (lowmem_press_eventfd_read(fd) < 0)
1527                 _E("Failed to read lowmem press event, %m\n");
1528
1529         for (type = CGROUP_ROOT; type < CGROUP_END; type++) {
1530                 if (!get_cgroup_tree(type) || !get_memcg_info(type))
1531                         continue;
1532                 mi = get_memcg_info(type);
1533                 if (fd == mi->evfd) {
1534                         /* call low memory handler for this memcg */
1535                         if (type == CGROUP_ROOT) {
1536                                 lowmem_press_root_cgroup_handler();
1537                                 return true;
1538                         }
1539                         else {
1540                                 _E("Wrong event fd for cgroup %s", convert_cgroup_type_to_str(type));
1541                                 return false;
1542                         }
1543                 }
1544         }
1545
1546         return false;
1547 }
1548
1549 static int lowmem_press_register_eventfd(struct memcg_info *mi)
1550 {
1551         int evfd;
1552         const char *name = mi->name;
1553         static fd_handler_h handler;
1554
1555         if (mi->threshold_mb[MEM_LEVEL_OOM] == LOWMEM_THRES_INIT)
1556                 return 0;
1557
1558         evfd = memcg_set_eventfd(name, MEMCG_EVENTFD_MEMORY_PRESSURE,
1559                         event_level);
1560
1561         if (evfd < 0) {
1562                 int saved_errno = errno;
1563                 _E("Failed to register event press fd %s cgroup", name);
1564                 return -saved_errno;
1565         }
1566
1567         mi->evfd = evfd;
1568
1569         add_fd_read_handler(evfd, lowmem_press_eventfd_handler, NULL, NULL, &handler);
1570         return 0;
1571 }
1572
1573 static int lowmem_press_setup_eventfd(void)
1574 {
1575         unsigned int i;
1576
1577         for (i = CGROUP_ROOT; i < CGROUP_END; i++) {
1578                 if (!get_use_hierarchy(i))
1579                         continue;
1580
1581                 lowmem_press_register_eventfd(get_memcg_info(i));
1582         }
1583         return RESOURCED_ERROR_NONE;
1584 }
1585
1586 static void lowmem_force_reclaim_cb(struct lowmem_control *ctl)
1587 {
1588         lowmem_change_memory_state(MEM_LEVEL_HIGH, 0);
1589 }
1590
1591 int lowmem_trigger_reclaim(int flags, int victims, enum cgroup_type type, int threshold_mb)
1592 {
1593         struct lowmem_control *ctl = LOWMEM_NEW_REQUEST();
1594
1595         if (!ctl)
1596                 return -ENOMEM;
1597
1598         flags |= OOM_FORCE | OOM_IN_DEPTH | OOM_SINGLE_SHOT;
1599         victims = victims > 0 ? victims : MAX_MEMORY_CGROUP_VICTIMS;
1600         type = type > 0 ? type : CGROUP_LOW;
1601         threshold_mb = threshold_mb > 0 ? threshold_mb : get_root_memcg_info()->threshold_leave_mb;
1602
1603         lowmem_change_memory_state(MEM_LEVEL_CRITICAL, 1);
1604         LOWMEM_SET_REQUEST(ctl, flags,
1605                 type, threshold_mb, victims,
1606                 lowmem_force_reclaim_cb);
1607         lowmem_queue_request(&lmw, ctl);
1608
1609         return 0;
1610 }
1611
1612 void lowmem_trigger_swap_reclaim(enum cgroup_type type, unsigned long long swap_size_bytes)
1613 {
1614         int size_mb, victims;
1615
1616         victims = num_max_victims  > MAX_PROACTIVE_HIGH_VICTIMS
1617                                  ? MAX_PROACTIVE_HIGH_VICTIMS : num_max_victims;
1618
1619         size_mb = get_root_memcg_info()->threshold_leave_mb + BYTE_TO_MBYTE(swap_size_bytes);
1620         lowmem_trigger_reclaim(0, victims, type, size_mb);
1621 }
1622
1623 bool lowmem_fragmentated(void)
1624 {
1625         struct buddyinfo bi;
1626         int ret;
1627
1628         ret = proc_get_buddyinfo("Normal", &bi);
1629         if (ret < 0)
1630                 return false;
1631
1632         /*
1633          * The fragmentation_size is the minimum count of order-2 pages in "Normal" zone.
1634          * If total buddy pages is smaller than fragmentation_size,
1635          * resourced will detect kernel memory is fragmented.
1636          * Default value is zero in low memory device.
1637          */
1638         if (bi.page[PAGE_32K] + (bi.page[PAGE_64K] << 1) + (bi.page[PAGE_128K] << 2) +
1639                 (bi.page[PAGE_256K] << 3) < fragmentation_size) {
1640                 _I("fragmentation detected, need to execute proactive oom killer");
1641                 return true;
1642         }
1643         return false;
1644 }
1645
1646 static void lowmem_proactive_oom_killer(int flags, char *appid)
1647 {
1648         unsigned int before_mb;
1649         int victims;
1650
1651         before_mb = proc_get_mem_available();
1652
1653         /* If memory state is medium or normal, just return and kill in oom killer */
1654         if (before_mb < get_root_memcg_info()->threshold_mb[MEM_LEVEL_OOM] ||
1655                         before_mb > proactive_leave_mb)
1656                 return;
1657
1658         victims = num_max_victims  > MAX_PROACTIVE_HIGH_VICTIMS
1659                                  ? MAX_PROACTIVE_HIGH_VICTIMS : num_max_victims;
1660
1661 #ifdef HEART_SUPPORT
1662         /*
1663          * This branch is used only when HEART module is compiled in and
1664          * it's MEMORY module must be enabled. Otherwise this is skipped.
1665          */
1666         struct heart_memory_data *md = heart_memory_get_memdata(appid, DATA_LATEST);
1667         if (md) {
1668                 unsigned int rss_mb, after_mb, size_mb;
1669
1670                 rss_mb = KBYTE_TO_MBYTE(md->avg_rss);
1671
1672                 free(md);
1673
1674                 after_mb = before_mb - rss_mb;
1675                 /*
1676                  * after launching app, ensure that available memory is
1677                  * above threshold_leave
1678                  */
1679                 if (after_mb >= get_root_memcg_info()->threshold[MEM_LEVEL_OOM])
1680                         return;
1681
1682                 if (proactive_threshold_mb - rss_mb >= get_root_memcg_info()->threshold[MEM_LEVEL_OOM])
1683                         size_mb = proactive_threshold_mb;
1684                 else
1685                         size_mb = rss_mb + get_root_memcg_info()->threshold[MEM_LEVEL_OOM] + THRESHOLD_MARGIN;
1686
1687                 _D("history based proactive LMK : avg rss %u, available %u required = %u MB",
1688                         rss_mb, before_mb, size_mb);
1689                 lowmem_trigger_reclaim(0, victims, CGROUP_LOW, size_mb);
1690
1691                 return;
1692         }
1693 #endif
1694
1695         /*
1696          * When there is no history data for the launching app,
1697          * it is necessary to check current fragmentation state or application manifest file.
1698          * So, resourced feels proactive LMK is required, run oom killer based on dynamic
1699          * threshold.
1700          */
1701         if (lowmem_fragmentated())
1702                 goto reclaim;
1703
1704         /*
1705          * run proactive oom killer only when available is larger than
1706          * dynamic process threshold
1707          */
1708         if (!proactive_threshold_mb || before_mb >= proactive_threshold_mb)
1709                 return;
1710
1711         if (!(flags & PROC_LARGEMEMORY))
1712                 return;
1713
1714 reclaim:
1715         /*
1716          * free THRESHOLD_MARGIN more than real should be freed,
1717          * because launching app is consuming up the memory.
1718          */
1719         _D("Run threshold based proactive LMK: memory level to reach: %u MB\n",
1720                 proactive_leave_mb + THRESHOLD_MARGIN);
1721         lowmem_trigger_reclaim(0, victims, CGROUP_LOW, proactive_leave_mb + THRESHOLD_MARGIN);
1722 }
1723
1724 unsigned int lowmem_get_proactive_thres(void)
1725 {
1726         return proactive_threshold_mb;
1727 }
1728
1729 static int lowmem_prelaunch_handler(void *data)
1730 {
1731         struct proc_status *ps = (struct proc_status *)data;
1732         struct proc_app_info *pai = ps->pai;
1733
1734         if (!pai || CHECK_BIT(pai->flags, PROC_SERVICEAPP))
1735                 return RESOURCED_ERROR_NONE;
1736
1737         lowmem_proactive_oom_killer(ps->pai->flags, ps->pai->appid);
1738         return RESOURCED_ERROR_NONE;
1739 }
1740
1741 int lowmem_control_handler(void *data)
1742 {
1743         struct lowmem_control_data *lowmem_data;
1744
1745         lowmem_data = (struct lowmem_control_data *)data;
1746         switch (lowmem_data->control_type) {
1747         case LOWMEM_MOVE_CGROUP:
1748                 lowmem_move_memcgroup((pid_t)lowmem_data->pid,
1749                                         lowmem_data->oom_score_adj, lowmem_data->pai);
1750                 break;
1751         default:
1752                 break;
1753         }
1754         return RESOURCED_ERROR_NONE;
1755 }
1756
1757 static inline int calculate_threshold_size(double ratio)
1758 {
1759         unsigned long long size_bytes = (double)totalram_bytes * ratio / 100.0;
1760         return BYTE_TO_MBYTE(size_bytes);
1761 }
1762
1763 static void load_configs(const char *path)
1764 {
1765         struct memcg_conf *memcg_conf = get_memcg_conf();
1766
1767         /* set MemoryGroupLimit section */
1768         for (int cgroup = CGROUP_VIP; cgroup < CGROUP_END; cgroup++) {
1769                 if (memcg_conf->cgroup_limit[cgroup] > 0.0)
1770                         memcg_info_set_limit(get_memcg_info(cgroup),
1771                                         memcg_conf->cgroup_limit[cgroup]/100.0, totalram_bytes);
1772         }
1773
1774         /* set MemoryLevelThreshold section */
1775         for (int lvl = MEM_LEVEL_MEDIUM; lvl < MEM_LEVEL_MAX; lvl++) {
1776                 if (memcg_conf->threshold[lvl].percent &&
1777                         memcg_conf->threshold[lvl].threshold > 0) {
1778                         memcg_set_threshold(CGROUP_ROOT, lvl,
1779                                         calculate_threshold_size(memcg_conf->threshold[lvl].threshold));
1780
1781                         if (lvl == MEM_LEVEL_OOM)
1782                                 memcg_set_leave_threshold(CGROUP_ROOT,
1783                                                 get_memcg_info(CGROUP_ROOT)->threshold_mb[lvl] * 2);
1784                 }
1785                 else if (memcg_conf->threshold[lvl].threshold > 0) {
1786                         memcg_set_threshold(CGROUP_ROOT, lvl,
1787                                         memcg_conf->threshold[lvl].threshold);
1788
1789                         if (lvl == MEM_LEVEL_OOM)
1790                                 memcg_set_leave_threshold(CGROUP_ROOT,
1791                                                 get_memcg_info(CGROUP_ROOT)->threshold_mb[lvl] * 2);
1792                 }
1793         }
1794         oom_popup_enable = memcg_conf->oom_popup;
1795
1796         /* set MemoryAppTypeLimit and MemoryAppStatusLimit section */
1797         lowmem_memory_init(memcg_conf->service.memory_bytes, memcg_conf->widget.memory_bytes,
1798                         memcg_conf->guiapp.memory_bytes, memcg_conf->background.memory_bytes);
1799         lowmem_action_init(memcg_conf->service.action, memcg_conf->widget.action,
1800                         memcg_conf->guiapp.action, memcg_conf->background.action);
1801
1802         free_memcg_conf();
1803 }
1804
1805 static void print_mem_configs(void)
1806 {
1807         /* print info of Memory section */
1808         for (int cgroup = CGROUP_VIP; cgroup < CGROUP_END; cgroup++) {
1809                 _I("[MEMORY-CGROUP] set memory for cgroup '%s' to %llu bytes",
1810                                 convert_cgroup_type_to_str(cgroup), get_memcg_info(cgroup)->limit_bytes);
1811         }
1812
1813         for (int cgroup = CGROUP_ROOT; cgroup < CGROUP_END; cgroup++) {
1814                 for (int mem_lvl = 0; mem_lvl < MEM_LEVEL_MAX; mem_lvl++) {
1815                         _I("[MEMORY-LEVEL] set threshold of %s for memory level '%s' to %u MB", convert_cgroup_type_to_str(cgroup),
1816                                         convert_memstate_to_str(mem_lvl), get_memcg_info(cgroup)->threshold_mb[mem_lvl]);
1817                 }
1818         }
1819
1820         _I("[LMK] set number of max victims as %d", num_max_victims);
1821         _I("[LMK] set threshold leave to %u MB", get_root_memcg_info()->threshold_leave_mb);
1822         _I("[LMK] set proactive threshold to %u MB", proactive_threshold_mb);
1823         _I("[LMK] set proactive low memory killer leave to %u MB", proactive_leave_mb);
1824
1825         /* print info of POPUP section */
1826         _I("[POPUP] oom popup is %s", oom_popup_enable == true ? "enabled" : "disabled");
1827 }
1828
1829 #include "file-helper.h"
1830
1831 /* To Do: should we need lowmem_fd_start, lowmem_fd_stop ?? */
1832 static int lowmem_init(void)
1833 {
1834         int ret = RESOURCED_ERROR_NONE;
1835
1836         _D("resourced memory init start");
1837
1838         /* init memcg */
1839         ret = cgroup_make_full_subdir(MEMCG_PATH);
1840         ret_value_msg_if(ret < 0, ret, "memory cgroup init failed\n");
1841         memcg_params_init();
1842
1843         setup_memcg_params();
1844
1845         /* default configuration */
1846         load_configs(MEM_CONF_FILE);
1847
1848         /* this function should be called after parsing configurations */
1849         memcg_write_limiter_params();
1850         print_mem_configs();
1851
1852         /* make a worker thread called low memory killer */
1853         ret = lowmem_activate_worker();
1854         if (ret) {
1855                 _E("[LMK] oom thread create failed\n");
1856                 return ret;
1857         }
1858
1859         /* register threshold and event fd */
1860         ret = lowmem_press_setup_eventfd();
1861         if (ret) {
1862                 _E("[MEMORY-LIMIT] eventfd setup failed");
1863                 return ret;
1864         }
1865
1866         lowmem_dbus_init();
1867         lowmem_limit_init();
1868         lowmem_system_init();
1869
1870         register_notifier(RESOURCED_NOTIFIER_APP_PRELAUNCH, lowmem_prelaunch_handler);
1871         register_notifier(RESOURCED_NOTIFIER_MEM_CONTROL, lowmem_control_handler);
1872
1873         return ret;
1874 }
1875
1876 static int lowmem_exit(void)
1877 {
1878         if (strncmp(event_level, MEMCG_DEFAULT_EVENT_LEVEL, sizeof(MEMCG_DEFAULT_EVENT_LEVEL)))
1879                 free(event_level);
1880
1881         lowmem_deactivate_worker();
1882         lowmem_limit_exit();
1883         lowmem_system_exit();
1884
1885         unregister_notifier(RESOURCED_NOTIFIER_APP_PRELAUNCH, lowmem_prelaunch_handler);
1886         unregister_notifier(RESOURCED_NOTIFIER_MEM_CONTROL, lowmem_control_handler);
1887
1888         return RESOURCED_ERROR_NONE;
1889 }
1890
1891 static int resourced_memory_init(void *data)
1892 {
1893         lowmem_ops = &memory_modules_ops;
1894         return lowmem_init();
1895 }
1896
1897 static int resourced_memory_finalize(void *data)
1898 {
1899         return lowmem_exit();
1900 }
1901
1902 void lowmem_change_memory_state(int state, int force)
1903 {
1904         int mem_state;
1905
1906         if (force) {
1907                 mem_state = state;
1908         } else {
1909                 unsigned int available_mb = proc_get_mem_available();
1910                 mem_state = check_mem_state(available_mb);
1911         }
1912
1913         lowmem_trigger_memory_state_action(mem_state);
1914 }
1915
1916 unsigned long lowmem_get_ktotalram(void)
1917 {
1918         return totalram_kb;
1919 }
1920
1921 unsigned long long lowmem_get_totalram(void)
1922 {
1923         return totalram_bytes;
1924 }
1925
1926 void lowmem_restore_memcg(struct proc_app_info *pai)
1927 {
1928         char *cgpath;
1929         int index, ret;
1930         struct cgroup *cgroup = NULL;
1931         struct memcg_info *mi = NULL;
1932         pid_t pid = pai->main_pid;
1933
1934         ret = cgroup_pid_get_path("memory", pid, &cgpath);
1935         if (ret < 0)
1936                 return;
1937
1938         for (index = CGROUP_END-1; index >= CGROUP_ROOT; index--) {
1939                 cgroup = get_cgroup_tree(index);
1940                 if (!cgroup)
1941                         continue;
1942
1943                 mi = cgroup->memcg_info;
1944                 if (!mi)
1945                         continue;
1946
1947                 if (!strcmp(cgroup->hashname, ""))
1948                         continue;
1949                 if (strstr(cgpath, cgroup->hashname))
1950                         break;
1951         }
1952         pai->memory.memcg_idx = index;
1953         pai->memory.memcg_info = mi;
1954         if(strstr(cgpath, pai->appid))
1955                 pai->memory.use_mem_limit = true;
1956
1957         free(cgpath);
1958 }
1959
1960 static struct module_ops memory_modules_ops = {
1961         .priority       = MODULE_PRIORITY_HIGH,
1962         .name           = "lowmem",
1963         .init           = resourced_memory_init,
1964         .exit           = resourced_memory_finalize,
1965 };
1966
1967 MODULE_REGISTER(&memory_modules_ops)