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