tizen 2.3.1 release
[kernel/api/system-resource.git] / src / cpu / cpu.c
1 /*
2  * resourced
3  *
4  * Copyright (c) 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  * @file cpu.c
21  *
22  * @desc cpu module
23  *
24  * Copyright (c) 2013 Samsung Electronics Co., Ltd. All rights reserved.
25  *
26  */
27 #include <dirent.h>
28 #include <errno.h>
29 #include <ctype.h>
30 #include <sys/types.h>
31 #include "notifier.h"
32 #include "proc-main.h"
33 #include "proc-process.h"
34 #include "macro.h"
35 #include "module.h"
36 #include "module-data.h"
37 #include "resourced.h"
38 #include "trace.h"
39 #include "vconf.h"
40 #include "cgroup.h"
41 #include "config-parser.h"
42 #include "const.h"
43
44 #define CPU_DEFAULT_CGROUP "/sys/fs/cgroup/cpu"
45 #define CPU_CONTROL_GROUP "/sys/fs/cgroup/cpu/background"
46 #define CPU_CONTROL_SERVICE_GROUP "/sys/fs/cgroup/cpu/service"
47 #define CPU_CONF_FILE                  "/etc/resourced/cpu.conf"
48 #define CPU_CONF_SECTION        "CONTROL"
49 #define CPU_CONF_PREDEFINE      "PREDEFINE"
50 #define CPU_SHARE       "/cpu.shares"
51
52 static int cpu_move_cgroup(pid_t pid, char *path)
53 {
54         return cgroup_write_node(path, CGROUP_FILE_NAME, pid);
55 }
56
57 static int load_cpu_config(struct parse_result *result, void *user_data)
58 {
59         pid_t pid = 0, value;
60         if (!result)
61                 return -EINVAL;
62
63         if (strcmp(result->section, CPU_CONF_SECTION))
64                 return RESOURCED_ERROR_NO_DATA;
65         if (!strcmp(result->name, CPU_CONF_PREDEFINE)) {
66                 pid = find_pid_from_cmdline(result->value);
67                 if (pid > 0)
68                         cpu_move_cgroup(pid, CPU_CONTROL_GROUP);
69         } else if (!strcmp(result->name, "BACKGROUND_CPU_SHARE")) {
70                 value = atoi(result->value);
71                 if (value)
72                         cgroup_write_node(CPU_CONTROL_GROUP, CPU_SHARE, value);
73        } else if (!strcmp(result->name, "SERVICE_CPU_SHARE")) {
74                 value = atoi(result->value);
75                 if (value)
76                         cgroup_write_node(CPU_CONTROL_SERVICE_GROUP, CPU_SHARE, value);
77        }
78        return RESOURCED_ERROR_NONE;
79 }
80
81 static int cpu_service_launch(void *data)
82 {
83         struct proc_status *p_data = (struct proc_status*)data;
84         _D("cpu_service_launch : pid = %d, appname = %s", p_data->pid, p_data->appid);
85         cpu_move_cgroup(p_data->pid, CPU_CONTROL_SERVICE_GROUP);
86         return RESOURCED_ERROR_NONE;
87 }
88
89 static int cpu_foreground_state(void *data)
90 {
91         struct proc_status *p_data = (struct proc_status*)data;
92         _D("cpu_foreground_state : pid = %d, appname = %s", p_data->pid, p_data->appid);
93         cpu_move_cgroup(p_data->pid, CPU_DEFAULT_CGROUP);
94         return RESOURCED_ERROR_NONE;
95 }
96
97 static int cpu_background_state(void *data)
98 {
99         struct proc_status *p_data = (struct proc_status*)data;
100         _D("cpu_background_state : pid = %d, appname = %s", p_data->pid, p_data->appid);
101         cpu_move_cgroup(p_data->pid, CPU_CONTROL_SERVICE_GROUP);
102         return RESOURCED_ERROR_NONE;
103 }
104
105 static int resourced_cpu_init(void *data)
106 {
107         int ret_code;
108
109         _D("resourced_cpu_init");
110         ret_code = make_cgroup_subdir(CPU_DEFAULT_CGROUP, "background", NULL);
111         ret_value_msg_if(ret_code < 0, ret_code, "cpu init failed\n");
112         ret_code = make_cgroup_subdir(CPU_DEFAULT_CGROUP, "service", NULL);
113         ret_value_msg_if(ret_code < 0, ret_code, "create service cgroup failed\n");
114         config_parse(CPU_CONF_FILE, load_cpu_config, NULL);
115
116         register_notifier(RESOURCED_NOTIFIER_SERVICE_LAUNCH, cpu_service_launch);
117         register_notifier(RESOURCED_NOTIFIER_APP_RESUME, cpu_foreground_state);
118         register_notifier(RESOURCED_NOTIFIER_APP_FOREGRD, cpu_foreground_state);
119         register_notifier(RESOURCED_NOTIFIER_APP_BACKGRD, cpu_background_state);
120         return RESOURCED_ERROR_NONE;
121 }
122
123 static int resourced_cpu_finalize(void *data)
124 {
125         unregister_notifier(RESOURCED_NOTIFIER_SERVICE_LAUNCH, cpu_service_launch);
126         unregister_notifier(RESOURCED_NOTIFIER_APP_RESUME, cpu_foreground_state);
127         unregister_notifier(RESOURCED_NOTIFIER_APP_FOREGRD, cpu_foreground_state);
128         unregister_notifier(RESOURCED_NOTIFIER_APP_BACKGRD, cpu_background_state);
129         return RESOURCED_ERROR_NONE;
130 }
131
132 static struct module_ops cpu_modules_ops = {
133         .priority = MODULE_PRIORITY_NORMAL,
134         .name = "cpu",
135         .init = resourced_cpu_init,
136         .exit = resourced_cpu_finalize,
137 };
138
139 MODULE_REGISTER(&cpu_modules_ops)