tizen 2.3 release
[framework/system/deviced.git] / src / pass / pass-gov-step.c
1 /*
2  * deviced
3  *
4  * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd.
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 #include <stdbool.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22
23 #include "pass.h"
24
25 /*
26  * pass_step_governor - Check cpu state and determine the amount of resource
27  *
28  * @stats: structure for getting cpu frequency state from kerncel
29  *
30  * This function check periodically current following state of system
31  * and then determine whether pass level up or down according to pass
32  * policy with gathered data.
33  * - current cpu frequency
34  * - the number of nr_running
35  * - the number of busy_cpu
36  */
37 int pass_step_governor(struct pass_policy *policy)
38 {
39         struct pass_table *table = policy->pass_table;
40         struct pass_cpu_stats *cpu_stats = policy->pass_cpu_stats;
41         int up_threshold = policy->up_threshold;
42         int down_threshold = policy->down_threshold;
43         int num_pass_gov = 0;
44         int level = policy->curr_level;
45         int count = 0;
46         int up_count = 0;
47         int up_max_count = 0;
48         int down_count = 0;
49         bool up_condition;
50         bool down_condition;
51         int freq;
52         int nr_running;
53         int busy_cpu;
54         int i;
55         int j;
56         int64_t time;
57         static int64_t last_time = 0;
58
59         for (i = 0; i < policy->num_pass_cpu_stats; i++) {
60                 time = cpu_stats[i].time;
61                 freq = cpu_stats[i].freq;
62                 nr_running = cpu_stats[i].nr_runnings;
63                 busy_cpu = cpu_stats[i].num_busy_cpu;
64                 up_condition = false;
65                 down_condition = false;
66
67                 if (last_time >= time)
68                         continue;
69                 last_time = time;
70                 num_pass_gov++;
71
72                 /* Check level up condition */
73                 for (j = 0; j < table[level].num_up_cond; j++) {
74                         /*
75                          * If one more conditions are false among following
76                          * conditions, don't increment up_count.
77                          */
78                         if (freq >= table[level].up_cond[j].freq
79                                 && nr_running >= table[level].up_cond[j].nr_running
80                                 && busy_cpu >= table[level].up_cond[j].busy_cpu)
81                                 up_condition = true;
82                 }
83
84                 if (table[level].num_up_cond && up_condition) {
85                         up_count++;
86
87                         /*
88                         _I("[Level%d] [up_count : %2d] \
89                                 freq(%d), nr_running(%d), busy_cpu(%d)",
90                                 level, up_count,
91                                 table[level].up_cond[j].freq ? freq : -1,
92                                 table[level].up_cond[j].nr_running ? nr_running : -1,
93                                 table[level].up_cond[j].busy_cpu ? busy_cpu : -1);
94                         */
95                 }
96
97                 /* Check level down condition */
98                 for (j = 0; j < table[level].num_down_cond; j++) {
99                         /*
100                          * If one more conditions are false among following
101                          * conditions, don't increment down_count.
102                          */
103                         if (freq <= table[level].down_cond[j].freq
104                                 && nr_running < table[level].down_cond[j].nr_running
105                                 && busy_cpu < table[level].down_cond[j].busy_cpu)
106                                 down_condition = true;
107                 }
108
109                 if (table[level].num_down_cond && down_condition) {
110                         down_count++;
111
112                         /*
113                         _I("[Level%d] [dw_count : %2d] \
114                                 freq(%d), nr_running(%d), busy_cpu(%d)",
115                                 level, down_count,
116                                 table[level].down_cond[j].freq ? freq : -1,
117                                 table[level].down_cond[j].nr_running ? nr_running : -1,
118                                 table[level].down_cond[j].busy_cpu ? busy_cpu : -1);
119                         */
120                 }
121
122                 if (level < policy->max_level &&
123                         freq == table[level].limit_max_freq)
124                         up_max_count++;
125         }
126
127         if (!num_pass_gov)
128                 return level;
129
130         if (up_count && level < policy->max_level &&
131                         up_count * 100 >= num_pass_gov * up_threshold) {
132                 level += 1;
133         } else if (down_count && level > policy->min_level &&
134                         down_count * 100 >= num_pass_gov * down_threshold) {
135                 level -= 1;
136         }
137
138         return level;
139 }