Remove useless source code
[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;
183 static unsigned proactive_leave;
184 static unsigned lmk_start_threshold;
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;
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       = __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 static void memory_cgroup_proactive_lmk_act(enum cgroup_type type, struct memcg_info *mi);
347 /* low memory action function */
348 static void high_mem_act(void);
349 static void swap_activate_act(void);
350 static void swap_compact_act(void);
351 static void lmk_act(void);
352
353
354 static size_t cur_mem_state = MEM_LEVEL_HIGH;
355 static int num_max_victims = MAX_MEMORY_CGROUP_VICTIMS;
356 static int num_vict_between_check = MAX_VICTIMS_BETWEEN_CHECK;
357
358 static unsigned long totalram;
359 static unsigned long ktotalram;
360
361 static struct module_ops memory_modules_ops;
362 static const struct module_ops *lowmem_ops;
363 static bool oom_popup_enable;
364 static bool oom_popup;
365 static bool memcg_swap_status;
366 static bool bg_reclaim;
367 static int fragmentation_size;
368
369 static const char *convert_cgroup_type_to_str(int type)
370 {
371         static const char *type_table[] =
372         {"/", "VIP", "High", "Medium", "Lowest"};
373         if (type >= CGROUP_ROOT && type <= CGROUP_LOW)
374                 return type_table[type];
375         else
376                 return "Error";
377 }
378
379 static const char *convert_status_to_str(int status)
380 {
381         static const char *status_table[] =
382         {"none", "done", "drop", "cont", "retry", "next_type"};
383         if(status >= LOWMEM_RECLAIM_NONE && status <= LOWMEM_RECLAIM_NEXT_TYPE)
384                 return status_table[status];
385         return "error status";
386 }
387
388 static const char *convert_memstate_to_str(int mem_state)
389 {
390         static const char *state_table[] = {"mem high", "mem medium",
391                 "mem low", "mem critical", "mem oom",};
392         if (mem_state >= 0 && mem_state < MEM_LEVEL_MAX)
393                 return state_table[mem_state];
394         return "";
395 }
396
397 static int lowmem_launch_oompopup(void)
398 {
399         GVariantBuilder *const gv_builder = g_variant_builder_new(G_VARIANT_TYPE("a{ss}"));
400         g_variant_builder_add(gv_builder, "{ss}", "_SYSPOPUP_CONTENT_", "lowmemory_oom");
401
402         GVariant *const params = g_variant_new("(a{ss})", gv_builder);
403         g_variant_builder_unref(gv_builder);
404
405         int ret = d_bus_call_method_sync_gvariant(SYSTEM_POPUP_BUS_NAME,
406                 SYSTEM_POPUP_PATH_SYSTEM, SYSTEM_POPUP_IFACE_SYSTEM,
407                 "PopupLaunch", params);
408
409         g_variant_unref(params);
410
411         return ret;
412 }
413
414 static inline void get_total_memory(void)
415 {
416         struct sysinfo si;
417         if (totalram)
418                 return;
419
420         if (!sysinfo(&si)) {
421                 totalram = si.totalram;
422                 ktotalram = BYTE_TO_KBYTE(totalram);
423         }
424 }
425
426 static int lowmem_mem_usage_uss(pid_t pid, unsigned int *usage)
427 {
428         unsigned int uss, zram = 0;
429         int ret;
430
431         *usage = 0;
432
433         /*
434          * In lowmem we need to know memory size of processes to
435          * for terminating apps. To get most real value of usage
436          * we should use USS + ZRAM usage for selected process.
437          *
438          * Those values will contain the most approximated amount
439          * of memory that will be freed after process termination.
440          */
441         ret = proc_get_uss(pid, &uss);
442         if (ret != RESOURCED_ERROR_NONE)
443                 return ret;
444
445         if (swap_get_state() == SWAP_ON) {
446                 ret = proc_get_zram_usage(pid, &zram);
447                 /* If we don't get zram usage, it's not a problem */
448                 if (ret != RESOURCED_ERROR_NONE)
449                         zram = 0;
450         }
451         *usage = uss + zram;
452         return RESOURCED_ERROR_NONE;
453 }
454
455 unsigned int lowmem_get_task_mem_usage_rss(const struct task_info *tsk)
456 {
457         unsigned int size = 0, total_size = 0;
458         int index, ret;
459         pid_t pid;
460
461         /*
462          * If pids are allocated only when there are multiple processes with
463          * the same pgid e.g., browser and web process. Mostly, single process
464          * is used.
465          */
466         if (tsk->pids == NULL) {
467                 ret = proc_get_ram_usage(tsk->pid, &size);
468
469                 /* If there is no proc entry for given pid the process
470                  * should be abandoned during further processing
471                  */
472                 if (ret < 0)
473                         _D("failed to get rss memory usage of %d", tsk->pid);
474
475                 return size;
476         }
477
478         for (index = 0; index < tsk->pids->len; index++) {
479                 pid = g_array_index(tsk->pids, pid_t, index);
480                 ret = proc_get_ram_usage(pid, &size);
481                 if (ret != RESOURCED_ERROR_NONE)
482                         continue;
483                 total_size += size;
484         }
485
486         return total_size;
487 }
488
489 static int lowmem_kill_victim(const struct task_info *tsk,
490                 int flags, int memps_log, unsigned int *victim_size)
491 {
492         pid_t pid;
493         int ret;
494         char appname[PATH_MAX];
495         int sigterm = 0;
496         struct proc_app_info *pai;
497
498         pid = tsk->pid;
499
500         if (pid <= 0 || pid == getpid())
501                 return RESOURCED_ERROR_FAIL;
502
503         ret = proc_get_cmdline(pid, appname, sizeof appname);
504         if (ret == RESOURCED_ERROR_FAIL)
505                 return RESOURCED_ERROR_FAIL;
506
507         if (!strcmp("memps", appname) ||
508             !strcmp("crash-worker", appname) ||
509             !strcmp("system-syspopup", appname)) {
510                 _E("%s(%d) was selected, skip it", appname, pid);
511                 return RESOURCED_ERROR_FAIL;
512         }
513
514         pai = tsk->pai;
515         if (pai) {
516                 resourced_proc_status_change(PROC_CGROUP_SET_TERMINATE_REQUEST,
517                         pid, NULL, NULL, PROC_TYPE_NONE);
518
519                 if (tsk->oom_score_lru <= OOMADJ_BACKGRD_LOCKED) {
520                         sigterm = 1;
521                 } else if (tsk->oom_score_lru > OOMADJ_BACKGRD_LOCKED && tsk->oom_score_lru < OOMADJ_BACKGRD_UNLOCKED) {
522                         int app_flag = pai->flags;
523                         sigterm = app_flag & PROC_SIGTERM;
524                 }
525
526                 if (pai->memory.oom_killed)
527                         sigterm = 0;
528
529                 pai->memory.oom_killed = true;
530         }
531
532         if (sigterm)
533                 safe_kill(pid, SIGTERM);
534         else
535                 safe_kill(pid, SIGKILL);
536
537         _D("[LMK] we killed, force(%d), %d (%s) score = %d, size: rss = %u, sigterm = %d\n",
538            flags & OOM_FORCE, pid, appname, tsk->oom_score_adj,
539            tsk->size, sigterm);
540         *victim_size = tsk->size;
541
542         if (tsk->oom_score_lru > OOMADJ_FOREGRD_UNLOCKED)
543                 return RESOURCED_ERROR_NONE;
544
545         if (oom_popup_enable && !oom_popup) {
546                 lowmem_launch_oompopup();
547                 oom_popup = true;
548         }
549
550         return RESOURCED_ERROR_NONE;
551 }
552
553 /* return LOWMEM_RECLAIM_CONT when killing should be continued */
554 static int lowmem_check_kill_continued(struct task_info *tsk, int flags)
555 {
556         unsigned int available;
557
558         /*
559          * Processes with the priority higher than perceptible are killed
560          * only when the available memory is less than dynamic oom threshold.
561          */
562         if (tsk->oom_score_lru > OOMADJ_BACKGRD_PERCEPTIBLE)
563                 return LOWMEM_RECLAIM_CONT;
564
565         if (flags & (OOM_FORCE|OOM_SINGLE_SHOT)) {
566                 _I("[LMK] %d is dropped during force kill, flag=%d",
567                         tsk->pid, flags);
568                 return LOWMEM_RECLAIM_DROP;
569         }
570         available = proc_get_mem_available();
571         if (available > lmk_start_threshold) {
572                 _I("[LMK] available=%d MB, larger than %u MB, do not kill foreground",
573                         available, lmk_start_threshold);
574                 return LOWMEM_RECLAIM_RETRY;
575         }
576         return LOWMEM_RECLAIM_CONT;
577 }
578
579 static int compare_victims(const struct task_info *ta, const struct task_info *tb)
580 {
581         unsigned int pa, pb;
582
583         assert(ta != NULL);
584         assert(tb != NULL);
585         /*
586          * followed by kernel badness point calculation using heuristic.
587          * oom_score_adj is normalized by its unit, which varies -1000 ~ 1000.
588          */
589         pa = ta->oom_score_lru * (ktotalram / 2000) + ta->size;
590         pb = tb->oom_score_lru * (ktotalram / 2000) + tb->size;
591
592         return pb - pa;
593 }
594
595 static void lowmem_free_task_info_array(GArray *array)
596 {
597         int i;
598
599         for (i = 0; i < array->len; i++) {
600                 struct task_info *tsk;
601
602                 tsk = &g_array_index(array, struct task_info, i);
603                 if (tsk->pids)
604                         g_array_free(tsk->pids, true);
605         }
606
607         g_array_free(array, true);
608 }
609
610 static inline int is_dynamic_process_killer(int flags)
611 {
612         return (flags & OOM_FORCE) && !(flags & OOM_NOMEMORY_CHECK);
613 }
614
615 static unsigned int is_memory_recovered(unsigned int *avail, unsigned int thres)
616 {
617         unsigned int available = proc_get_mem_available();
618         unsigned int should_be_freed = 0;
619
620         if (available < thres)
621                 should_be_freed = thres - available;
622         /*
623          * free THRESHOLD_MARGIN more than real should be freed,
624          * because launching app is consuming up the memory.
625          */
626         if (should_be_freed > 0)
627                 should_be_freed += THRESHOLD_MARGIN;
628
629         *avail = available;
630
631         return should_be_freed;
632 }
633
634 static int lowmem_get_pids_proc(GArray *pids)
635 {
636         DIR *dp;
637         struct dirent *dentry;
638
639         dp = opendir("/proc");
640         if (!dp) {
641                 _E("fail to open /proc");
642                 return RESOURCED_ERROR_FAIL;
643         }
644         while ((dentry = readdir(dp)) != NULL) {
645                 struct task_info tsk;
646                 pid_t pid = 0, pgid = 0;
647                 int oom = 0;
648
649                 if (!isdigit(dentry->d_name[0]))
650                         continue;
651
652                 pid = (pid_t)atoi(dentry->d_name);
653                 if (pid < 1)
654                         /* skip invalid pids or kernel processes */
655                         continue;
656
657                 pgid = getpgid(pid);
658                 if (pgid < 1)
659                         continue;
660
661                 if(is_app(pid) != 1)
662                         continue;
663
664                 if (proc_get_oom_score_adj(pid, &oom) < 0) {
665                         _D("pid(%d) was already terminated", pid);
666                         continue;
667                 }
668
669                 /* VIP pids should be excluded from the LMK list */
670                 if (cgroup_get_type(oom) == CGROUP_VIP)
671                         continue;
672
673                 /*
674                  * Check whether this array includes applications or not.
675                  * If it doesn't require to get applications
676                  * and pid has been already included in pai,
677                  * skip to append.
678                  */
679                 if (oom > OOMADJ_SU && oom <= OOMADJ_APP_MAX)
680                         continue;
681
682                 /*
683                  * Currently, for tasks in the memory cgroup,
684                  * do not consider multiple tasks with one pgid.
685                  */
686                 tsk.pid = pid;
687                 tsk.pgid = pgid;
688                 tsk.oom_score_adj = oom;
689                 tsk.oom_score_lru = oom;
690                 tsk.pids = NULL;
691                 tsk.size = lowmem_get_task_mem_usage_rss(&tsk);
692                 tsk.pai = NULL;
693
694                 g_array_append_val(pids, tsk);
695         }
696
697         closedir(dp);
698         return RESOURCED_ERROR_NONE;
699 }
700
701 /**
702  * @brief Terminate up to max_victims processes after finding them from pai.
703         It depends on proc_app_info lists
704         and it also reference systemservice cgroup
705         because some processes in this group don't have proc_app_info.
706  *
707  * @max_victims:            max number of processes to be terminated
708  * @start_oom:      find victims from start oom adj score value
709  * @end_oom: find victims to end oom adj score value
710  * @should_be_freed: amount of memory to be reclaimed (in MB)
711  * @total_size[out]: total size of possibly reclaimed memory (required)
712  * @completed:      final outcome (optional)
713  * @threshold:          desired value of memory available
714  */
715 static int lowmem_kill_victims(int max_victims,
716         int start_oom, int end_oom, unsigned should_be_freed, int flags,
717         unsigned int *total_size, int *completed, int threshold)
718 {
719         int total_count = 0;
720         GSList *proc_app_list = NULL;
721         int i, ret, victim = 0;
722         unsigned int victim_size = 0;
723         unsigned int total_victim_size = 0;
724         int status = LOWMEM_RECLAIM_NONE;
725         GArray *candidates = NULL;
726         GSList *iter, *iterchild;
727         struct proc_app_info *pai = NULL;
728         int oom_score_adj;
729         int should_be_freed_kb = MBYTE_TO_KBYTE(should_be_freed);
730
731         candidates = g_array_new(false, false, sizeof(struct task_info));
732
733         proc_app_list = proc_app_list_open();
734         gslist_for_each_item(iter, proc_app_list) {
735                 struct task_info ti;
736
737                 total_count++;
738                 pai = (struct proc_app_info *)iter->data;
739                 if (!pai->main_pid)
740                         continue;
741
742                 oom_score_adj = pai->memory.oom_score_adj;
743                 if (oom_score_adj > end_oom || oom_score_adj < start_oom)
744                         continue;
745
746                 if ((flags & OOM_REVISE) && pai->memory.oom_killed)
747                         continue;
748
749                 ti.pid = pai->main_pid;
750                 ti.pgid = getpgid(ti.pid);
751                 ti.oom_score_adj = oom_score_adj;
752                 ti.pai = pai;
753
754                 /*
755                  * Before oom_score_adj of favourite (oom_score = 270) applications is
756                  * independent of lru_state, now we consider lru_state, while
757                  * killing favourite process.
758                  */
759
760                 if (oom_score_adj == OOMADJ_FAVORITE && pai->lru_state >= PROC_BACKGROUND)
761                         ti.oom_score_lru = OOMADJ_FAVORITE + OOMADJ_FAVORITE_APP_INCREASE * pai->lru_state;
762                 else
763                         ti.oom_score_lru = oom_score_adj;
764
765                 if (pai->childs) {
766                         ti.pids = g_array_new(false, false, sizeof(pid_t));
767                         g_array_append_val(ti.pids, ti.pid);
768                         gslist_for_each_item(iterchild, pai->childs) {
769                                 pid_t child = GPOINTER_TO_PID(iterchild->data);
770                                 g_array_append_val(ti.pids, child);
771                         }
772                 } else
773                         ti.pids = NULL;
774
775                 g_array_append_val(candidates, ti);
776         }
777
778         proc_app_list_close();
779
780         if (!candidates->len) {
781                 status = LOWMEM_RECLAIM_NEXT_TYPE;
782                 goto leave;
783         }
784         else {
785                 _D("[LMK] candidate ratio=%d/%d", candidates->len, total_count);
786         }
787
788         for (i = 0; i < candidates->len; i++) {
789                 struct task_info *tsk;
790
791                 tsk = &g_array_index(candidates, struct task_info, i);
792                 tsk->size = lowmem_get_task_mem_usage_rss(tsk);
793         }
794
795         /*
796          * In case of start_oom == OOMADJ_SU,
797          * we're going to try to kill some of processes in /proc
798          * to handle low memory situation.
799          * It can find malicious system process even though it has low oom score.
800          */
801         if (start_oom == OOMADJ_SU)
802                 lowmem_get_pids_proc(candidates);
803
804         g_array_sort(candidates, (GCompareFunc)compare_victims);
805
806         for (i = 0; i < candidates->len; i++) {
807                 struct task_info *tsk;
808
809                 if (i >= max_victims) {
810                         status = LOWMEM_RECLAIM_NEXT_TYPE;
811                         break;
812                 }
813
814                 /*
815                  * Available memory is checking only every
816                  * num_vict_between_check process for reducing burden.
817                  */
818                 if (!(i % num_vict_between_check)) {
819                         if (proc_get_mem_available() > threshold) {
820                                 status = LOWMEM_RECLAIM_DONE;
821                                 break;
822                         }
823                 }
824
825                 if (!(flags & OOM_NOMEMORY_CHECK) &&
826                     total_victim_size >= should_be_freed_kb) {
827                         _D("[LMK] victim=%d, max_victims=%d, total_size=%uKB",
828                                 victim, max_victims, total_victim_size);
829                         status = LOWMEM_RECLAIM_DONE;
830                         break;
831                 }
832
833                 tsk = &g_array_index(candidates, struct task_info, i);
834
835                 status = lowmem_check_kill_continued(tsk, flags);
836                 if (status != LOWMEM_RECLAIM_CONT)
837                         break;
838
839                 _I("[LMK] select victims from proc_app_list pid(%d) with oom_score_adj(%d)\n", tsk->pid, tsk->oom_score_adj);
840
841                 ret = lowmem_kill_victim(tsk, flags, i, &victim_size);
842                 if (ret != RESOURCED_ERROR_NONE)
843                         continue;
844                 victim++;
845                 total_victim_size += victim_size;
846         }
847
848 leave:
849         lowmem_free_task_info_array(candidates);
850         *total_size = total_victim_size;
851         if(*completed != LOWMEM_RECLAIM_CONT)
852                 *completed = status;
853         else
854                 *completed = LOWMEM_RECLAIM_NEXT_TYPE;
855         return victim;
856 }
857
858 static int calculate_range_of_oom(enum cgroup_type type, int *min, int *max)
859 {
860         if (type == CGROUP_VIP || type >= CGROUP_END || type <= CGROUP_TOP) {
861                 _E("cgroup type (%d) is out of scope", type);
862                 return RESOURCED_ERROR_FAIL;
863         }
864
865         *max = cgroup_get_highest_oom_score_adj(type);
866         *min = cgroup_get_lowest_oom_score_adj(type);
867
868         return RESOURCED_ERROR_NONE;
869 }
870
871 static void lowmem_handle_request(struct lowmem_control *ctl)
872 {
873         int start_oom, end_oom;
874         int count = 0, victim_cnt = 0;
875         int max_victim_cnt = ctl->count;
876         int status = LOWMEM_RECLAIM_NONE;
877         unsigned int available = 0;
878         unsigned int total_size = 0;
879         unsigned int current_size = 0;
880         unsigned int reclaim_size, shortfall = 0;
881         enum cgroup_type cgroup_type = ctl->type;
882
883         available = proc_get_mem_available();
884         reclaim_size = ctl->size  > available
885                      ? ctl->size - available : 0;
886
887         if (!reclaim_size) {
888                 status = LOWMEM_RECLAIM_DONE;
889                 goto done;
890         }
891
892 retry:
893         /* Prepare LMK to start doing it's job. Check preconditions. */
894         if (calculate_range_of_oom(cgroup_type, &start_oom, &end_oom))
895                 goto done;
896
897         lmk_start_threshold = get_root_memcg_info()->threshold[MEM_LEVEL_OOM];
898         shortfall = is_memory_recovered(&available, ctl->size);
899
900         if (!shortfall || !reclaim_size) {
901                 status = LOWMEM_RECLAIM_DONE;
902                 goto done;
903         }
904
905         /* precaution */
906         current_size = 0;
907         victim_cnt = lowmem_kill_victims(max_victim_cnt, start_oom, end_oom,
908                             reclaim_size, ctl->flags, &current_size, &status, ctl->size);
909
910         if (victim_cnt) {
911                 current_size = KBYTE_TO_MBYTE(current_size);
912                 reclaim_size -= reclaim_size > current_size
913                         ? current_size : reclaim_size;
914                 total_size += current_size;
915                 count += victim_cnt;
916                 _I("[LMK] current: kill %d victims, reclaim_size=%uMB from %d to %d status=%s",
917                                 victim_cnt, current_size,
918                                 start_oom, end_oom, convert_status_to_str(status));
919         }
920
921         if ((status == LOWMEM_RECLAIM_DONE) ||
922             (status == LOWMEM_RECLAIM_DROP) ||
923             (status == LOWMEM_RECLAIM_RETRY))
924                 goto done;
925
926         /*
927          * If it doesn't finish reclaiming memory in first operation,
928                 - if flags has OOM_IN_DEPTH,
929                    try to find victims again in the active cgroup.
930                    otherwise, just return because there is no more victims in the desired cgroup.
931                 - if flags has OOM_REVISE,
932                    it means that resourced can't find victims from proc_app_list.
933                    So, it should search victims or malicious process from /proc.
934                    But searching /proc leads to abnormal behaviour.
935                    (Make sluggish or kill same victims continuously)
936                    Thus, otherwise, just return in first operation and wait some period.
937          */
938         if (cgroup_type == CGROUP_LOW) {
939                 cgroup_type = CGROUP_MEDIUM;
940                 goto retry;
941         } else if ((cgroup_type == CGROUP_MEDIUM) && (ctl->flags & OOM_IN_DEPTH)) {
942                 cgroup_type = CGROUP_HIGH;
943                 if(ctl->flags & OOM_FORCE)
944                         max_victim_cnt = FOREGROUND_VICTIMS;
945                 goto retry;
946         } else if ((cgroup_type == CGROUP_HIGH) && (ctl->flags & OOM_IN_DEPTH)) {
947                 status = LOWMEM_RECLAIM_RETRY;
948                 ctl->type = CGROUP_ROOT;
949         }
950         else if (cgroup_type == CGROUP_ROOT) {
951                 status = LOWMEM_RECLAIM_RETRY;
952         }
953 done:
954         _I("[LMK] Done: killed %d processes reclaimed=%uMB remaining=%uMB shortfall=%uMB status=%s",
955                 count, total_size, reclaim_size, shortfall, convert_status_to_str(status));
956
957         /* After we finish reclaiming it's worth to remove oldest memps logs */
958         ctl->status = status;
959 }
960
961 static void *lowmem_reclaim_worker(void *arg)
962 {
963         struct lowmem_worker *lmw = (struct lowmem_worker *)arg;
964
965         setpriority(PRIO_PROCESS, 0, OOM_KILLER_PRIORITY);
966
967         g_async_queue_ref(lmw->queue);
968
969         while (1) {
970                 int try_count = 0;
971                 struct lowmem_control *ctl;
972
973                 LOWMEM_WORKER_IDLE(lmw);
974                 /* Wait on any wake-up call */
975                 ctl = g_async_queue_pop(lmw->queue);
976
977                 if (ctl->flags & OOM_DROP)
978                         LOWMEM_DESTROY_REQUEST(ctl);
979
980                 if (!LOWMEM_WORKER_IS_ACTIVE(lmw) || !ctl)
981                         break;
982
983                 LOWMEM_WORKER_RUN(lmw);
984 process_again:
985                 _D("[LMK] %d tries", ++try_count);
986                 lowmem_handle_request(ctl);
987                 /**
988                  * Case the process failed to reclaim requested amount of memory
989                  * or still under have memory pressure - try the timeout wait.
990                  * There is a chance this will get woken-up in a better reality.
991                  */
992                 if (ctl->status == LOWMEM_RECLAIM_RETRY &&
993                     !(ctl->flags & OOM_SINGLE_SHOT)) {
994                         unsigned int available = proc_get_mem_available();
995
996                         if (available >= ctl->size) {
997                                 _I("[LMK] Memory restored: requested=%uMB available=%uMB\n",
998                                         ctl->size, available);
999                                 ctl->status = LOWMEM_RECLAIM_DONE;
1000                                 if (ctl->callback)
1001                                         ctl->callback(ctl);
1002                                 LOWMEM_DESTROY_REQUEST(ctl);
1003                                 LOWMEM_WORKER_IDLE(lmw);
1004                                 continue;
1005                         }
1006
1007                         if (LOWMEM_WORKER_IS_ACTIVE(lmw)) {
1008                                 g_usleep(LMW_RETRY_WAIT_TIMEOUT_MSEC);
1009                                 ctl->flags |= OOM_REVISE;
1010                                 goto process_again;
1011                         }
1012                 }
1013
1014                 /*
1015                  * The ctl callback would check available size again.
1016                  * And it is last point in reclaiming worker.
1017                  * Resourced sent SIGKILL signal to victim processes
1018                  * so it should wait for a some seconds until each processes returns memory.
1019                  */
1020                 g_usleep(LMW_LOOP_WAIT_TIMEOUT_MSEC);
1021                 if (ctl->callback)
1022                         ctl->callback(ctl);
1023
1024                 /* The lmk becomes the owner of all queued requests .. */
1025                 LOWMEM_DESTROY_REQUEST(ctl);
1026                 LOWMEM_WORKER_IDLE(lmw);
1027         }
1028         g_async_queue_unref(lmw->queue);
1029         pthread_exit(NULL);
1030 }
1031
1032 static void change_lowmem_state(unsigned int mem_state)
1033 {
1034         cur_mem_state = mem_state;
1035         lmk_start_threshold = get_root_memcg_info()->threshold[MEM_LEVEL_OOM];
1036
1037         resourced_notify(RESOURCED_NOTIFIER_MEM_LEVEL_CHANGED,
1038                 (void *)&cur_mem_state);
1039 }
1040
1041 /* only app can call this function
1042  * that is, service cannot call the function
1043  */
1044 static void lowmem_swap_memory(char *path)
1045 {
1046         unsigned int available;
1047
1048         if (cur_mem_state == MEM_LEVEL_HIGH)
1049                 return;
1050
1051         if (swap_get_state() != SWAP_ON)
1052                 return;
1053
1054         available = proc_get_mem_available();
1055         if (cur_mem_state != MEM_LEVEL_LOW &&
1056             available <= get_root_memcg_info()->threshold[MEM_LEVEL_LOW])
1057                 swap_activate_act();
1058
1059         resourced_notify(RESOURCED_NOTIFIER_SWAP_START, path);
1060         memcg_swap_status = true;
1061 }
1062
1063 void lowmem_trigger_swap(pid_t pid, char *path, bool move)
1064 {
1065         int error;
1066         int oom_score_adj;
1067         int lowest_oom_score_adj;
1068
1069         if (!path) {
1070                 _E("[SWAP] Unknown memory cgroup path to swap");
1071                 return;
1072         }
1073
1074         /* In this case, corresponding process will be moved to memory CGROUP_LOW.
1075          */
1076         if (move) {
1077                 error = proc_get_oom_score_adj(pid, &oom_score_adj);
1078                 if (error) {
1079                         _E("[SWAP] Cannot get oom_score_adj of pid (%d)", pid);
1080                         return;
1081                 }
1082
1083                 lowest_oom_score_adj = cgroup_get_lowest_oom_score_adj(CGROUP_LOW);
1084
1085                 if (oom_score_adj < lowest_oom_score_adj) {
1086                         oom_score_adj = lowest_oom_score_adj;
1087                         /* End of this funciton, 'lowmem_swap_memory()' funciton will be called */
1088                         proc_set_oom_score_adj(pid, oom_score_adj, find_app_info(pid));
1089                         return;
1090                 }
1091         }
1092
1093         /* Correponding process is already managed per app or service.
1094          * In addition, if some process is already located in the CGROUP_LOW, then just do swap
1095          */
1096         resourced_notify(RESOURCED_NOTIFIER_SWAP_START, path);
1097 }
1098
1099 static void memory_level_send_system_event(int lv)
1100 {
1101         bundle *b;
1102         const char *str;
1103
1104         switch (lv) {
1105                 case MEM_LEVEL_HIGH:
1106                 case MEM_LEVEL_MEDIUM:
1107                 case MEM_LEVEL_LOW:
1108                         str = EVT_VAL_MEMORY_NORMAL;
1109                         break;
1110                 case MEM_LEVEL_CRITICAL:
1111                         str = EVT_VAL_MEMORY_SOFT_WARNING;
1112                         break;
1113                 case MEM_LEVEL_OOM:
1114                         str = EVT_VAL_MEMORY_HARD_WARNING;
1115                         break;
1116                 default:
1117                         _E("Invalid state");
1118                         return;
1119         }
1120
1121         b = bundle_create();
1122         if (!b) {
1123                 _E("Failed to create bundle");
1124                 return;
1125         }
1126
1127         bundle_add_str(b, EVT_KEY_LOW_MEMORY, str);
1128         eventsystem_send_system_event(SYS_EVENT_LOW_MEMORY, b);
1129         bundle_free(b);
1130 }
1131
1132 static void high_mem_act(void)
1133 {
1134         int ret, status;
1135
1136         ret = vconf_get_int(VCONFKEY_SYSMAN_LOW_MEMORY, &status);
1137         if (ret)
1138                 _D("vconf_get_int fail %s", VCONFKEY_SYSMAN_LOW_MEMORY);
1139         if (status != VCONFKEY_SYSMAN_LOW_MEMORY_NORMAL) {
1140                 vconf_set_int(VCONFKEY_SYSMAN_LOW_MEMORY,
1141                               VCONFKEY_SYSMAN_LOW_MEMORY_NORMAL);
1142                 memory_level_send_system_event(MEM_LEVEL_HIGH);
1143         }
1144
1145         change_lowmem_state(MEM_LEVEL_HIGH);
1146
1147         if (swap_get_state() == SWAP_ON && memcg_swap_status) {
1148                 resourced_notify(RESOURCED_NOTIFIER_SWAP_UNSET_LIMIT, get_memcg_info(CGROUP_LOW));
1149                 memcg_swap_status = false;
1150         }
1151         if (proc_get_freezer_status() == CGROUP_FREEZER_PAUSED)
1152                 resourced_notify(RESOURCED_NOTIFIER_FREEZER_CGROUP_STATE,
1153                         (void *)CGROUP_FREEZER_ENABLED);
1154 }
1155
1156 static void swap_activate_act(void)
1157 {
1158         int ret, status;
1159
1160         ret = vconf_get_int(VCONFKEY_SYSMAN_LOW_MEMORY, &status);
1161         if (ret)
1162                 _E("vconf get failed %s", VCONFKEY_SYSMAN_LOW_MEMORY);
1163
1164         if (status != VCONFKEY_SYSMAN_LOW_MEMORY_NORMAL) {
1165                 vconf_set_int(VCONFKEY_SYSMAN_LOW_MEMORY,
1166                                 VCONFKEY_SYSMAN_LOW_MEMORY_NORMAL);
1167                 memory_level_send_system_event(MEM_LEVEL_LOW);
1168         }
1169         change_lowmem_state(MEM_LEVEL_LOW);
1170         if (proc_get_freezer_status() == CGROUP_FREEZER_PAUSED)
1171                 resourced_notify(RESOURCED_NOTIFIER_FREEZER_CGROUP_STATE,
1172                         (void *)CGROUP_FREEZER_ENABLED);
1173
1174         if (swap_get_state() != SWAP_ON)
1175                 resourced_notify(RESOURCED_NOTIFIER_SWAP_ACTIVATE, NULL);
1176 }
1177
1178 static void dedup_act(enum ksm_scan_mode mode)
1179 {
1180         int ret, status;
1181         int data;
1182
1183         if (dedup_get_state() != DEDUP_ONE_SHOT)
1184                 return;
1185
1186         if (proc_get_freezer_status() == CGROUP_FREEZER_PAUSED)
1187                 resourced_notify(RESOURCED_NOTIFIER_FREEZER_CGROUP_STATE,
1188                                 (void *)CGROUP_FREEZER_ENABLED);
1189
1190         if (mode == KSM_SCAN_PARTIAL) {
1191                 ret = vconf_get_int(VCONFKEY_SYSMAN_LOW_MEMORY, &status);
1192                 if (ret)
1193                         _E("vconf get failed %s", VCONFKEY_SYSMAN_LOW_MEMORY);
1194
1195                 if (status != VCONFKEY_SYSMAN_LOW_MEMORY_NORMAL) {
1196                         vconf_set_int(VCONFKEY_SYSMAN_LOW_MEMORY,
1197                                         VCONFKEY_SYSMAN_LOW_MEMORY_NORMAL);
1198                         memory_level_send_system_event(MEM_LEVEL_MEDIUM);
1199                 }
1200                 change_lowmem_state(MEM_LEVEL_MEDIUM);
1201
1202                 data = KSM_SCAN_PARTIAL;
1203                 resourced_notify(RESOURCED_NOTIFIER_DEDUP_SCAN, &data);
1204         } else if (mode == KSM_SCAN_FULL) {
1205                 data = KSM_SCAN_FULL;
1206                 resourced_notify(RESOURCED_NOTIFIER_DEDUP_SCAN, &data);
1207         }
1208 }
1209
1210 static void swap_compact_act(void)
1211 {
1212         change_lowmem_state(MEM_LEVEL_CRITICAL);
1213         resourced_notify(RESOURCED_NOTIFIER_SWAP_COMPACT, (void *)SWAP_COMPACT_MEM_LEVEL_CRITICAL);
1214         memory_level_send_system_event(MEM_LEVEL_CRITICAL);
1215 }
1216
1217 static void medium_cb(struct lowmem_control *ctl)
1218 {
1219         if (ctl->status == LOWMEM_RECLAIM_DONE)
1220                 oom_popup = false;
1221         lowmem_change_memory_state(MEM_LEVEL_HIGH, 0);
1222 }
1223
1224 static void lmk_act(void)
1225 {
1226         unsigned int available;
1227         int ret;
1228         int status = VCONFKEY_SYSMAN_LOW_MEMORY_NORMAL;
1229
1230         /*
1231          * Don't trigger reclaim worker
1232          * if it is already running
1233          */
1234         if (LOWMEM_WORKER_IS_RUNNING(&lmw))
1235                 return;
1236
1237         ret = vconf_get_int(VCONFKEY_SYSMAN_LOW_MEMORY, &status);
1238         if (ret)
1239                 _D("vconf_get_int fail %s", VCONFKEY_SYSMAN_LOW_MEMORY);
1240
1241         memory_level_send_system_event(MEM_LEVEL_OOM);
1242         if (status != VCONFKEY_SYSMAN_LOW_MEMORY_HARD_WARNING) {
1243                 if (proc_get_freezer_status() == CGROUP_FREEZER_ENABLED)
1244                         resourced_notify(RESOURCED_NOTIFIER_FREEZER_CGROUP_STATE,
1245                                 (void *)CGROUP_FREEZER_PAUSED);
1246                 vconf_set_int(VCONFKEY_SYSMAN_LOW_MEMORY,
1247                               VCONFKEY_SYSMAN_LOW_MEMORY_HARD_WARNING);
1248         }
1249         available = proc_get_mem_available();
1250
1251         change_lowmem_state(MEM_LEVEL_OOM);
1252
1253         if (available < get_root_memcg_info()->threshold_leave) {
1254                 struct lowmem_control *ctl;
1255
1256                 ctl = LOWMEM_NEW_REQUEST();
1257                 if (ctl) {
1258                         LOWMEM_SET_REQUEST(ctl, OOM_IN_DEPTH,
1259                                 CGROUP_LOW, get_root_memcg_info()->threshold_leave,
1260                                 num_max_victims, medium_cb);
1261                         lowmem_queue_request(&lmw, ctl);
1262                 }
1263         }
1264
1265         resourced_notify(RESOURCED_NOTIFIER_SWAP_COMPACT, (void *)SWAP_COMPACT_MEM_LEVEL_OOM);
1266
1267         /*
1268          * Flush resourced memory such as other processes.
1269          * Resourced can use both many fast bins and sqlite3 cache memery.
1270          */
1271         malloc_trim(0);
1272
1273         return;
1274 }
1275
1276 static void lowmem_trigger_memory_state_action(int mem_state)
1277 {
1278         /*
1279          * Check if the state we want to set is different from current
1280          * But it should except this condition if mem_state is already medium.
1281          * Otherwise, recalim worker couldn't run any more.
1282          */
1283         if (mem_state != MEM_LEVEL_OOM && cur_mem_state == mem_state)
1284                 return;
1285
1286         switch (mem_state) {
1287         case MEM_LEVEL_HIGH:
1288                 high_mem_act();
1289                 break;
1290         case MEM_LEVEL_MEDIUM:
1291                 dedup_act(KSM_SCAN_PARTIAL);
1292                 break;
1293         case MEM_LEVEL_LOW:
1294                 swap_activate_act();
1295                 break;
1296         case MEM_LEVEL_CRITICAL:
1297                 dedup_act(KSM_SCAN_FULL);
1298                 swap_compact_act();
1299                 break;
1300         case MEM_LEVEL_OOM:
1301                 lmk_act();
1302                 break;
1303         default:
1304                 assert(0);
1305         }
1306 }
1307
1308 static void lowmem_dump_cgroup_procs(struct memcg_info *mi)
1309 {
1310         int i;
1311         unsigned int size;
1312         pid_t pid;
1313         GArray *pids_array = NULL;
1314
1315         cgroup_get_pids(mi->name, &pids_array);
1316
1317         for (i = 0; i < pids_array->len; i++) {
1318                 pid = g_array_index(pids_array, pid_t, i);
1319                 lowmem_mem_usage_uss(pid, &size);
1320                 _I("pid = %d, size = %u KB", pid, size);
1321         }
1322         g_array_free(pids_array, true);
1323 }
1324
1325 static void memory_cgroup_proactive_lmk_act(enum cgroup_type type, struct memcg_info *mi)
1326 {
1327         struct lowmem_control *ctl;
1328
1329         /* To Do: only start to kill fg victim when no pending fg victim */
1330         lowmem_dump_cgroup_procs(mi);
1331
1332         ctl = LOWMEM_NEW_REQUEST();
1333         if (ctl) {
1334                 LOWMEM_SET_REQUEST(ctl, OOM_SINGLE_SHOT | OOM_IN_DEPTH, type,
1335                         mi->oomleave, num_max_victims, NULL);
1336                 lowmem_queue_request(&lmw, ctl);
1337         }
1338 }
1339
1340 static unsigned int check_mem_state(unsigned int available)
1341 {
1342         int mem_state;
1343         for (mem_state = MEM_LEVEL_MAX - 1; mem_state > MEM_LEVEL_HIGH; mem_state--) {
1344                 if (mem_state != MEM_LEVEL_OOM && available <= get_root_memcg_info()->threshold[mem_state])
1345                         break;
1346                 else if (mem_state == MEM_LEVEL_OOM && available <= lmk_start_threshold)
1347                         break;
1348         }
1349
1350         return mem_state;
1351 }
1352
1353 /* setup memcg parameters depending on total ram size. */
1354 static void setup_memcg_params(void)
1355 {
1356         unsigned long long total_ramsize;
1357
1358         get_total_memory();
1359         total_ramsize = BYTE_TO_MBYTE(totalram);
1360
1361         _D("Total: %llu MB", total_ramsize);
1362         if (total_ramsize <= MEM_SIZE_64) {
1363                 /* set thresholds for ram size 64M */
1364                 proactive_threshold = PROACTIVE_64_THRES;
1365                 proactive_leave = PROACTIVE_64_LEAVE;
1366                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_MEDIUM, CGROUP_ROOT_64_THRES_DEDUP);
1367                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_LOW, CGROUP_ROOT_64_THRES_SWAP);
1368                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_CRITICAL, CGROUP_ROOT_64_THRES_LOW);
1369                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_OOM, CGROUP_ROOT_64_THRES_MEDIUM);
1370                 memcg_set_leave_threshold(CGROUP_ROOT, CGROUP_ROOT_64_THRES_LEAVE);
1371                 num_max_victims = CGROUP_ROOT_64_NUM_VICTIMS;
1372         } else if (total_ramsize <= MEM_SIZE_256) {
1373                 /* set thresholds for ram size 256M */
1374                 proactive_threshold = PROACTIVE_256_THRES;
1375                 proactive_leave = PROACTIVE_256_LEAVE;
1376                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_MEDIUM, CGROUP_ROOT_256_THRES_DEDUP);
1377                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_LOW, CGROUP_ROOT_256_THRES_SWAP);
1378                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_CRITICAL, CGROUP_ROOT_256_THRES_LOW);
1379                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_OOM, CGROUP_ROOT_256_THRES_MEDIUM);
1380                 memcg_set_leave_threshold(CGROUP_ROOT, CGROUP_ROOT_256_THRES_LEAVE);
1381                 num_max_victims = CGROUP_ROOT_256_NUM_VICTIMS;
1382         } else if (total_ramsize <= MEM_SIZE_448) {
1383                 /* set thresholds for ram size 448M */
1384                 proactive_threshold = PROACTIVE_448_THRES;
1385                 proactive_leave = PROACTIVE_448_LEAVE;
1386                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_MEDIUM, CGROUP_ROOT_448_THRES_DEDUP);
1387                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_LOW, CGROUP_ROOT_448_THRES_SWAP);
1388                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_CRITICAL, CGROUP_ROOT_448_THRES_LOW);
1389                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_OOM, CGROUP_ROOT_448_THRES_MEDIUM);
1390                 memcg_set_leave_threshold(CGROUP_ROOT, CGROUP_ROOT_448_THRES_LEAVE);
1391                 num_max_victims = CGROUP_ROOT_448_NUM_VICTIMS;
1392         } else if (total_ramsize <= MEM_SIZE_512) {
1393                 /* set thresholds for ram size 512M */
1394                 proactive_threshold = PROACTIVE_512_THRES;
1395                 proactive_leave = PROACTIVE_512_LEAVE;
1396                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_MEDIUM, CGROUP_ROOT_512_THRES_DEDUP);
1397                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_LOW, CGROUP_ROOT_512_THRES_SWAP);
1398                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_CRITICAL, CGROUP_ROOT_512_THRES_LOW);
1399                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_OOM, CGROUP_ROOT_512_THRES_MEDIUM);
1400                 memcg_set_leave_threshold(CGROUP_ROOT, CGROUP_ROOT_512_THRES_LEAVE);
1401                 num_max_victims = CGROUP_ROOT_512_NUM_VICTIMS;
1402         }  else if (total_ramsize <= MEM_SIZE_768) {
1403                 /* set thresholds for ram size 512M */
1404                 proactive_threshold = PROACTIVE_768_THRES;
1405                 proactive_leave = PROACTIVE_768_LEAVE;
1406                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_MEDIUM, CGROUP_ROOT_768_THRES_DEDUP);
1407                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_LOW, CGROUP_ROOT_768_THRES_SWAP);
1408                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_CRITICAL, CGROUP_ROOT_768_THRES_LOW);
1409                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_OOM, CGROUP_ROOT_768_THRES_MEDIUM);
1410                 memcg_set_leave_threshold(CGROUP_ROOT, CGROUP_ROOT_768_THRES_LEAVE);
1411                 num_max_victims = CGROUP_ROOT_768_NUM_VICTIMS;
1412         } else if (total_ramsize <= MEM_SIZE_1024) {
1413                 /* set thresholds for ram size more than 1G */
1414                 proactive_threshold = PROACTIVE_1024_THRES;
1415                 proactive_leave = PROACTIVE_1024_LEAVE;
1416                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_MEDIUM, CGROUP_ROOT_1024_THRES_DEDUP);
1417                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_LOW, CGROUP_ROOT_1024_THRES_SWAP);
1418                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_CRITICAL, CGROUP_ROOT_1024_THRES_LOW);
1419                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_OOM, CGROUP_ROOT_1024_THRES_MEDIUM);
1420                 memcg_set_leave_threshold(CGROUP_ROOT, CGROUP_ROOT_1024_THRES_LEAVE);
1421                 num_max_victims = CGROUP_ROOT_1024_NUM_VICTIMS;
1422         } else if (total_ramsize <= MEM_SIZE_2048) {
1423                 proactive_threshold = PROACTIVE_2048_THRES;
1424                 proactive_leave = PROACTIVE_2048_LEAVE;
1425                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_MEDIUM, CGROUP_ROOT_2048_THRES_DEDUP);
1426                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_LOW, CGROUP_ROOT_2048_THRES_SWAP);
1427                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_CRITICAL, CGROUP_ROOT_2048_THRES_LOW);
1428                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_OOM, CGROUP_ROOT_2048_THRES_MEDIUM);
1429                 memcg_set_leave_threshold(CGROUP_ROOT, CGROUP_ROOT_2048_THRES_LEAVE);
1430                 num_max_victims = CGROUP_ROOT_2048_NUM_VICTIMS;
1431         } else {
1432                 proactive_threshold = PROACTIVE_3072_THRES;
1433                 proactive_leave = PROACTIVE_3072_LEAVE;
1434                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_MEDIUM, CGROUP_ROOT_3072_THRES_DEDUP);
1435                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_LOW, CGROUP_ROOT_3072_THRES_SWAP);
1436                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_CRITICAL, CGROUP_ROOT_3072_THRES_LOW);
1437                 memcg_set_threshold(CGROUP_ROOT, MEM_LEVEL_OOM, CGROUP_ROOT_3072_THRES_MEDIUM);
1438                 memcg_set_leave_threshold(CGROUP_ROOT, CGROUP_ROOT_3072_THRES_LEAVE);
1439                 num_max_victims = CGROUP_ROOT_3072_NUM_VICTIMS;
1440         }
1441 }
1442
1443 static void lowmem_move_memcgroup(int pid, int next_oom_score_adj, struct proc_app_info *pai)
1444 {
1445         int cur_oom_score_adj;
1446         int cur_memcg_idx;
1447         struct memcg_info *mi;
1448         int next_memcg_idx = cgroup_get_type(next_oom_score_adj);
1449
1450         if(next_memcg_idx < CGROUP_VIP || next_memcg_idx > CGROUP_LOW) {
1451                 _E("cgroup type (%d) should not be called", next_memcg_idx);
1452                 return;
1453         }
1454         mi = get_memcg_info(next_memcg_idx);
1455
1456         if (!mi) {
1457                 return;
1458         }
1459
1460         if (!pai) {
1461                 cgroup_write_pid_fullpath(mi->name, pid);
1462                 return;
1463         }
1464
1465         /* parent pid */
1466         if (pai->main_pid == pid) {
1467                 cur_oom_score_adj = pai->memory.oom_score_adj;
1468                 cur_memcg_idx = cgroup_get_type(cur_oom_score_adj);
1469
1470                 /* -1 means that this pid is not yet registered at the memory cgroup
1471                  * plz, reference proc_create_app_info function
1472                  */
1473                 if (cur_oom_score_adj != OOMADJ_APP_MAX + 10) {
1474                         /* VIP processes should not be asked to move. */
1475                         if (cur_memcg_idx <= CGROUP_VIP) {
1476                                 _E("[DEBUG] current cgroup (%s) cannot be VIP or Root", convert_cgroup_type_to_str(cur_memcg_idx));
1477                                 return;
1478                         }
1479                 }
1480
1481                 _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));
1482
1483                 if (cur_oom_score_adj == next_oom_score_adj) {
1484                         _D("next oom_score_adj (%d) is same with current one", next_oom_score_adj);
1485                         return;
1486                 }
1487
1488                 proc_set_process_memory_state(pai, next_memcg_idx, mi, next_oom_score_adj);
1489
1490                 if (!lowmem_limit_move_cgroup(pai))
1491                         return;
1492
1493                 if(cur_memcg_idx == next_memcg_idx)
1494                         return;
1495
1496                 cgroup_write_pid_fullpath(mi->name, pid);
1497                 if (next_memcg_idx == CGROUP_LOW)
1498                         lowmem_swap_memory(get_memcg_info(CGROUP_LOW)->name);
1499         }
1500         /* child pid */
1501         else {
1502                 if (pai->memory.use_mem_limit)
1503                         return;
1504
1505                 cgroup_write_pid_fullpath(mi->name, pid);
1506         }
1507 }
1508
1509 static int lowmem_activate_worker(void)
1510 {
1511         int ret = RESOURCED_ERROR_NONE;
1512
1513         if (LOWMEM_WORKER_IS_ACTIVE(&lmw)) {
1514                 return ret;
1515         }
1516
1517         lmw.queue = g_async_queue_new_full(lowmem_request_destroy);
1518         if (!lmw.queue) {
1519                 _E("Failed to create request queue\n");
1520                 return RESOURCED_ERROR_FAIL;
1521         }
1522         LOWMEM_WORKER_ACTIVATE(&lmw);
1523         ret = pthread_create(&lmw.worker_thread, NULL,
1524                 (void *)lowmem_reclaim_worker, (void *)&lmw);
1525         if (ret) {
1526                 LOWMEM_WORKER_DEACTIVATE(&lmw);
1527                 _E("Failed to create LMK thread: %d\n", ret);
1528         } else {
1529                 pthread_detach(lmw.worker_thread);
1530                 ret = RESOURCED_ERROR_NONE;
1531         }
1532         return ret;
1533 }
1534
1535 static void lowmem_deactivate_worker(void)
1536 {
1537         struct lowmem_control *ctl;
1538
1539         if (!LOWMEM_WORKER_IS_ACTIVE(&lmw))
1540                 return;
1541
1542         LOWMEM_WORKER_DEACTIVATE(&lmw);
1543         lowmem_drain_queue(&lmw);
1544
1545         ctl = LOWMEM_NEW_REQUEST();
1546         if (!ctl) {
1547                 _E("Critical - g_slice alloc failed - Lowmem cannot be deactivated");
1548                 return;
1549         }
1550         ctl->flags = OOM_DROP;
1551         g_async_queue_push(lmw.queue, ctl);
1552         g_async_queue_unref(lmw.queue);
1553 }
1554
1555 static int lowmem_press_eventfd_read(int fd)
1556 {
1557         uint64_t dummy_state;
1558
1559         return read(fd, &dummy_state, sizeof(dummy_state));
1560 }
1561
1562 static void lowmem_press_root_cgroup_handler(void)
1563 {
1564         static unsigned int prev_available;
1565         unsigned int available;
1566         int mem_state;
1567
1568         available = proc_get_mem_available();
1569         if (prev_available == available)
1570                 return;
1571
1572         mem_state = check_mem_state(available);
1573         lowmem_trigger_memory_state_action(mem_state);
1574
1575         prev_available = available;
1576 }
1577
1578 static void lowmem_press_cgroup_handler(enum cgroup_type type, struct memcg_info *mi)
1579 {
1580         unsigned int usage, threshold;
1581         int ret;
1582
1583         ret = memcg_get_anon_usage(mi->name, &usage);
1584         if (ret) {
1585                 _D("getting anonymous memory usage fails");
1586                 return;
1587         }
1588
1589         threshold = mi->threshold[MEM_LEVEL_OOM];
1590         if (usage >= threshold)
1591                 memory_cgroup_proactive_lmk_act(type, mi);
1592         else
1593                 _I("anon page %u MB < medium threshold %u MB", BYTE_TO_MBYTE(usage),
1594                                 BYTE_TO_MBYTE(threshold));
1595 }
1596
1597 static bool lowmem_press_eventfd_handler(int fd, void *data)
1598 {
1599         struct memcg_info *mi;
1600         enum cgroup_type type = CGROUP_ROOT;
1601
1602         // FIXME: probably shouldn't get ignored
1603         if (lowmem_press_eventfd_read(fd) < 0)
1604                 _E("Failed to read lowmem press event, %m\n");
1605
1606         for (type = CGROUP_ROOT; type < CGROUP_END; type++) {
1607                 if (!get_cgroup_tree(type) || !get_memcg_info(type))
1608                         continue;
1609                 mi = get_memcg_info(type);
1610                 if (fd == mi->evfd) {
1611                         /* call low memory handler for this memcg */
1612                         if (type == CGROUP_ROOT)
1613                                 lowmem_press_root_cgroup_handler();
1614                         else {
1615                                 lowmem_press_cgroup_handler(type, mi);
1616                         }
1617                         return true;
1618                 }
1619         }
1620
1621         return true;
1622 }
1623
1624 static int lowmem_press_register_eventfd(struct memcg_info *mi)
1625 {
1626         int evfd;
1627         const char *name = mi->name;
1628         static fd_handler_h handler;
1629
1630         if (mi->threshold[MEM_LEVEL_OOM] == LOWMEM_THRES_INIT)
1631                 return 0;
1632
1633         evfd = memcg_set_eventfd(name, MEMCG_EVENTFD_MEMORY_PRESSURE,
1634                         event_level);
1635
1636         if (evfd < 0) {
1637                 int saved_errno = errno;
1638                 _E("fail to register event press fd %s cgroup", name);
1639                 return -saved_errno;
1640         }
1641
1642         mi->evfd = evfd;
1643
1644         _I("register event fd success for %s cgroup", name);
1645         add_fd_read_handler(evfd, lowmem_press_eventfd_handler, NULL, NULL, &handler);
1646         return 0;
1647 }
1648
1649 static int lowmem_press_setup_eventfd(void)
1650 {
1651         unsigned int i;
1652
1653         for (i = CGROUP_ROOT; i < CGROUP_END; i++) {
1654                 if (!get_use_hierarchy(i))
1655                         continue;
1656
1657                 lowmem_press_register_eventfd(get_memcg_info(i));
1658         }
1659         return RESOURCED_ERROR_NONE;
1660 }
1661
1662 static void lowmem_force_reclaim_cb(struct lowmem_control *ctl)
1663 {
1664         lowmem_change_memory_state(MEM_LEVEL_HIGH, 0);
1665 }
1666
1667 int lowmem_trigger_reclaim(int flags, int victims, enum cgroup_type type, int threshold)
1668 {
1669         struct lowmem_control *ctl = LOWMEM_NEW_REQUEST();
1670
1671         if (!ctl)
1672                 return -ENOMEM;
1673
1674         flags |= OOM_FORCE | OOM_IN_DEPTH | OOM_SINGLE_SHOT;
1675         victims = victims > 0 ? victims : MAX_MEMORY_CGROUP_VICTIMS;
1676         type = type > 0 ? type : CGROUP_LOW;
1677         threshold = threshold > 0 ? threshold : get_root_memcg_info()->threshold_leave;
1678
1679         lowmem_change_memory_state(MEM_LEVEL_CRITICAL, 1);
1680         LOWMEM_SET_REQUEST(ctl, flags,
1681                 type, threshold, victims,
1682                 lowmem_force_reclaim_cb);
1683         lowmem_queue_request(&lmw, ctl);
1684
1685         return 0;
1686 }
1687
1688 void lowmem_trigger_swap_reclaim(enum cgroup_type type, int swap_size)
1689 {
1690         int size, victims;
1691
1692         victims = num_max_victims  > MAX_PROACTIVE_HIGH_VICTIMS
1693                                  ? MAX_PROACTIVE_HIGH_VICTIMS : num_max_victims;
1694
1695         size = get_root_memcg_info()->threshold_leave + BYTE_TO_MBYTE(swap_size);
1696         _I("reclaim from swap module, type : %d, size : %d, victims: %d", type, size, victims);
1697         lowmem_trigger_reclaim(0, victims, type, size);
1698 }
1699
1700 bool lowmem_fragmentated(void)
1701 {
1702         struct buddyinfo bi;
1703         int ret;
1704
1705         ret = proc_get_buddyinfo("Normal", &bi);
1706         if (ret < 0)
1707                 return false;
1708
1709         /*
1710          * The fragmentation_size is the minimum count of order-2 pages in "Normal" zone.
1711          * If total buddy pages is smaller than fragmentation_size,
1712          * resourced will detect kernel memory is fragmented.
1713          * Default value is zero in low memory device.
1714          */
1715         if (bi.page[PAGE_32K] + (bi.page[PAGE_64K] << 1) + (bi.page[PAGE_128K] << 2) +
1716                 (bi.page[PAGE_256K] << 3) < fragmentation_size) {
1717                 _I("fragmentation detected, need to execute proactive oom killer");
1718                 return true;
1719         }
1720         return false;
1721 }
1722
1723 static void lowmem_proactive_oom_killer(int flags, char *appid)
1724 {
1725         unsigned int before;
1726         int victims;
1727
1728         before = proc_get_mem_available();
1729
1730         /* If memory state is medium or normal, just return and kill in oom killer */
1731         if (before < get_root_memcg_info()->threshold[MEM_LEVEL_OOM] || before > proactive_leave)
1732                 return;
1733
1734         victims = num_max_victims  > MAX_PROACTIVE_HIGH_VICTIMS
1735                                  ? MAX_PROACTIVE_HIGH_VICTIMS : num_max_victims;
1736
1737 #ifdef HEART_SUPPORT
1738         /*
1739          * This branch is used only when HEART module is compiled in and
1740          * it's MEMORY module must be enabled. Otherwise this is skipped.
1741          */
1742         struct heart_memory_data *md = heart_memory_get_memdata(appid, DATA_LATEST);
1743         if (md) {
1744                 unsigned int rss, after, size;
1745
1746                 rss = KBYTE_TO_MBYTE(md->avg_rss);
1747
1748                 free(md);
1749
1750                 after = before - rss;
1751                 /*
1752                  * after launching app, ensure that available memory is
1753                  * above threshold_leave
1754                  */
1755                 if (after >= get_root_memcg_info()->threshold[MEM_LEVEL_OOM])
1756                         return;
1757
1758                 if (proactive_threshold - rss >= get_root_memcg_info()->threshold[MEM_LEVEL_OOM])
1759                         size = proactive_threshold;
1760                 else
1761                         size = rss + get_root_memcg_info()->threshold[MEM_LEVEL_OOM] + THRESHOLD_MARGIN;
1762
1763                 _D("history based proactive LMK : avg rss %u, available %u required = %u MB",
1764                         rss, before, size);
1765                 lowmem_trigger_reclaim(0, victims, CGROUP_LOW, size);
1766
1767                 return;
1768         }
1769 #endif
1770
1771         /*
1772          * When there is no history data for the launching app,
1773          * it is necessary to check current fragmentation state or application manifest file.
1774          * So, resourced feels proactive LMK is required, run oom killer based on dynamic
1775          * threshold.
1776          */
1777         if (lowmem_fragmentated())
1778                 goto reclaim;
1779
1780         /*
1781          * run proactive oom killer only when available is larger than
1782          * dynamic process threshold
1783          */
1784         if (!proactive_threshold || before >= proactive_threshold)
1785                 return;
1786
1787         if (!(flags & PROC_LARGEMEMORY))
1788                 return;
1789
1790 reclaim:
1791         /*
1792          * free THRESHOLD_MARGIN more than real should be freed,
1793          * because launching app is consuming up the memory.
1794          */
1795         _D("Run threshold based proactive LMK: memory level to reach: %u\n",
1796                 proactive_leave + THRESHOLD_MARGIN);
1797         lowmem_trigger_reclaim(0, victims, CGROUP_LOW, proactive_leave + THRESHOLD_MARGIN);
1798 }
1799
1800 unsigned int lowmem_get_proactive_thres(void)
1801 {
1802         return proactive_threshold;
1803 }
1804
1805 static int lowmem_prelaunch_handler(void *data)
1806 {
1807         struct proc_status *ps = (struct proc_status *)data;
1808         struct proc_app_info *pai = ps->pai;
1809
1810         if (!pai || CHECK_BIT(pai->flags, PROC_SERVICEAPP))
1811                 return RESOURCED_ERROR_NONE;
1812
1813         lowmem_proactive_oom_killer(ps->pai->flags, ps->pai->appid);
1814         return RESOURCED_ERROR_NONE;
1815 }
1816
1817 int lowmem_control_handler(void *data)
1818 {
1819         struct lowmem_control_data *lowmem_data;
1820
1821         lowmem_data = (struct lowmem_control_data *)data;
1822         switch (lowmem_data->control_type) {
1823         case LOWMEM_MOVE_CGROUP:
1824                 lowmem_move_memcgroup((pid_t)lowmem_data->pid,
1825                                         lowmem_data->oom_score_adj, lowmem_data->pai);
1826                 break;
1827         default:
1828                 break;
1829         }
1830         return RESOURCED_ERROR_NONE;
1831 }
1832
1833 static int lowmem_bg_reclaim_handler(void *data)
1834 {
1835         if (swap_get_state() != SWAP_ON)
1836                 return RESOURCED_ERROR_NONE;
1837
1838         if (!bg_reclaim)
1839                 return RESOURCED_ERROR_NONE;
1840
1841         /*
1842          * Proactively reclaiming memory used by long-lived background processes
1843          * (such as widget instances) may be efficient on devices with limited
1844          * memory constraints. The pages used by such processes could be reclaimed
1845          * (if swap is enabled) earlier than they used to while minimizing the
1846          * impact on the user experience.
1847          */
1848         resourced_notify(RESOURCED_NOTIFIER_SWAP_START, get_memcg_info(CGROUP_MEDIUM)->name);
1849
1850         return RESOURCED_ERROR_NONE;
1851 }
1852
1853 static int calculate_threshold_size(double ratio)
1854 {
1855         int size = (double)totalram * ratio / 100.0;
1856         return size;
1857 }
1858
1859 static void load_configs(const char *path)
1860 {
1861         struct memcg_conf *memcg_conf = get_memcg_conf();
1862
1863         /* set MemoryGroupLimit section */
1864         for (int cgroup = CGROUP_VIP; cgroup < CGROUP_END; cgroup++) {
1865                 if (memcg_conf->cgroup_limit[cgroup] > 0.0)
1866                         memcg_info_set_limit(get_memcg_info(cgroup),
1867                                         memcg_conf->cgroup_limit[cgroup]/100.0, totalram);
1868         }
1869
1870         /* set MemoryLevelThreshold section */
1871         for (int lvl = MEM_LEVEL_MEDIUM; lvl < MEM_LEVEL_MAX; lvl++) {
1872                 if (memcg_conf->threshold[lvl].percent &&
1873                         memcg_conf->threshold[lvl].threshold > 0)
1874                         memcg_set_threshold(CGROUP_ROOT, lvl,
1875                                         calculate_threshold_size(memcg_conf->threshold[lvl].threshold));
1876                 else if (memcg_conf->threshold[lvl].threshold > 0)
1877                         memcg_set_threshold(CGROUP_ROOT, lvl,
1878                                         memcg_conf->threshold[lvl].threshold);
1879         }
1880         oom_popup_enable = memcg_conf->oom_popup;
1881
1882         /* set MemoryAppTypeLimit and MemoryAppStatusLimit section */
1883         lowmem_memory_init(memcg_conf->service.memory, memcg_conf->widget.memory,
1884                         memcg_conf->guiapp.memory, memcg_conf->background.memory);
1885         lowmem_action_init(memcg_conf->service.action, memcg_conf->widget.action,
1886                         memcg_conf->guiapp.action, memcg_conf->background.action);
1887
1888         free_memcg_conf();
1889 }
1890
1891 static void print_mem_configs(void)
1892 {
1893         /* print info of Memory section */
1894         for (int cgroup = CGROUP_VIP; cgroup < CGROUP_END; cgroup++) {
1895                 _I("[DEBUG] set memory for cgroup '%s' to %u bytes",
1896                                 convert_cgroup_type_to_str(cgroup), get_memcg_info(cgroup)->limit);
1897         }
1898
1899         for (int mem_lvl = 0; mem_lvl < MEM_LEVEL_MAX; mem_lvl++)
1900                 _I("[DEBUG] set threshold for memory level '%s' to %u MB",
1901                                 convert_memstate_to_str(mem_lvl), get_root_memcg_info()->threshold[mem_lvl]);
1902
1903         _I("[DEBUG] set number of max victims as %d", num_max_victims);
1904         _I("[DEBUG] set threshold leave to %u MB", get_root_memcg_info()->threshold_leave);
1905         _I("[DEBUG] set proactive threshold to %u MB", proactive_threshold);
1906         _I("[DEBUG] set proactive low memory killer leave to %u MB", proactive_leave);
1907
1908         /* print info of POPUP section */
1909         _I("[DEBUG] oom popup is %s", oom_popup_enable == true ? "enabled" : "disabled");
1910
1911         /* print info of BackgroundReclaim section */
1912         _I("[DEBUG] Background reclaim is %s", bg_reclaim == true ? "enabled" : "disabled");
1913 }
1914
1915 #include "file-helper.h"
1916
1917 /* To Do: should we need lowmem_fd_start, lowmem_fd_stop ?? */
1918 static int lowmem_init(void)
1919 {
1920         int ret = RESOURCED_ERROR_NONE;
1921
1922         _D("[DEBUG] resourced memory init start");
1923
1924         /* init memcg */
1925         ret = cgroup_make_full_subdir(MEMCG_PATH);
1926         ret_value_msg_if(ret < 0, ret, "memory cgroup init failed\n");
1927         memcg_params_init();
1928
1929         setup_memcg_params();
1930
1931         /* default configuration */
1932         load_configs(MEM_CONF_FILE);
1933
1934         /* this function should be called after parsing configurations */
1935         memcg_write_limiter_params();
1936         print_mem_configs();
1937
1938         /* make a worker thread called low memory killer */
1939         ret = lowmem_activate_worker();
1940         if (ret) {
1941                 _E("[DEBUG] oom thread create failed\n");
1942                 return ret;
1943         }
1944
1945         /* register threshold and event fd */
1946         ret = lowmem_press_setup_eventfd();
1947         if (ret) {
1948                 _E("[DEBUG] eventfd setup failed");
1949                 return ret;
1950         }
1951
1952         lowmem_dbus_init();
1953         lowmem_limit_init();
1954         lowmem_system_init();
1955
1956         register_notifier(RESOURCED_NOTIFIER_APP_PRELAUNCH, lowmem_prelaunch_handler);
1957         register_notifier(RESOURCED_NOTIFIER_MEM_CONTROL, lowmem_control_handler);
1958         register_notifier(RESOURCED_NOTIFIER_LCD_OFF, lowmem_bg_reclaim_handler);
1959
1960         return ret;
1961 }
1962
1963 static int lowmem_exit(void)
1964 {
1965         if (strncmp(event_level, MEMCG_DEFAULT_EVENT_LEVEL, sizeof(MEMCG_DEFAULT_EVENT_LEVEL)))
1966                 free(event_level);
1967
1968         lowmem_deactivate_worker();
1969         lowmem_limit_exit();
1970         lowmem_system_exit();
1971
1972         unregister_notifier(RESOURCED_NOTIFIER_APP_PRELAUNCH, lowmem_prelaunch_handler);
1973         unregister_notifier(RESOURCED_NOTIFIER_MEM_CONTROL, lowmem_control_handler);
1974         unregister_notifier(RESOURCED_NOTIFIER_LCD_OFF, lowmem_bg_reclaim_handler);
1975
1976         return RESOURCED_ERROR_NONE;
1977 }
1978
1979 static int resourced_memory_init(void *data)
1980 {
1981         lowmem_ops = &memory_modules_ops;
1982         return lowmem_init();
1983 }
1984
1985 static int resourced_memory_finalize(void *data)
1986 {
1987         return lowmem_exit();
1988 }
1989
1990 void lowmem_change_memory_state(int state, int force)
1991 {
1992         int mem_state;
1993
1994         if (force) {
1995                 mem_state = state;
1996         } else {
1997                 unsigned int available = proc_get_mem_available();
1998                 mem_state = check_mem_state(available);
1999         }
2000
2001         lowmem_trigger_memory_state_action(mem_state);
2002 }
2003
2004 unsigned long lowmem_get_ktotalram(void)
2005 {
2006         return ktotalram;
2007 }
2008
2009 unsigned long lowmem_get_totalram(void)
2010 {
2011         return totalram;
2012 }
2013
2014 void lowmem_restore_memcg(struct proc_app_info *pai)
2015 {
2016         char *cgpath;
2017         int index, ret;
2018         struct cgroup *cgroup = NULL;
2019         struct memcg_info *mi = NULL;
2020         pid_t pid = pai->main_pid;
2021
2022         ret = cgroup_pid_get_path("memory", pid, &cgpath);
2023         if (ret < 0)
2024                 return;
2025
2026         for (index = CGROUP_END-1; index >= CGROUP_ROOT; index--) {
2027                 cgroup = get_cgroup_tree(index);
2028                 if (!cgroup)
2029                         continue;
2030
2031                 mi = cgroup->memcg_info;
2032                 if (!mi)
2033                         continue;
2034
2035                 if (!strcmp(cgroup->hashname, ""))
2036                         continue;
2037                 if (strstr(cgpath, cgroup->hashname))
2038                         break;
2039         }
2040         pai->memory.memcg_idx = index;
2041         pai->memory.memcg_info = mi;
2042         if(strstr(cgpath, pai->appid))
2043                 pai->memory.use_mem_limit = true;
2044
2045         free(cgpath);
2046 }
2047
2048 static struct module_ops memory_modules_ops = {
2049         .priority       = MODULE_PRIORITY_HIGH,
2050         .name           = "lowmem",
2051         .init           = resourced_memory_init,
2052         .exit           = resourced_memory_finalize,
2053 };
2054
2055 MODULE_REGISTER(&memory_modules_ops)