Initialize Tizen 2.3
[kernel/api/system-resource.git] / src / memory / lowmem-process.c
1 /*
2  * resourced
3  *
4  * Copyright (c) 2000 - 2013 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 #include <ctype.h>
21 #include <stdio.h>
22 #include <stdbool.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include <dirent.h>
27 #include <sys/types.h>
28
29 #include "resourced.h"
30 #include "trace.h"
31 #include "proc-main.h"
32 #include "lowmem-process.h"
33 #include "lowmem-handler.h"
34 #include "macro.h"
35 #include "proc-noti.h"
36 #include "proc-winstate.h"
37
38 #define PROC_NAME_MAX 512
39 #define PROC_BUF_MAX  64
40 #define PROC_OOM_SCORE_ADJ_PATH "/proc/%d/oom_score_adj"
41
42 static int lowmem_backgrd_manage(int currentpid)
43 {
44         int pid = -1, pgid, ret;
45         DIR *dp;
46         struct dirent *dentry;
47         FILE *fp;
48         char buf[sizeof(PROC_OOM_SCORE_ADJ_PATH) + MAX_DEC_SIZE(int)] = {0};
49         char appname[PROC_NAME_MAX];
50         int count = 0;
51
52         int cur_oom = -1, prev_oom=OOMADJ_BACKGRD_UNLOCKED, select_pid=0;
53         static int checkprevpid = 0;
54
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;
60                 }
61         }
62
63         dp = opendir("/proc");
64         if (!dp) {
65                 _E("BACKGRD MANAGE : fail to open /proc");
66                 return RESOURCED_ERROR_FAIL;
67         }
68         while ((dentry = readdir(dp)) != NULL) {
69                 if (!isdigit(dentry->d_name[0]))
70                         continue;
71
72                 pid = atoi(dentry->d_name);
73                 pgid = getpgid(pid);
74                 if (!pgid)
75                         continue;
76
77                 if (currentpid != pid && currentpid == pgid) {
78                         _D("found owner pid = %d, pgid = %d", pid, pgid);
79                         lowmem_move_memcgroup(pid, OOMADJ_BACKGRD_UNLOCKED);
80                         continue;
81                 }
82
83                 if (select_pid != pid && select_pid == pgid && count < 16)
84                 {
85                         _D("found candidate child pid = %d, pgid = %d", pid, pgid);
86                 
87                         continue;
88                 }
89                 snprintf(buf, sizeof(buf), PROC_OOM_SCORE_ADJ_PATH, pid);
90                 fp = fopen(buf, "r+");
91                 if (fp == NULL)
92                         continue;
93                 if (fgets(buf, sizeof(buf), fp) == NULL) {
94                         fclose(fp);
95                         continue;
96                 }
97                 cur_oom = atoi(buf);
98                 if (cur_oom > OOMADJ_BACKGRD_UNLOCKED && cur_oom > prev_oom) {
99                         count = 0;
100                         
101                         select_pid = pid;
102                         prev_oom = cur_oom;
103                 }
104
105                 if (cur_oom >= OOMADJ_APP_MAX) {
106                         fclose(fp);
107                         continue;
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);
112                 }
113                 fclose(fp);
114         }
115         checkprevpid = currentpid;
116         closedir(dp);
117         return RESOURCED_ERROR_OK;
118 }
119
120 static void lowmem_foregrd_manage(int pid)
121 {
122         lowmem_cgroup_foregrd_manage(pid);
123 }
124
125 int lowmem_sweep_memory(int callpid)
126 {
127         int pid = -1, count=0, ret;
128         DIR *dp;
129         struct dirent *dentry;
130         FILE *fp;
131         char buf[sizeof(PROC_OOM_SCORE_ADJ_PATH) + MAX_DEC_SIZE(int)] = {0};
132         char appname[PROC_NAME_MAX];
133
134         int cur_oom = -1;
135         dp = opendir("/proc");
136         if (!dp) {
137                 _E("BACKGRD MANAGE : fail to open /proc");
138                 return RESOURCED_ERROR_FAIL;
139         }
140         while ((dentry = readdir(dp)) != NULL) {
141                 if (!isdigit(dentry->d_name[0]))
142                         continue;
143
144                 pid = atoi(dentry->d_name);
145                 if (pid == callpid)
146                         continue;
147
148                 snprintf(buf, sizeof(buf), PROC_OOM_SCORE_ADJ_PATH, pid);
149                 fp = fopen(buf, "r+");
150                 if (fp == NULL)
151                         continue;
152                 if (fgets(buf, sizeof(buf), fp) == NULL) {
153                         fclose(fp);
154                         continue;
155                 }
156                 cur_oom = atoi(buf);
157                 if (cur_oom >= OOMADJ_BACKGRD_UNLOCKED) {
158                         ret = lowmem_get_proc_cmdline(pid, appname);
159                         if (ret != 0) {
160                                 fclose(fp);
161                                 continue;
162                         }
163                         kill(pid, SIGKILL);
164                         _D("sweep memory : background process %d(%s) killed",
165                                         pid, appname);
166                         count++;
167                 }
168                 fclose(fp);
169         }
170         closedir(dp);
171         return count;
172 }
173
174
175 int lowmem_get_proc_cmdline(pid_t pid, char *cmdline)
176 {
177         char buf[PROC_BUF_MAX];
178         char cmdline_buf[PROC_NAME_MAX];
179         char *filename;
180         FILE *fp;
181
182         sprintf(buf, "/proc/%d/cmdline", pid);
183         fp = fopen(buf, "r");
184         if (fp == NULL)
185                 return RESOURCED_ERROR_FAIL;
186
187         if (fgets(cmdline_buf, PROC_NAME_MAX-1, fp) == NULL) {
188                 fclose(fp);
189                 return RESOURCED_ERROR_FAIL;
190         }
191         fclose(fp);
192
193         filename = strrchr(cmdline_buf, '/');
194         if (filename == NULL)
195                 filename = cmdline_buf;
196         else
197                 filename = filename + 1;
198
199         strncpy(cmdline, filename, PROC_NAME_MAX-1);
200
201         return RESOURCED_ERROR_NONE;
202 }
203
204
205 int get_proc_oom_score_adj(int pid, int *oom_score_adj)
206 {
207         char buf[sizeof(PROC_OOM_SCORE_ADJ_PATH) + MAX_DEC_SIZE(int)] = {0};
208         FILE *fp = NULL;
209
210         if (pid < 0)
211                 return RESOURCED_ERROR_FAIL;
212
213         snprintf(buf, sizeof(buf), PROC_OOM_SCORE_ADJ_PATH, pid);
214         fp = fopen(buf, "r");
215         if (fp == NULL)
216                 return RESOURCED_ERROR_FAIL;
217         if (fgets(buf, sizeof(buf), fp) == NULL) {
218                 fclose(fp);
219                 return RESOURCED_ERROR_FAIL;
220         }
221         (*oom_score_adj) = atoi(buf);
222         fclose(fp);
223         return RESOURCED_ERROR_OK;
224 }
225
226 int set_proc_oom_score_adj(int pid, int oom_score_adj)
227 {
228         char buf[sizeof(PROC_OOM_SCORE_ADJ_PATH) + MAX_DEC_SIZE(int)] = {0};
229         FILE *fp;
230
231         snprintf(buf, sizeof(buf), PROC_OOM_SCORE_ADJ_PATH, pid);
232         fp = fopen(buf, "r+");
233         if (fp == NULL)
234                 return RESOURCED_ERROR_FAIL;
235         if (fgets(buf, sizeof(buf), fp) == NULL) {
236                 fclose(fp);
237                 return RESOURCED_ERROR_FAIL;
238         }
239         fprintf(fp, "%d", oom_score_adj);
240         fclose(fp);
241
242         lowmem_move_memcgroup(pid, oom_score_adj);
243         return 0;
244 }
245
246 int lowmem_set_foregrd(int pid, int oom_score_adj)
247 {
248         int ret = 0;
249
250         switch (oom_score_adj) {
251         case OOMADJ_FOREGRD_LOCKED:
252         case OOMADJ_FOREGRD_UNLOCKED:
253         case OOMADJ_SU:
254                 ret = 0;
255                 break;
256         case OOMADJ_BACKGRD_LOCKED:
257                 lowmem_foregrd_manage(pid);
258                 ret = set_proc_oom_score_adj(pid, OOMADJ_FOREGRD_LOCKED);
259                 break;
260         case OOMADJ_BACKGRD_UNLOCKED:
261                 lowmem_foregrd_manage(pid);
262                 ret = set_proc_oom_score_adj(pid, OOMADJ_FOREGRD_UNLOCKED);
263                 break;
264         case OOMADJ_INIT:
265                 ret = set_proc_oom_score_adj(pid, OOMADJ_FOREGRD_UNLOCKED);
266                 break;
267         default:
268                 if (oom_score_adj > OOMADJ_BACKGRD_UNLOCKED) {
269                         ret = set_proc_oom_score_adj(pid, OOMADJ_FOREGRD_UNLOCKED);
270                 } else {
271                         _E("Unknown oom_score_adj value (%d) !", oom_score_adj);
272                         ret = -1;
273                 }
274                 break;
275
276         }
277         return ret;
278 }
279
280 int lowmem_set_backgrd(int pid, int oom_score_adj)
281 {
282         int ret = 0;
283
284         switch (oom_score_adj) {
285         case OOMADJ_BACKGRD_LOCKED:
286         case OOMADJ_BACKGRD_UNLOCKED:
287         case OOMADJ_SU:
288                 _D("don't change oom value pid = (%d) oom_score_adj (%d)!", pid, oom_score_adj);
289                 ret = -1;
290                 break;
291         case OOMADJ_FOREGRD_LOCKED:
292                 ret = set_proc_oom_score_adj(pid, OOMADJ_BACKGRD_LOCKED);
293                 break;
294         case OOMADJ_FOREGRD_UNLOCKED:
295                 lowmem_backgrd_manage(pid);
296                 ret = set_proc_oom_score_adj(pid, OOMADJ_BACKGRD_UNLOCKED);
297                 break;
298         case OOMADJ_INIT:
299                 ret = set_proc_oom_score_adj(pid, OOMADJ_BACKGRD_UNLOCKED);
300                 break;
301         default:
302                 if (oom_score_adj > OOMADJ_BACKGRD_UNLOCKED) {
303                         ret = 0;
304                 } else {
305                         _E("Unknown oom_score_adj value (%d) !", oom_score_adj);
306                         ret = -1;
307                 }
308                 break;
309         }
310         return ret;
311 }
312
313 int lowmem_set_active(int pid, int oom_score_adj)
314 {
315         int ret = 0;
316
317         switch (oom_score_adj) {
318         case OOMADJ_FOREGRD_LOCKED:
319         case OOMADJ_BACKGRD_LOCKED:
320         case OOMADJ_SU:
321                 /* don't change oom value pid */
322                 ret = -1;
323                 break;
324         case OOMADJ_FOREGRD_UNLOCKED:
325                 ret = set_proc_oom_score_adj(pid, OOMADJ_FOREGRD_LOCKED);
326                 break;
327         case OOMADJ_BACKGRD_UNLOCKED:
328                 ret = set_proc_oom_score_adj(pid, OOMADJ_BACKGRD_LOCKED);
329                 break;
330         case OOMADJ_INIT:
331                 ret = set_proc_oom_score_adj(pid, OOMADJ_BACKGRD_LOCKED);
332                 break;
333         default:
334                 if (oom_score_adj > OOMADJ_BACKGRD_UNLOCKED) {
335                         ret = set_proc_oom_score_adj(pid, OOMADJ_BACKGRD_LOCKED);
336                 } else {
337                         _E("Unknown oom_score_adj value (%d) !", oom_score_adj);
338                         ret = -1;
339                 }
340                 break;
341         }
342         return ret;
343 }
344
345 int lowmem_set_inactive(int pid, int oom_score_adj)
346 {
347         int ret = 0;
348
349         switch (oom_score_adj) {
350         case OOMADJ_FOREGRD_UNLOCKED:
351         case OOMADJ_BACKGRD_UNLOCKED:
352         case OOMADJ_SU:
353                 /* don't change oom value pid */
354                 ret = -1;
355                 break;
356         case OOMADJ_FOREGRD_LOCKED:
357                 ret = set_proc_oom_score_adj(pid, OOMADJ_FOREGRD_UNLOCKED);
358                 break;
359         case OOMADJ_BACKGRD_LOCKED:
360                 ret = set_proc_oom_score_adj(pid, OOMADJ_BACKGRD_UNLOCKED);
361                 break;
362         case OOMADJ_INIT:
363                 ret = set_proc_oom_score_adj(pid, OOMADJ_BACKGRD_UNLOCKED);
364                 break;
365         default:
366                 if (oom_score_adj > OOMADJ_BACKGRD_UNLOCKED) {
367                         ret = 0;
368                 } else {
369                         _E("Unknown oom_score_adj value (%d) !", oom_score_adj);
370                         ret = -1;
371                 }
372                 break;
373
374         }
375         return ret;
376 }