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 strncpy(path_buf, TIMER_CGROUP_PATH, sizeof(TIMER_CGROUP_PATH));
96 strcat(path_buf, "/");
97 strcat(path_buf, sub_cgroup);
98 ret = cgroup_write_node(path_buf, node, val);
100 ret = cgroup_write_node(TIMER_CGROUP_PATH, node, val);
104 static int launch_service(void *data)
106 struct proc_status *p_data = (struct proc_status*)data;
108 ret = timer_slack_write(TIMER_SERVICE_CGROUP, CGROUP_FILE_NAME, p_data->pid);
109 _I("move to service timer slack cgroup : pid (%d), ret (%d)", p_data->pid, ret);
113 static int wakeup_timer_state(void *data)
115 struct proc_status *p_data = (struct proc_status*)data;
117 ret = timer_slack_write(TIMER_EXCLUDE_CGROUP, CGROUP_FILE_NAME, p_data->pid);
121 static int background_timer_state(void *data)
123 struct proc_status *p_data = (struct proc_status*)data;
125 ret = timer_slack_write(TIMER_BACKGRD_CGROUP, CGROUP_FILE_NAME, p_data->pid);
129 static int active_timer_state(void *data)
131 struct proc_status *p_data = (struct proc_status*)data;
133 ret = timer_slack_write(TIMER_EXCLUDE_CGROUP, CGROUP_FILE_NAME, p_data->pid);
137 static int inactive_timer_state(void *data)
139 struct proc_status *p_data = (struct proc_status*)data;
141 ret = timer_slack_write(TIMER_SLACK_ROOT, CGROUP_FILE_NAME, p_data->pid);
145 static int timer_lcd_off(void *data)
147 if (current_root_timer_state == TIMER_SLACK_DEFAULT) {
148 timer_slack_write(TIMER_SLACK_ROOT, TIMER_SLACK_MODE,
149 timer_slack[TIMER_SLACK_LCDOFF].timer_mode);
150 timer_slack_write(TIMER_SLACK_ROOT, TIMER_SLACK_VALUE,
151 timer_slack[TIMER_SLACK_LCDOFF].slack_value);
153 current_root_timer_state = TIMER_SLACK_LCDOFF;
154 return RESOURCED_ERROR_NONE;
157 static int timer_lcd_on(void *data)
159 if (current_root_timer_state == TIMER_SLACK_LCDOFF) {
160 timer_slack_write(TIMER_SLACK_ROOT, TIMER_SLACK_MODE,
161 timer_slack[TIMER_SLACK_DEFAULT].timer_mode);
162 timer_slack_write(TIMER_SLACK_ROOT, TIMER_SLACK_VALUE,
163 timer_slack[TIMER_SLACK_DEFAULT].slack_value);
164 current_root_timer_state = TIMER_SLACK_DEFAULT;
166 return RESOURCED_ERROR_NONE;
169 static void set_default_cgroup_value(void)
173 for (i = 0; i < TIMER_SLACK_MAX; i++) {
174 if (i == TIMER_SLACK_DEFAULT)
175 cgroup = TIMER_SLACK_ROOT;
176 else if (i == TIMER_SLACK_SERVICE)
177 cgroup = TIMER_SERVICE_CGROUP;
178 else if (i == TIMER_SLACK_BACKGROUND)
179 cgroup = TIMER_BACKGRD_CGROUP;
182 timer_slack_write(cgroup, TIMER_SLACK_MODE, timer_slack[i].timer_mode);
183 timer_slack_write(cgroup, TIMER_SLACK_VALUE, timer_slack[i].slack_value);
187 static int load_timer_config(struct parse_result *result, void *user_data)
195 if (!strcmp(result->section, EXCLUDE_CONF_SECTION)) {
196 if (strcmp(result->name, EXCLUDE_CONF_NAME))
197 return RESOURCED_ERROR_NO_DATA;
198 pid = find_pid_from_cmdline(result->value);
200 timer_slack_write(TIMER_EXCLUDE_CGROUP, CGROUP_FILE_NAME, pid);
202 for (i = 0; i < TIMER_SLACK_MAX; i++) {
203 if (strcmp(result->section, timer_slack[i].name))
205 if (!strcmp(result->name, "timer_mode"))
206 timer_slack[i].timer_mode = atoi(result->value);
207 if (!strcmp(result->name, "min_slack_ns"))
208 timer_slack[i].slack_value = atoi(result->value);
211 return RESOURCED_ERROR_NONE;
214 static void timer_slack_cgroup_init(void)
216 make_cgroup_subdir(TIMER_CGROUP_PATH, TIMER_EXCLUDE_CGROUP, NULL);
217 make_cgroup_subdir(TIMER_CGROUP_PATH, TIMER_SERVICE_CGROUP, NULL);
218 make_cgroup_subdir(TIMER_CGROUP_PATH, TIMER_BACKGRD_CGROUP, NULL);
220 config_parse(TIMER_CONF_FILE, load_timer_config, NULL);
221 set_default_cgroup_value();
224 static int resourced_timer_slack_check_runtime_support(void *data)
228 dir = opendir(TIMER_CGROUP_PATH);
232 return RESOURCED_ERROR_NONE;
234 return RESOURCED_ERROR_NO_DATA;
237 static int resourced_timer_slack_init(void *data)
239 timer_ops = &timer_modules_ops;
241 timer_slack_cgroup_init();
243 register_notifier(RESOURCED_NOTIFIER_SERVICE_LAUNCH, launch_service);
244 register_notifier(RESOURCED_NOTIFIER_APP_RESUME, wakeup_timer_state);
245 register_notifier(RESOURCED_NOTIFIER_APP_FOREGRD, wakeup_timer_state);
246 register_notifier(RESOURCED_NOTIFIER_APP_BACKGRD, background_timer_state);
247 register_notifier(RESOURCED_NOTIFIER_APP_ACTIVE, active_timer_state);
248 register_notifier(RESOURCED_NOTIFIER_APP_INACTIVE, inactive_timer_state);
249 register_notifier(RESOURCED_NOTIFIER_LCD_ON, timer_lcd_on);
250 register_notifier(RESOURCED_NOTIFIER_LCD_OFF, timer_lcd_off);
251 return RESOURCED_ERROR_NONE;
254 static int resourced_timer_slack_finalize(void *data)
256 unregister_notifier(RESOURCED_NOTIFIER_SERVICE_LAUNCH, launch_service);
257 unregister_notifier(RESOURCED_NOTIFIER_APP_RESUME, wakeup_timer_state);
258 unregister_notifier(RESOURCED_NOTIFIER_APP_FOREGRD, wakeup_timer_state);
259 unregister_notifier(RESOURCED_NOTIFIER_APP_BACKGRD, background_timer_state);
260 unregister_notifier(RESOURCED_NOTIFIER_APP_ACTIVE, active_timer_state);
261 unregister_notifier(RESOURCED_NOTIFIER_APP_INACTIVE, inactive_timer_state);
262 unregister_notifier(RESOURCED_NOTIFIER_LCD_ON, timer_lcd_on);
263 unregister_notifier(RESOURCED_NOTIFIER_LCD_OFF, timer_lcd_off);
264 return RESOURCED_ERROR_NONE;
267 static const struct module_ops timer_modules_ops = {
268 .priority = MODULE_PRIORITY_NORMAL,
269 .name = TIMER_MODULE_NAME,
270 .init = resourced_timer_slack_init,
271 .exit = resourced_timer_slack_finalize,
272 .check_runtime_support = resourced_timer_slack_check_runtime_support,
274 MODULE_REGISTER(&timer_modules_ops)