change device node control api from plugin to device-node
[framework/system/system-server.git] / ss_procmgr.c
1 /*
2  * Copyright (c) 2012 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
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 #include <device-node.h>
24
25 #include <sysman.h>
26 #include "include/ss_data.h"
27 #include "ss_queue.h"
28 #include "ss_log.h"
29
30 #define LIMITED_BACKGRD_NUM 15
31 #define MAX_BACKGRD_OOMADJ (OOMADJ_BACKGRD_UNLOCKED + LIMITED_BACKGRD_NUM)
32 #define PROCESS_VIP             "process_vip"
33 #define PROCESS_PERMANENT       "process_permanent"
34
35 int get_app_oomadj(int pid, int *oomadj)
36 {
37         if (pid < 0)
38                 return -1;
39
40         char buf[PATH_MAX];
41         FILE *fp = NULL;
42
43         snprintf(buf, sizeof(buf), "/proc/%d/oom_adj", pid);
44         fp = fopen(buf, "r");
45         if (fp == NULL)
46                 return -1;
47         if (fgets(buf, PATH_MAX, fp) == NULL) {
48                 fclose(fp);
49                 return -1;
50         }
51         (*oomadj) = atoi(buf);
52         fclose(fp);
53         return 0;
54 }
55
56 int set_app_oomadj(pid_t pid, int new_oomadj)
57 {
58         char buf[PATH_MAX];
59         FILE *fp;
60         int old_oomadj;
61         char exe_name[PATH_MAX];
62
63         if (sysman_get_cmdline_name(pid, exe_name, PATH_MAX) < 0)
64                 snprintf(exe_name, sizeof(exe_name), "Unknown (maybe dead)");
65
66         snprintf(buf, sizeof(buf), "/proc/%d/oom_adj", pid);
67         fp = fopen(buf, "r");
68         if (fp == NULL)
69                 return -1;
70         if (fgets(buf, PATH_MAX, fp) == NULL) {
71                 fclose(fp);
72                 return -1;
73         }
74         old_oomadj = atoi(buf);
75         fclose(fp);
76         PRT_TRACE_EM("Process %s, pid %d, old_oomadj %d", exe_name, pid,
77                      old_oomadj);
78
79         if (old_oomadj < OOMADJ_APP_LIMIT)
80                 return 0;
81
82         PRT_TRACE_EM("Process %s, pid %d, new_oomadj %d", exe_name, pid,
83                      new_oomadj);
84         snprintf(buf, sizeof(buf), "/proc/%d/oom_adj", pid);
85         fp = fopen(buf, "w");
86         if (fp == NULL)
87                 return -1;
88
89         fprintf(fp, "%d", new_oomadj);
90         fclose(fp);
91
92         return 0;
93 }
94
95 int set_oomadj_action(int argc, char **argv)
96 {
97         int pid = -1;
98         int new_oomadj = -20;
99
100         if (argc < 2)
101                 return -1;
102         if ((pid = atoi(argv[0])) < 0 || (new_oomadj = atoi(argv[1])) <= -20)
103                 return -1;
104
105         char buf[255];
106         FILE *fp;
107
108         PRT_TRACE_EM("OOMADJ_SET : pid %d, new_oomadj %d", pid, new_oomadj);
109         snprintf(buf, sizeof(buf), "/proc/%d/oom_adj", pid);
110         fp = fopen(buf, "w");
111         if (fp == NULL)
112                 return -1;
113         fprintf(fp, "%d", new_oomadj);
114         fclose(fp);
115
116         return 0;
117 }
118
119 static int update_backgrd_app_oomadj(pid_t pid, int new_oomadj)
120 {
121         char buf[PATH_MAX];
122         FILE* fp;
123
124         snprintf(buf, sizeof(buf), "/proc/%d/oom_adj", pid);
125         fp = fopen(buf, "w");
126         if (fp == NULL)
127                 return -1;
128
129         fprintf(fp, "%d", new_oomadj);
130         fclose(fp);
131
132         return 0;
133 }
134
135 int check_and_set_old_backgrd()
136 {
137         int pid = -1;
138         DIR *dp;
139         struct dirent *dentry;
140         FILE *fp;
141         char buf[PATH_MAX];
142         int token =0;
143         int oom_adj, new_oomadj, i;
144         pid_t buckets[MAX_BACKGRD_OOMADJ][LIMITED_BACKGRD_NUM];
145
146         dp = opendir("/proc");
147         if (!dp) {
148                 PRT_TRACE_EM("BACKGRD MANAGE : fail to open /proc : %s", strerror(errno));
149                 return -1;
150         }
151
152         memset(buckets, 0, sizeof(buckets));
153         while ((dentry = readdir(dp)) != NULL) {
154                 if (!isdigit(dentry->d_name[0]))
155                         continue;
156
157                 pid = atoi(dentry->d_name);
158
159                 snprintf(buf, sizeof(buf), "/proc/%d/oom_adj", pid);
160                 fp = fopen(buf, "r");
161                 if (fp == NULL)
162                         continue;
163                 if (fgets(buf, sizeof(buf), fp) == NULL) {
164                         fclose(fp);
165                         continue;
166                 }
167                 oom_adj = atoi(buf);
168                 if (oom_adj < MAX_BACKGRD_OOMADJ && oom_adj >= OOMADJ_BACKGRD_UNLOCKED) {
169                         pid_t *bucket = buckets[oom_adj];
170                         for (i = 0; i < LIMITED_BACKGRD_NUM; i++) {
171                                 if (!bucket[i])
172                                         break;
173                         }
174                         if (i >= LIMITED_BACKGRD_NUM)
175                                 PRT_TRACE_EM("BACKGRB MANAGE : background applications(oom_adj %d) exceeds limitation", i);
176                         else
177                                 bucket[i] = pid;
178                 }
179                 fclose(fp);
180         }
181         closedir(dp);
182
183         new_oomadj = OOMADJ_BACKGRD_UNLOCKED + 1;
184         for (oom_adj = OOMADJ_BACKGRD_UNLOCKED; oom_adj < MAX_BACKGRD_OOMADJ; oom_adj++) {
185                 for (i = 0; i < LIMITED_BACKGRD_NUM; i++) {
186                         pid = buckets[oom_adj][i];
187                         if (!pid)
188                                 break;
189                         if (new_oomadj >= MAX_BACKGRD_OOMADJ) {
190                                 PRT_TRACE("BACKGRD MANAGE : kill the process %d (oom_adj %d)", pid, MAX_BACKGRD_OOMADJ);
191                                 kill(pid, SIGTERM);
192                         }
193                         else {
194                                 if (new_oomadj != oom_adj)
195                                         update_backgrd_app_oomadj(pid, new_oomadj);
196                                 new_oomadj++;
197                         }
198                 }
199         }
200
201         return 0;
202 }
203
204 int set_active_action(int argc, char **argv)
205 {
206         int pid = -1;
207         int ret = 0;
208         int oomadj = 0;
209
210         if (argc < 1)
211                 return -1;
212         if ((pid = atoi(argv[0])) < 0)
213                 return -1;
214
215         if (get_app_oomadj(pid, &oomadj) < 0)
216                 return -1;
217
218         switch (oomadj) {
219         case OOMADJ_FOREGRD_LOCKED:
220         case OOMADJ_BACKGRD_LOCKED:
221         case OOMADJ_SU:
222                 ret = 0;
223                 break;
224         case OOMADJ_FOREGRD_UNLOCKED:
225                 ret = set_app_oomadj((pid_t) pid, OOMADJ_FOREGRD_LOCKED);
226                 break;
227         case OOMADJ_BACKGRD_UNLOCKED:
228                 ret = set_app_oomadj((pid_t) pid, OOMADJ_BACKGRD_LOCKED);
229                 break;
230         case OOMADJ_INIT:
231                 ret = set_app_oomadj((pid_t) pid, OOMADJ_BACKGRD_LOCKED);
232                 break;
233         default:
234                 if(oomadj > OOMADJ_BACKGRD_UNLOCKED) {
235                         ret = set_app_oomadj((pid_t) pid, OOMADJ_BACKGRD_LOCKED);
236                 } else {
237                         PRT_TRACE_EM("Unknown oomadj value (%d) !", oomadj);
238                         ret = -1;
239                 }
240                 break;
241         }
242         return ret;
243 }
244
245 int set_inactive_action(int argc, char **argv)
246 {
247         int pid = -1;
248         int ret = 0;
249         int oomadj = 0;
250
251         if (argc < 1)
252                 return -1;
253         if ((pid = atoi(argv[0])) < 0)
254                 return -1;
255
256         if (get_app_oomadj(pid, &oomadj) < 0)
257                 return -1;
258
259         switch (oomadj) {
260         case OOMADJ_FOREGRD_UNLOCKED:
261         case OOMADJ_BACKGRD_UNLOCKED:
262         case OOMADJ_SU:
263                 ret = 0;
264                 break;
265         case OOMADJ_FOREGRD_LOCKED:
266                 ret = set_app_oomadj((pid_t) pid, OOMADJ_FOREGRD_UNLOCKED);
267                 break;
268         case OOMADJ_BACKGRD_LOCKED:
269                 check_and_set_old_backgrd();
270                 ret = set_app_oomadj((pid_t) pid, OOMADJ_BACKGRD_UNLOCKED);
271                 break;
272         case OOMADJ_INIT:
273                 check_and_set_old_backgrd();
274                 ret = set_app_oomadj((pid_t) pid, OOMADJ_BACKGRD_UNLOCKED);
275                 break;
276         default:
277                 if(oomadj > OOMADJ_BACKGRD_UNLOCKED) {
278                         ret = 0;
279                 } else {
280                         PRT_TRACE_EM("Unknown oomadj value (%d) !", oomadj);
281                         ret = -1;
282                 }
283                 break;
284
285         }
286         return ret;
287 }
288
289 int set_foregrd_action(int argc, char **argv)
290 {
291         int pid = -1;
292         int ret = 0;
293         int oomadj = 0;
294
295         if (argc < 1)
296                 return -1;
297         if ((pid = atoi(argv[0])) < 0)
298                 return -1;
299
300         if (get_app_oomadj(pid, &oomadj) < 0)
301                 return -1;
302
303         switch (oomadj) {
304         case OOMADJ_FOREGRD_LOCKED:
305         case OOMADJ_FOREGRD_UNLOCKED:
306         case OOMADJ_SU:
307                 ret = 0;
308                 break;
309         case OOMADJ_BACKGRD_LOCKED:
310                 ret = set_app_oomadj((pid_t) pid, OOMADJ_FOREGRD_LOCKED);
311                 break;
312         case OOMADJ_BACKGRD_UNLOCKED:
313                 ret = set_app_oomadj((pid_t) pid, OOMADJ_FOREGRD_UNLOCKED);
314                 break;
315         case OOMADJ_INIT:
316                 ret = set_app_oomadj((pid_t) pid, OOMADJ_FOREGRD_UNLOCKED);
317                 break;
318         default:
319                 if(oomadj > OOMADJ_BACKGRD_UNLOCKED) {
320                         ret = set_app_oomadj((pid_t) pid, OOMADJ_FOREGRD_UNLOCKED);
321                 } else {                
322                         PRT_TRACE_EM("Unknown oomadj value (%d) !", oomadj);
323                         ret = -1;                                       
324                 }
325                 break;
326
327         }
328         return ret;
329 }
330
331 int set_backgrd_action(int argc, char **argv)
332 {
333         int pid = -1;
334         int ret = 0;
335         int oomadj = 0;
336
337         if (argc < 1)
338                 return -1;
339         if ((pid = atoi(argv[0])) < 0)
340                 return -1;
341
342         if (get_app_oomadj(pid, &oomadj) < 0)
343                 return -1;
344
345         switch (oomadj) {
346         case OOMADJ_BACKGRD_LOCKED:
347         case OOMADJ_BACKGRD_UNLOCKED:
348         case OOMADJ_SU:
349                 ret = 0;
350                 break;
351         case OOMADJ_FOREGRD_LOCKED:
352                 ret = set_app_oomadj((pid_t) pid, OOMADJ_BACKGRD_LOCKED);
353                 break;
354         case OOMADJ_FOREGRD_UNLOCKED:
355                 check_and_set_old_backgrd();
356                 ret = set_app_oomadj((pid_t) pid, OOMADJ_BACKGRD_UNLOCKED);
357                 break;
358         case OOMADJ_INIT:
359                 check_and_set_old_backgrd();
360                 ret = set_app_oomadj((pid_t) pid, OOMADJ_BACKGRD_UNLOCKED);
361                 break;
362         default:
363                 if(oomadj > OOMADJ_BACKGRD_UNLOCKED) {
364                         ret = 0;
365                 } else {                
366                         PRT_TRACE_EM("Unknown oomadj value (%d) !", oomadj);
367                         ret = -1;                                       
368                 }
369                 break;
370         }
371         return ret;
372 }
373
374 int set_process_group_action(int argc, char **argv)
375 {
376         int pid = -1;
377         int ret = -1;
378
379         if (argc != 2)
380                 return -1;
381         if ((pid = atoi(argv[0])) < 0)
382                 return -1;
383
384         if (strncmp(argv[1], PROCESS_VIP, strlen(PROCESS_VIP)) == 0)
385                 ret = device_set_property(DEVICE_TYPE_PROCESS, PROP_PROCESS_MP_VIP, pid);
386         else if (strncmp(argv[1], PROCESS_PERMANENT, strlen(PROCESS_PERMANENT)) == 0)
387                 ret = device_set_property(DEVICE_TYPE_PROCESS, PROP_PROCESS_MP_PNP, pid);
388
389         if (ret == 0)
390                 PRT_TRACE_ERR("%s : pid %d", argv[1], pid);
391         else
392                 PRT_TRACE_ERR("fail to set %s : pid %d",argv[1], pid);
393         return 0;
394 }
395
396 int ss_process_manager_init(void)
397 {
398         ss_action_entry_add_internal(PREDEF_FOREGRD, set_foregrd_action, NULL,
399                                      NULL);
400         ss_action_entry_add_internal(PREDEF_BACKGRD, set_backgrd_action, NULL,
401                                      NULL);
402         ss_action_entry_add_internal(PREDEF_ACTIVE, set_active_action, NULL,
403                                      NULL);
404         ss_action_entry_add_internal(PREDEF_INACTIVE, set_inactive_action, NULL,
405                                      NULL);
406         ss_action_entry_add_internal(OOMADJ_SET, set_oomadj_action, NULL, NULL);
407         ss_action_entry_add_internal(PROCESS_GROUP_SET, set_process_group_action, NULL, NULL);
408         return 0;
409 }