tizen_2.0_build
[framework/system/system-server.git] / ss_procmgr.c
1 /*
2  * Copyright 2012  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.tizenopensource.org/license
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15 */
16
17
18 #include <stdio.h>
19 #include <stdbool.h>
20 #include <unistd.h>
21 #include <dirent.h>
22 #include <sys/types.h>
23
24 #include <sysman.h>
25 #include "include/ss_data.h"
26 #include "ss_queue.h"
27 #include "ss_log.h"
28
29 #define LIMITED_PROCESS_OOMADJ 15
30
31 int get_app_oomadj(int pid, int *oomadj)
32 {
33         if (pid < 0)
34                 return -1;
35
36         char buf[PATH_MAX];
37         FILE *fp = NULL;
38
39         snprintf(buf, sizeof(buf), "/proc/%d/oom_adj", pid);
40         fp = fopen(buf, "r");
41         if (fp == NULL)
42                 return -1;
43         if (fgets(buf, PATH_MAX, fp) == NULL) {
44                 fclose(fp);
45                 return -1;
46         }
47         (*oomadj) = atoi(buf);
48         fclose(fp);
49         return 0;
50 }
51
52 int set_app_oomadj(pid_t pid, int new_oomadj)
53 {
54         char buf[PATH_MAX];
55         FILE *fp;
56         int old_oomadj;
57         char exe_name[PATH_MAX];
58
59         if (sysman_get_cmdline_name(pid, exe_name, PATH_MAX) < 0)
60                 snprintf(exe_name, sizeof(exe_name), "Unknown (maybe dead)");
61
62         snprintf(buf, sizeof(buf), "/proc/%d/oom_adj", pid);
63         fp = fopen(buf, "r");
64         if (fp == NULL)
65                 return -1;
66         if (fgets(buf, PATH_MAX, fp) == NULL) {
67                 fclose(fp);
68                 return -1;
69         }
70         old_oomadj = atoi(buf);
71         fclose(fp);
72         PRT_TRACE_EM("Process %s, pid %d, old_oomadj %d", exe_name, pid,
73                      old_oomadj);
74
75         if (old_oomadj < OOMADJ_APP_LIMIT)
76                 return 0;
77
78         PRT_TRACE_EM("Process %s, pid %d, new_oomadj %d", exe_name, pid,
79                      new_oomadj);
80         snprintf(buf, sizeof(buf), "/proc/%d/oom_adj", pid);
81         fp = fopen(buf, "w");
82         if (fp == NULL)
83                 return -1;
84
85         fprintf(fp, "%d", new_oomadj);
86         fclose(fp);
87
88         return 0;
89 }
90
91 int set_oomadj_action(int argc, char **argv)
92 {
93         int pid = -1;
94         int new_oomadj = -20;
95
96         if (argc < 2)
97                 return -1;
98         if ((pid = atoi(argv[0])) < 0 || (new_oomadj = atoi(argv[1])) <= -20)
99                 return -1;
100
101         char buf[255];
102         FILE *fp;
103
104         PRT_TRACE_EM("OOMADJ_SET : pid %d, new_oomadj %d", pid, new_oomadj);
105         snprintf(buf, sizeof(buf), "/proc/%d/oom_adj", pid);
106         fp = fopen(buf, "w");
107         if (fp == NULL)
108                 return -1;
109         fprintf(fp, "%d", new_oomadj);
110         fclose(fp);
111
112         return 0;
113 }
114
115 int check_and_set_old_backgrd()
116 {
117         int pid = -1;
118         DIR *dp;
119         struct dirent *dentry;
120         FILE *fp;
121         char buf[PATH_MAX];
122         int token =0;
123
124         dp = opendir("/proc");
125         if (!dp) {
126                 PRT_TRACE_EM("BACKGRD MANAGE : fail to open /proc : %s", strerror(errno));
127                 return -1;
128         }
129
130         while ((dentry = readdir(dp)) != NULL) {
131                 if (!isdigit(dentry->d_name[0]))
132                         continue;
133
134                 pid = atoi(dentry->d_name);
135
136                 snprintf(buf, sizeof(buf), "/proc/%d/oom_adj", pid);
137                 fp = fopen(buf, "r");
138                 if (fp == NULL)
139                         continue;
140                 if (fgets(buf, sizeof(buf), fp) == NULL) {
141                         fclose(fp);
142                         continue;
143                 }
144                 if(atoi(buf) == OOMADJ_BACKGRD_UNLOCKED) {
145                         fclose(fp);
146                         PRT_TRACE("BACKGRD MANAGE : process wchich has OOMADJ_BACKGRD_UNLOCKED exists");
147                         break;
148                 }
149                 fclose(fp);
150         }
151         closedir(dp);
152
153         if(dentry != NULL ) {
154                 int cur_oom=-1;
155                 dp = opendir("/proc");
156                 if (!dp) {
157                         PRT_TRACE_EM("BACKGRD MANAGE : fail to open /proc : %s", strerror(errno));
158                         return -1;
159                 }
160                 while ((dentry = readdir(dp)) != NULL) {
161
162                         if (!isdigit(dentry->d_name[0]))
163                                 continue;
164
165                         pid = atoi(dentry->d_name);
166
167                         snprintf(buf, sizeof(buf), "/proc/%d/oom_adj", pid);
168                         fp = fopen(buf, "r+");
169                         if (fp == NULL)
170                                 continue;
171                         if (fgets(buf, sizeof(buf), fp) == NULL) {
172                                 fclose(fp); 
173                                 continue;
174                         }                          
175                         cur_oom = atoi(buf);
176                         if(cur_oom >= LIMITED_PROCESS_OOMADJ) {
177                                 PRT_TRACE("BACKGRD MANAGE : kill the process %d (oom_adj %d)", pid, cur_oom);
178                                 kill(pid, SIGTERM);
179                         }
180                         else if(cur_oom >= OOMADJ_BACKGRD_UNLOCKED) {
181                                 PRT_TRACE("BACKGRD MANAGE : process %d set oom_adj %d (before %d)", pid, cur_oom+1, cur_oom);
182                                 fprintf(fp, "%d", ++cur_oom);
183                         }
184                         fclose(fp);
185                 }
186                 closedir(dp);
187         }
188         return 0;
189 }
190
191 int set_active_action(int argc, char **argv)
192 {
193         int pid = -1;
194         int ret = 0;
195         int oomadj = 0;
196
197         if (argc < 1)
198                 return -1;
199         if ((pid = atoi(argv[0])) < 0)
200                 return -1;
201
202         if (get_app_oomadj(pid, &oomadj) < 0)
203                 return -1;
204
205         switch (oomadj) {
206         case OOMADJ_FOREGRD_LOCKED:
207         case OOMADJ_BACKGRD_LOCKED:
208         case OOMADJ_SU:
209                 ret = 0;
210                 break;
211         case OOMADJ_FOREGRD_UNLOCKED:
212                 ret = set_app_oomadj((pid_t) pid, OOMADJ_FOREGRD_LOCKED);
213                 break;
214         case OOMADJ_BACKGRD_UNLOCKED:
215                 ret = set_app_oomadj((pid_t) pid, OOMADJ_BACKGRD_LOCKED);
216                 break;
217         case OOMADJ_INIT:
218                 ret = set_app_oomadj((pid_t) pid, OOMADJ_BACKGRD_LOCKED);
219                 break;
220         default:
221                 if(oomadj > OOMADJ_BACKGRD_UNLOCKED) {
222                         ret = set_app_oomadj((pid_t) pid, OOMADJ_BACKGRD_LOCKED);
223                 } else {
224                         PRT_TRACE_EM("Unknown oomadj value (%d) !", oomadj);
225                         ret = -1;
226                 }
227                 break;
228         }
229         return ret;
230 }
231
232 int set_inactive_action(int argc, char **argv)
233 {
234         int pid = -1;
235         int ret = 0;
236         int oomadj = 0;
237
238         if (argc < 1)
239                 return -1;
240         if ((pid = atoi(argv[0])) < 0)
241                 return -1;
242
243         if (get_app_oomadj(pid, &oomadj) < 0)
244                 return -1;
245
246         switch (oomadj) {
247         case OOMADJ_FOREGRD_UNLOCKED:
248         case OOMADJ_BACKGRD_UNLOCKED:
249         case OOMADJ_SU:
250                 ret = 0;
251                 break;
252         case OOMADJ_FOREGRD_LOCKED:
253                 ret = set_app_oomadj((pid_t) pid, OOMADJ_FOREGRD_UNLOCKED);
254                 break;
255         case OOMADJ_BACKGRD_LOCKED:
256                 check_and_set_old_backgrd();
257                 ret = set_app_oomadj((pid_t) pid, OOMADJ_BACKGRD_UNLOCKED);
258                 break;
259         case OOMADJ_INIT:
260                 check_and_set_old_backgrd();
261                 ret = set_app_oomadj((pid_t) pid, OOMADJ_BACKGRD_UNLOCKED);
262                 break;
263         default:
264                 if(oomadj > OOMADJ_BACKGRD_UNLOCKED) {
265                         ret = 0;
266                 } else {
267                         PRT_TRACE_EM("Unknown oomadj value (%d) !", oomadj);
268                         ret = -1;
269                 }
270                 break;
271
272         }
273         return ret;
274 }
275
276 int set_foregrd_action(int argc, char **argv)
277 {
278         int pid = -1;
279         int ret = 0;
280         int oomadj = 0;
281
282         if (argc < 1)
283                 return -1;
284         if ((pid = atoi(argv[0])) < 0)
285                 return -1;
286
287         if (get_app_oomadj(pid, &oomadj) < 0)
288                 return -1;
289
290         switch (oomadj) {
291         case OOMADJ_FOREGRD_LOCKED:
292         case OOMADJ_FOREGRD_UNLOCKED:
293         case OOMADJ_SU:
294                 ret = 0;
295                 break;
296         case OOMADJ_BACKGRD_LOCKED:
297                 ret = set_app_oomadj((pid_t) pid, OOMADJ_FOREGRD_LOCKED);
298                 break;
299         case OOMADJ_BACKGRD_UNLOCKED:
300                 ret = set_app_oomadj((pid_t) pid, OOMADJ_FOREGRD_UNLOCKED);
301                 break;
302         case OOMADJ_INIT:
303                 ret = set_app_oomadj((pid_t) pid, OOMADJ_FOREGRD_UNLOCKED);
304                 break;
305         default:
306                 if(oomadj > OOMADJ_BACKGRD_UNLOCKED) {
307                         ret = set_app_oomadj((pid_t) pid, OOMADJ_FOREGRD_UNLOCKED);
308                 } else {                
309                         PRT_TRACE_EM("Unknown oomadj value (%d) !", oomadj);
310                         ret = -1;                                       
311                 }
312                 break;
313
314         }
315         return ret;
316 }
317
318 int set_backgrd_action(int argc, char **argv)
319 {
320         int pid = -1;
321         int ret = 0;
322         int oomadj = 0;
323
324         if (argc < 1)
325                 return -1;
326         if ((pid = atoi(argv[0])) < 0)
327                 return -1;
328
329         if (get_app_oomadj(pid, &oomadj) < 0)
330                 return -1;
331
332         switch (oomadj) {
333         case OOMADJ_BACKGRD_LOCKED:
334         case OOMADJ_BACKGRD_UNLOCKED:
335         case OOMADJ_SU:
336                 ret = 0;
337                 break;
338         case OOMADJ_FOREGRD_LOCKED:
339                 ret = set_app_oomadj((pid_t) pid, OOMADJ_BACKGRD_LOCKED);
340                 break;
341         case OOMADJ_FOREGRD_UNLOCKED:
342                 check_and_set_old_backgrd();
343                 ret = set_app_oomadj((pid_t) pid, OOMADJ_BACKGRD_UNLOCKED);
344                 break;
345         case OOMADJ_INIT:
346                 check_and_set_old_backgrd();
347                 ret = set_app_oomadj((pid_t) pid, OOMADJ_BACKGRD_UNLOCKED);
348                 break;
349         default:
350                 if(oomadj > OOMADJ_BACKGRD_UNLOCKED) {
351                         ret = 0;
352                 } else {                
353                         PRT_TRACE_EM("Unknown oomadj value (%d) !", oomadj);
354                         ret = -1;                                       
355                 }
356                 break;
357         }
358         return ret;
359 }
360
361 int ss_process_manager_init(void)
362 {
363         ss_action_entry_add_internal(PREDEF_FOREGRD, set_foregrd_action, NULL,
364                                      NULL);
365         ss_action_entry_add_internal(PREDEF_BACKGRD, set_backgrd_action, NULL,
366                                      NULL);
367         ss_action_entry_add_internal(PREDEF_ACTIVE, set_active_action, NULL,
368                                      NULL);
369         ss_action_entry_add_internal(PREDEF_INACTIVE, set_inactive_action, NULL,
370                                      NULL);
371         ss_action_entry_add_internal(OOMADJ_SET, set_oomadj_action, NULL, NULL);
372         return 0;
373 }