]> rtime.felk.cvut.cz Git - frescor/frsh.git/blob - frsh_api/frsh_power.c
Fixed warnings caused by the previous merge
[frescor/frsh.git] / frsh_api / frsh_power.c
1 /**
2  * @file   frsh_power.c
3  * @author Michael Trimarchi <trimarchimichael@yahoo.it>
4  *         Dario Faggioli <faggioli@gandalf.sssup.it>
5  *
6  * @brief  FRSH core thread related functions not implamented in managers..
7  *
8  *
9  */
10
11 #include <string.h>
12
13 #include <fres_contract.h>
14 #include <fres_contract_idl.h>
15 #include <fres_blocks.h>
16 #include <fcb.h>
17 #include <fra_generic.h>
18 #include <frsh_forb.h>
19 #include "frsh_resources.h"
20 #ifdef CONFIG_ACPI_CPU
21 #  include <fra_acpi_cpu.h>
22 #endif
23 #ifdef CONFIG_ACPI_BATTERY
24 #  include "fra_acpi_battery.h"
25 #endif
26 #ifdef CONFIG_ACPI_LCD
27 #  include <fra_acpi_lcd.h>
28 #endif
29 #include <frsh.h>
30
31 static inline int __is_a_valid_power(int level)
32 {
33         if (level >= 0 && level < 3 )
34                 return 1;
35
36         return 0;
37 }
38
39 static inline
40 fres_block_power_management *__dup_power_management(frsh_contract_t *contract)
41 {
42         fres_block_power_management *p, *old_p;
43
44         old_p = fres_contract_get_power_management(*contract);
45         p = malloc(sizeof(*p));
46         if (!p) return 0;
47         /**
48          * Needed since frsh_contract_del_xxx frees the
49          *  old block.
50          **/
51         if (old_p)
52                 memcpy(p, old_p, sizeof(*old_p));
53         else
54                 bzero(p, sizeof(*p));
55
56         return p;
57 }
58
59 int frsh_contract_set_min_expiration(frsh_contract_t *contract,
60                                      frsh_rel_time_t min_expiration)
61 {
62         fres_block_power_management *p;
63         int ret;
64
65         if (!contract || !*contract)
66                 return FRSH_ERR_BAD_ARGUMENT;
67
68         p = __dup_power_management(contract);
69         if (!p)
70                 return ENOMEM;
71
72         p->min_expiration = min_expiration;
73
74         fres_contract_del_power_management(*contract);
75         ret = fres_contract_add_power_management(*contract, p);
76         if (ret) {
77                 free(p);
78                 return errno;
79         }
80
81         return FRSH_NO_ERROR;
82 }
83
84 int frsh_contract_get_min_expiration(const frsh_contract_t *contract,
85                                      frsh_rel_time_t *min_expiration)
86 {
87         fres_block_power_management *p;
88
89         if (!contract || !*contract)
90                 return FRSH_ERR_BAD_ARGUMENT;
91
92         p = fres_contract_get_power_management(*contract);
93         if (!p)
94                 return FRSH_ERR_BAD_ARGUMENT;
95
96         *min_expiration = p->min_expiration;
97
98         return FRSH_NO_ERROR;
99 }
100
101 int frsh_contract_set_min_budget_pow
102   (frsh_contract_t *contract,
103    frsh_power_level_t power_level,
104    const frsh_rel_time_t *pow_min_budget)
105 {
106         fres_block_power_management *b;
107         int ret;
108
109         if (!contract || !*contract ||
110             !pow_min_budget)
111                 return FRSH_ERR_BAD_ARGUMENT;
112
113         b = __dup_power_management(contract);
114         if (!b)
115                 return ENOMEM;
116
117         b->min_budget[power_level] = *pow_min_budget;
118
119         fres_contract_del_power_management(*contract);
120         ret = fres_contract_add_power_management(*contract, b);
121         if (ret) {
122                 free(b);
123                 return errno;
124         }
125
126         return FRSH_NO_ERROR;
127 }
128
129 int frsh_contract_get_min_budget_pow
130   (const frsh_contract_t *contract,
131    frsh_power_level_t power_level,
132    frsh_rel_time_t *pow_min_budget)
133 {
134         fres_block_power_management *b;
135
136         if (!contract || !*contract ||
137             !__is_a_valid_power(power_level))
138                 return FRSH_ERR_BAD_ARGUMENT;
139
140         b = fres_contract_get_power_management(*contract);
141         if (!b)
142                 return FRSH_ERR_BAD_ARGUMENT;
143
144         *pow_min_budget = b->min_budget[power_level];
145
146         return FRSH_NO_ERROR;
147 }
148
149 int frsh_contract_set_max_budget_pow
150   (frsh_contract_t *contract,
151    frsh_power_level_t power_level,
152    const frsh_rel_time_t *pow_max_budget)
153 {
154         fres_block_power_management *b;
155         int ret;
156
157         if (!contract || !*contract ||
158             !pow_max_budget || !__is_a_valid_power(power_level))
159                 return FRSH_ERR_BAD_ARGUMENT;
160
161         b = __dup_power_management(contract);
162         if (!b)
163                 return ENOMEM;
164
165         b->max_budget[power_level] = *pow_max_budget;
166
167         fres_contract_del_power_management(*contract);
168         ret = fres_contract_add_power_management(*contract, b);
169         if (ret) {
170                 free(b);
171                 return errno;
172         }
173
174         return FRSH_NO_ERROR;
175 }
176
177 int frsh_contract_get_max_budget_pow(const frsh_contract_t *contract,
178                                      frsh_power_level_t power_level,
179                                      frsh_rel_time_t *pow_max_budget)
180 {
181         fres_block_power_management *b;
182
183         if (!contract || !*contract ||
184             !__is_a_valid_power(power_level)) {
185                 return FRSH_ERR_BAD_ARGUMENT;
186         }
187
188         b = fres_contract_get_power_management(*contract);
189         if (!b)
190                 return FRSH_ERR_BAD_ARGUMENT;
191
192         *pow_max_budget = b->max_budget[power_level];
193
194         return FRSH_NO_ERROR;
195 }
196
197 int frsh_contract_set_utilization_pow
198   (frsh_contract_t *contract,
199    frsh_power_level_t power_level,
200    const frsh_rel_time_t *budget,
201    const frsh_rel_time_t *period,
202    const frsh_rel_time_t *deadline)
203 {
204         return FRSH_ERR_NOT_IMPLEMENTED;
205 }
206
207 int frsh_contract_get_utilization_pow
208   (const frsh_contract_t *contract,
209    frsh_power_level_t power_level,
210    frsh_rel_time_t *budget,
211    frsh_rel_time_t *period,
212    frsh_rel_time_t *deadline)
213 {
214         return FRSH_ERR_NOT_IMPLEMENTED;;
215 }
216
217 /* FIXME: What happens when one application set one power-level and
218  * second application different level. I think this function should
219  * not be part of API. It should be used internally (e.g. by contract
220  * broker) to achieve the requirements specified by
221  * frsh_contract_set_min_expiration() and similar functions.
222  *
223  * This implementation also skips FCB when doing changes to resources,
224  * which is certainly not good, because resource manager does not know
225  * about the change.
226  */
227 int frsh_resource_set_power_level
228   (frsh_resource_type_t resource_type,
229    frsh_resource_id_t resource_id,
230    frsh_power_level_t power_level)
231 {
232
233         if (!__is_a_valid_power(power_level))
234                 return FRSH_ERR_BAD_ARGUMENT;
235
236         switch(resource_type)
237         {
238 #ifdef CONFIG_ACPI_CPU
239                 case FRSH_RT_PROCESSOR:
240                 {
241                         int ret;
242                         ret = fra_CPU_power_init(resource_id);
243                         if (ret) return FRSH_ERR_INTERNAL_ERROR;
244                         ret = fra_CPU_set_power(resource_id, power_level);
245                         if (ret) return FRSH_ERR_INTERNAL_ERROR;
246
247                         /**
248                          * @TODO:
249                          * if (i budget sono effettivamente diversi)
250                          *      rinegozia i contratti coi nuovi valori
251                          **/
252                         break;
253                 }
254 #endif
255 #ifdef CONFIG_ACPI_LCD
256                 case FRSH_RT_LCD:
257                 {
258                         int ret;
259                         ret = fra_LCD_power_init(resource_id);
260                         if (ret) return FRSH_ERR_INTERNAL_ERROR;
261                         ret = fra_LCD_set_power(resource_id, power_level);
262                         if (ret) return FRSH_ERR_INTERNAL_ERROR;
263                         break;
264                 }
265 #endif
266                 default:
267                         return FRSH_ERR_NOT_IMPLEMENTED;
268         }
269
270         return FRSH_NO_ERROR;
271 }
272
273 int frsh_resource_get_power_level
274   (frsh_resource_type_t resource_type,
275    frsh_resource_id_t resource_id,
276    frsh_power_level_t *power_level)
277 {
278         switch(resource_type)
279         {
280 #ifdef CONFIG_ACPI_CPU
281                 case FRSH_RT_PROCESSOR:
282                 {
283                         int ret;
284                         ret = fra_CPU_get_power(resource_id,
285                                                 (int*) power_level);
286                         if (ret) return FRSH_ERR_INTERNAL_ERROR;
287
288                         break;
289                 }
290 #endif
291 #ifdef CONFIG_ACPI_LCD
292                 case FRSH_RT_LCD:
293                 {
294                         int ret;
295                         ret = fra_LCD_get_power(resource_id,
296                                                 (int*) power_level);
297                         if (ret) return FRSH_ERR_INTERNAL_ERROR;
298
299                         break;
300                 }
301 #endif
302                 default:
303                         return FRSH_ERR_NOT_IMPLEMENTED;
304         }
305
306         return FRSH_NO_ERROR;
307 }
308
309 int frsh_resource_get_num_power_levels
310   (frsh_resource_type_t resource_type,
311    frsh_resource_id_t resource_id,
312    frsh_power_level_t *num_power_levels)
313 {
314         int ret;
315
316         *num_power_levels = 1;
317
318         switch(resource_type)
319         {
320                 case FRSH_RT_PROCESSOR:
321                 {
322                         ret = fra_CPU_power_init(resource_id);
323                         if (ret) goto ret;
324
325                         break;
326                 }
327                 case FRSH_RT_LCD:
328                 {
329                         ret = fra_LCD_power_init(resource_id);
330                         if (ret) goto ret;
331
332                         break;
333                 }
334                 default:
335                         return FRSH_ERR_NOT_IMPLEMENTED;
336         }
337
338         /**
339          * @FIXME:
340          *   This looks tremendous... But the number '3' is hardcoded
341          *   whereever in the headers as the number of power level, so...
342          */
343         *num_power_levels = 3;
344
345 ret:
346         return FRSH_NO_ERROR;
347 }
348
349 int frsh_battery_get_expiration(frsh_abs_time_t *expiration)
350 {
351 #ifdef CONFIG_ACPI_BATTERY
352         frsh_rel_time_t interval;
353         int ret;
354
355         ret = fra_battery_init();
356         if (ret) return FRSH_ERR_INTERNAL_ERROR;
357
358         ret = fra_battery_expiration(&interval);
359         if (ret == EAGAIN) {
360                 *expiration = fosa_msec_to_abs_time(0);
361                 goto out;
362         }
363         if (ret)
364                 return FRSH_ERR_INTERNAL_ERROR;
365
366         fosa_clock_get_time(FOSA_CLOCK_REALTIME, expiration);
367         *expiration = fosa_abs_time_incr(*expiration, interval);
368
369 out:
370         return FRSH_NO_ERROR;
371 #else
372         return FRSH_ERR_NOT_IMPLEMENTED;        
373 #endif
374 }
375