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.
22 * @desc control timer about timer-slack cgroup
23 * Copyright (c) 2013 Samsung Electronics Co., Ltd. All rights reserved.
28 #include "module-data.h"
29 #include "edbus-handler.h"
30 #include "resourced.h"
34 #include "config-parser.h"
36 #include "timer-slack.h"
38 #include "proc-main.h"
39 #include "proc-process.h"
41 #include <resourced.h>
45 #include <sys/types.h>
48 #define TIMER_EXCLUDE_CGROUP "exclude"
49 #define TIMER_SERVICE_CGROUP "service"
50 #define TIMER_BACKGRD_CGROUP "background"
51 #define TIMER_STATUS_LCDOFF "LCDOFF"
52 #define TIMER_SLACK_ROOT NULL
53 #define TIMER_STATUS_POWERSAVING "POWERSAVING"
55 #define TIMER_CONF_FILE "/etc/resourced/timer-slack.conf"
56 #define EXCLUDE_CONF_SECTION "EXCLUDE_TIMER_SLACK"
57 #define EXCLUDE_CONF_NAME "EXCLUDE_PROC_NAME"
59 #define TIMER_SLACK_MODE "/timer_slack.timer_mode"
60 #define TIMER_SLACK_VALUE "/timer_slack.min_slack_ns"
62 struct timer_slack_class {
71 TIMER_SLACK_BACKGROUND,
73 TIMER_SLACK_POWERSAVIG,
77 static struct timer_slack_class timer_slack[TIMER_SLACK_MAX] = {
79 {TIMER_SERVICE_CGROUP, 0, 0},
80 {TIMER_BACKGRD_CGROUP, 0, 0},
81 {TIMER_STATUS_LCDOFF, 0, 0},
82 {TIMER_STATUS_POWERSAVING, 0, 0},
85 static int current_root_timer_state = TIMER_SLACK_DEFAULT;
87 static const struct module_ops timer_modules_ops;
88 static const struct module_ops *timer_ops;
90 static int timer_slack_write(char *sub_cgroup, char *node, int val)
92 char path_buf[MAX_PATH_LENGTH];
95 snprintf(path_buf, sizeof(path_buf), "%s/%s", TIMER_CGROUP_PATH, sub_cgroup);
96 ret = cgroup_write_node(path_buf, node, val);
98 ret = cgroup_write_node(TIMER_CGROUP_PATH, node, val);
102 static int launch_service(void *data)
104 struct proc_status *p_data = (struct proc_status*)data;
106 ret = timer_slack_write(TIMER_SERVICE_CGROUP, CGROUP_FILE_NAME, p_data->pid);
107 _I("move to service timer slack cgroup : pid (%d), ret (%d)", p_data->pid, ret);
111 static int wakeup_timer_state(void *data)
113 struct proc_status *p_data = (struct proc_status*)data;
115 ret = timer_slack_write(TIMER_EXCLUDE_CGROUP, CGROUP_FILE_NAME, p_data->pid);
119 static int background_timer_state(void *data)
121 struct proc_status *p_data = (struct proc_status*)data;
123 ret = timer_slack_write(TIMER_BACKGRD_CGROUP, CGROUP_FILE_NAME, p_data->pid);
127 static int active_timer_state(void *data)
129 struct proc_status *p_data = (struct proc_status*)data;
131 ret = timer_slack_write(TIMER_EXCLUDE_CGROUP, CGROUP_FILE_NAME, p_data->pid);
135 static int inactive_timer_state(void *data)
137 struct proc_status *p_data = (struct proc_status*)data;
139 ret = timer_slack_write(TIMER_SLACK_ROOT, CGROUP_FILE_NAME, p_data->pid);
143 static int timer_lcd_off(void *data)
145 if (current_root_timer_state == TIMER_SLACK_DEFAULT) {
146 timer_slack_write(TIMER_SLACK_ROOT, TIMER_SLACK_MODE,
147 timer_slack[TIMER_SLACK_LCDOFF].timer_mode);
148 timer_slack_write(TIMER_SLACK_ROOT, TIMER_SLACK_VALUE,
149 timer_slack[TIMER_SLACK_LCDOFF].slack_value);
151 current_root_timer_state = TIMER_SLACK_LCDOFF;
152 return RESOURCED_ERROR_NONE;
155 static int timer_lcd_on(void *data)
157 if (current_root_timer_state == TIMER_SLACK_LCDOFF) {
158 timer_slack_write(TIMER_SLACK_ROOT, TIMER_SLACK_MODE,
159 timer_slack[TIMER_SLACK_DEFAULT].timer_mode);
160 timer_slack_write(TIMER_SLACK_ROOT, TIMER_SLACK_VALUE,
161 timer_slack[TIMER_SLACK_DEFAULT].slack_value);
162 current_root_timer_state = TIMER_SLACK_DEFAULT;
164 return RESOURCED_ERROR_NONE;
167 static void set_default_cgroup_value(void)
171 for (i = 0; i < TIMER_SLACK_MAX; i++) {
172 if (i == TIMER_SLACK_DEFAULT)
173 cgroup = TIMER_SLACK_ROOT;
174 else if (i == TIMER_SLACK_SERVICE)
175 cgroup = TIMER_SERVICE_CGROUP;
176 else if (i == TIMER_SLACK_BACKGROUND)
177 cgroup = TIMER_BACKGRD_CGROUP;
180 timer_slack_write(cgroup, TIMER_SLACK_MODE, timer_slack[i].timer_mode);
181 timer_slack_write(cgroup, TIMER_SLACK_VALUE, timer_slack[i].slack_value);
185 static int load_timer_config(struct parse_result *result, void *user_data)
193 if (!strcmp(result->section, EXCLUDE_CONF_SECTION)) {
194 if (strcmp(result->name, EXCLUDE_CONF_NAME))
195 return RESOURCED_ERROR_NO_DATA;
196 pid = find_pid_from_cmdline(result->value);
198 timer_slack_write(TIMER_EXCLUDE_CGROUP, CGROUP_FILE_NAME, pid);
200 for (i = 0; i < TIMER_SLACK_MAX; i++) {
201 if (strcmp(result->section, timer_slack[i].name))
203 if (!strcmp(result->name, "timer_mode"))
204 timer_slack[i].timer_mode = atoi(result->value);
205 if (!strcmp(result->name, "min_slack_ns"))
206 timer_slack[i].slack_value = atoi(result->value);
209 return RESOURCED_ERROR_NONE;
212 static void timer_slack_cgroup_init(void)
214 make_cgroup_subdir(TIMER_CGROUP_PATH, TIMER_EXCLUDE_CGROUP, NULL);
215 make_cgroup_subdir(TIMER_CGROUP_PATH, TIMER_SERVICE_CGROUP, NULL);
216 make_cgroup_subdir(TIMER_CGROUP_PATH, TIMER_BACKGRD_CGROUP, NULL);
218 config_parse(TIMER_CONF_FILE, load_timer_config, NULL);
219 set_default_cgroup_value();
222 static int resourced_timer_slack_check_runtime_support(void *data)
226 dir = opendir(TIMER_CGROUP_PATH);
230 return RESOURCED_ERROR_NONE;
232 return RESOURCED_ERROR_NO_DATA;
235 static int resourced_timer_slack_init(void *data)
237 timer_ops = &timer_modules_ops;
239 timer_slack_cgroup_init();
241 register_notifier(RESOURCED_NOTIFIER_SERVICE_LAUNCH, launch_service);
242 register_notifier(RESOURCED_NOTIFIER_APP_RESUME, wakeup_timer_state);
243 register_notifier(RESOURCED_NOTIFIER_APP_FOREGRD, wakeup_timer_state);
244 register_notifier(RESOURCED_NOTIFIER_APP_BACKGRD, background_timer_state);
245 register_notifier(RESOURCED_NOTIFIER_APP_ACTIVE, active_timer_state);
246 register_notifier(RESOURCED_NOTIFIER_APP_INACTIVE, inactive_timer_state);
247 register_notifier(RESOURCED_NOTIFIER_LCD_ON, timer_lcd_on);
248 register_notifier(RESOURCED_NOTIFIER_LCD_OFF, timer_lcd_off);
249 return RESOURCED_ERROR_NONE;
252 static int resourced_timer_slack_finalize(void *data)
254 unregister_notifier(RESOURCED_NOTIFIER_SERVICE_LAUNCH, launch_service);
255 unregister_notifier(RESOURCED_NOTIFIER_APP_RESUME, wakeup_timer_state);
256 unregister_notifier(RESOURCED_NOTIFIER_APP_FOREGRD, wakeup_timer_state);
257 unregister_notifier(RESOURCED_NOTIFIER_APP_BACKGRD, background_timer_state);
258 unregister_notifier(RESOURCED_NOTIFIER_APP_ACTIVE, active_timer_state);
259 unregister_notifier(RESOURCED_NOTIFIER_APP_INACTIVE, inactive_timer_state);
260 unregister_notifier(RESOURCED_NOTIFIER_LCD_ON, timer_lcd_on);
261 unregister_notifier(RESOURCED_NOTIFIER_LCD_OFF, timer_lcd_off);
262 return RESOURCED_ERROR_NONE;
265 static const struct module_ops timer_modules_ops = {
266 .priority = MODULE_PRIORITY_NORMAL,
267 .name = TIMER_MODULE_NAME,
268 .init = resourced_timer_slack_init,
269 .exit = resourced_timer_slack_finalize,
270 .check_runtime_support = resourced_timer_slack_check_runtime_support,
272 MODULE_REGISTER(&timer_modules_ops)