4 * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
27 #include <sys/types.h>
29 #include "resourced.h"
31 #include "proc-main.h"
32 #include "lowmem-process.h"
33 #include "lowmem-handler.h"
35 #include "proc-noti.h"
36 #include "proc-winstate.h"
38 #define PROC_NAME_MAX 512
39 #define PROC_BUF_MAX 64
40 #define PROC_OOM_SCORE_ADJ_PATH "/proc/%d/oom_score_adj"
42 static int lowmem_backgrd_manage(int currentpid)
44 int pid = -1, pgid, ret;
46 struct dirent *dentry;
48 char buf[sizeof(PROC_OOM_SCORE_ADJ_PATH) + MAX_DEC_SIZE(int)] = {0};
49 char appname[PROC_NAME_MAX];
52 int cur_oom = -1, prev_oom=OOMADJ_BACKGRD_UNLOCKED, select_pid=0;
53 static int checkprevpid = 0;
55 ret = lowmem_get_proc_cmdline(currentpid, appname);
56 if (ret == RESOURCED_ERROR_NONE) {
57 if (checkprevpid == currentpid) {
58 _D("BACKGRD MANAGE : don't manage background application by %d", currentpid);
59 return RESOURCED_ERROR_NONE;
63 dp = opendir("/proc");
65 _E("BACKGRD MANAGE : fail to open /proc");
66 return RESOURCED_ERROR_FAIL;
68 while ((dentry = readdir(dp)) != NULL) {
69 if (!isdigit(dentry->d_name[0]))
72 pid = atoi(dentry->d_name);
77 if (currentpid != pid && currentpid == pgid) {
78 _D("found owner pid = %d, pgid = %d", pid, pgid);
79 lowmem_move_memcgroup(pid, OOMADJ_BACKGRD_UNLOCKED);
83 if (select_pid != pid && select_pid == pgid && count < 16)
85 _D("found candidate child pid = %d, pgid = %d", pid, pgid);
89 snprintf(buf, sizeof(buf), PROC_OOM_SCORE_ADJ_PATH, pid);
90 fp = fopen(buf, "r+");
93 if (fgets(buf, sizeof(buf), fp) == NULL) {
98 if (cur_oom > OOMADJ_BACKGRD_UNLOCKED && cur_oom > prev_oom) {
105 if (cur_oom >= OOMADJ_APP_MAX) {
108 } else if (cur_oom >= OOMADJ_BACKGRD_UNLOCKED) {
109 _D("BACKGRD : process %d set oom_score_adj %d (before %d)",
110 pid, cur_oom+OOMADJ_APP_INCREASE, cur_oom);
111 fprintf(fp, "%d", cur_oom+OOMADJ_APP_INCREASE);
115 checkprevpid = currentpid;
117 return RESOURCED_ERROR_OK;
120 static void lowmem_foregrd_manage(int pid)
122 lowmem_cgroup_foregrd_manage(pid);
125 int lowmem_sweep_memory(int callpid)
127 int pid = -1, count=0, ret;
129 struct dirent *dentry;
131 char buf[sizeof(PROC_OOM_SCORE_ADJ_PATH) + MAX_DEC_SIZE(int)] = {0};
132 char appname[PROC_NAME_MAX];
135 dp = opendir("/proc");
137 _E("BACKGRD MANAGE : fail to open /proc");
138 return RESOURCED_ERROR_FAIL;
140 while ((dentry = readdir(dp)) != NULL) {
141 if (!isdigit(dentry->d_name[0]))
144 pid = atoi(dentry->d_name);
148 snprintf(buf, sizeof(buf), PROC_OOM_SCORE_ADJ_PATH, pid);
149 fp = fopen(buf, "r+");
152 if (fgets(buf, sizeof(buf), fp) == NULL) {
157 if (cur_oom >= OOMADJ_BACKGRD_UNLOCKED) {
158 ret = lowmem_get_proc_cmdline(pid, appname);
164 _D("sweep memory : background process %d(%s) killed",
175 int lowmem_get_proc_cmdline(pid_t pid, char *cmdline)
177 char buf[PROC_BUF_MAX];
178 char cmdline_buf[PROC_NAME_MAX];
182 sprintf(buf, "/proc/%d/cmdline", pid);
183 fp = fopen(buf, "r");
185 return RESOURCED_ERROR_FAIL;
187 if (fgets(cmdline_buf, PROC_NAME_MAX-1, fp) == NULL) {
189 return RESOURCED_ERROR_FAIL;
193 filename = strrchr(cmdline_buf, '/');
194 if (filename == NULL)
195 filename = cmdline_buf;
197 filename = filename + 1;
199 strncpy(cmdline, filename, PROC_NAME_MAX-1);
201 return RESOURCED_ERROR_NONE;
205 int get_proc_oom_score_adj(int pid, int *oom_score_adj)
207 char buf[sizeof(PROC_OOM_SCORE_ADJ_PATH) + MAX_DEC_SIZE(int)] = {0};
211 return RESOURCED_ERROR_FAIL;
213 snprintf(buf, sizeof(buf), PROC_OOM_SCORE_ADJ_PATH, pid);
214 fp = fopen(buf, "r");
216 return RESOURCED_ERROR_FAIL;
217 if (fgets(buf, sizeof(buf), fp) == NULL) {
219 return RESOURCED_ERROR_FAIL;
221 (*oom_score_adj) = atoi(buf);
223 return RESOURCED_ERROR_OK;
226 int set_proc_oom_score_adj(int pid, int oom_score_adj)
228 char buf[sizeof(PROC_OOM_SCORE_ADJ_PATH) + MAX_DEC_SIZE(int)] = {0};
231 snprintf(buf, sizeof(buf), PROC_OOM_SCORE_ADJ_PATH, pid);
232 fp = fopen(buf, "r+");
234 return RESOURCED_ERROR_FAIL;
235 if (fgets(buf, sizeof(buf), fp) == NULL) {
237 return RESOURCED_ERROR_FAIL;
239 fprintf(fp, "%d", oom_score_adj);
242 lowmem_move_memcgroup(pid, oom_score_adj);
246 int lowmem_set_foregrd(int pid, int oom_score_adj)
250 switch (oom_score_adj) {
251 case OOMADJ_FOREGRD_LOCKED:
252 case OOMADJ_FOREGRD_UNLOCKED:
256 case OOMADJ_BACKGRD_LOCKED:
257 lowmem_foregrd_manage(pid);
258 ret = set_proc_oom_score_adj(pid, OOMADJ_FOREGRD_LOCKED);
260 case OOMADJ_BACKGRD_UNLOCKED:
261 lowmem_foregrd_manage(pid);
262 ret = set_proc_oom_score_adj(pid, OOMADJ_FOREGRD_UNLOCKED);
265 ret = set_proc_oom_score_adj(pid, OOMADJ_FOREGRD_UNLOCKED);
268 if (oom_score_adj > OOMADJ_BACKGRD_UNLOCKED) {
269 ret = set_proc_oom_score_adj(pid, OOMADJ_FOREGRD_UNLOCKED);
271 _E("Unknown oom_score_adj value (%d) !", oom_score_adj);
280 int lowmem_set_backgrd(int pid, int oom_score_adj)
284 switch (oom_score_adj) {
285 case OOMADJ_BACKGRD_LOCKED:
286 case OOMADJ_BACKGRD_UNLOCKED:
288 _D("don't change oom value pid = (%d) oom_score_adj (%d)!", pid, oom_score_adj);
291 case OOMADJ_FOREGRD_LOCKED:
292 ret = set_proc_oom_score_adj(pid, OOMADJ_BACKGRD_LOCKED);
294 case OOMADJ_FOREGRD_UNLOCKED:
295 lowmem_backgrd_manage(pid);
296 ret = set_proc_oom_score_adj(pid, OOMADJ_BACKGRD_UNLOCKED);
299 ret = set_proc_oom_score_adj(pid, OOMADJ_BACKGRD_UNLOCKED);
302 if (oom_score_adj > OOMADJ_BACKGRD_UNLOCKED) {
305 _E("Unknown oom_score_adj value (%d) !", oom_score_adj);
313 int lowmem_set_active(int pid, int oom_score_adj)
317 switch (oom_score_adj) {
318 case OOMADJ_FOREGRD_LOCKED:
319 case OOMADJ_BACKGRD_LOCKED:
321 /* don't change oom value pid */
324 case OOMADJ_FOREGRD_UNLOCKED:
325 ret = set_proc_oom_score_adj(pid, OOMADJ_FOREGRD_LOCKED);
327 case OOMADJ_BACKGRD_UNLOCKED:
328 ret = set_proc_oom_score_adj(pid, OOMADJ_BACKGRD_LOCKED);
331 ret = set_proc_oom_score_adj(pid, OOMADJ_BACKGRD_LOCKED);
334 if (oom_score_adj > OOMADJ_BACKGRD_UNLOCKED) {
335 ret = set_proc_oom_score_adj(pid, OOMADJ_BACKGRD_LOCKED);
337 _E("Unknown oom_score_adj value (%d) !", oom_score_adj);
345 int lowmem_set_inactive(int pid, int oom_score_adj)
349 switch (oom_score_adj) {
350 case OOMADJ_FOREGRD_UNLOCKED:
351 case OOMADJ_BACKGRD_UNLOCKED:
353 /* don't change oom value pid */
356 case OOMADJ_FOREGRD_LOCKED:
357 ret = set_proc_oom_score_adj(pid, OOMADJ_FOREGRD_UNLOCKED);
359 case OOMADJ_BACKGRD_LOCKED:
360 ret = set_proc_oom_score_adj(pid, OOMADJ_BACKGRD_UNLOCKED);
363 ret = set_proc_oom_score_adj(pid, OOMADJ_BACKGRD_UNLOCKED);
366 if (oom_score_adj > OOMADJ_BACKGRD_UNLOCKED) {
369 _E("Unknown oom_score_adj value (%d) !", oom_score_adj);