]> rtime.felk.cvut.cz Git - frescor/frsh.git/blob - frsh_api/frsh_contract.c
Added speed reading functions.
[frescor/frsh.git] / frsh_api / frsh_contract.c
1 /**************************************************************************/
2 /* ---------------------------------------------------------------------- */
3 /* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                 */
4 /*                                                                        */
5 /*   Universidad de Cantabria,              SPAIN                         */
6 /*   University of York,                    UK                            */
7 /*   Scuola Superiore Sant'Anna,            ITALY                         */
8 /*   Kaiserslautern University,             GERMANY                       */
9 /*   Univ. Politécnica  Valencia,           SPAIN                        */
10 /*   Czech Technical University in Prague,  CZECH REPUBLIC                */
11 /*   ENEA                                   SWEDEN                        */
12 /*   Thales Communication S.A.              FRANCE                        */
13 /*   Visual Tools S.A.                      SPAIN                         */
14 /*   Rapita Systems Ltd                     UK                            */
15 /*   Evidence                               ITALY                         */
16 /*                                                                        */
17 /*   See http://www.frescor.org for a link to partners' websites          */
18 /*                                                                        */
19 /*          FRESCOR project (FP6/2005/IST/5-034026) is funded             */
20 /*       in part by the European Union Sixth Framework Programme          */
21 /*       The European Union is not liable of any use that may be          */
22 /*       made of this code.                                               */
23 /*                                                                        */
24 /*                                                                        */
25 /*  This file is part of FRSH (FRescor ScHeduler)                         */
26 /*                                                                        */
27 /* FRSH is free software; you can redistribute it and/or modify it        */
28 /* under terms of the GNU General Public License as published by the      */
29 /* Free Software Foundation; either version 2, or (at your option) any    */
30 /* later version.  FRSH is distributed in the hope that it will be        */
31 /* useful, but WITHOUT ANY WARRANTY; without even the implied warranty    */
32 /* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU    */
33 /* General Public License for more details. You should have received a    */
34 /* copy of the GNU General Public License along with FRSH; see file       */
35 /* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
36 /* Cambridge, MA 02139, USA.                                              */
37 /*                                                                        */
38 /* As a special exception, including FRSH header files in a file,         */
39 /* instantiating FRSH generics or templates, or linking other files       */
40 /* with FRSH objects to produce an executable application, does not       */
41 /* by itself cause the resulting executable application to be covered     */
42 /* by the GNU General Public License. This exception does not             */
43 /* however invalidate any other reasons why the executable file might be  */
44 /* covered by the GNU Public License.                                     */
45 /**************************************************************************/
46
47 /**
48  * @file   frsh_contract.c
49  * @author Michal Sojka <sojkam1@fel.cvut.cz>
50  *         Dario Faggioli <faggioli@gandalf.sssup.it>
51  * 
52  * @brief  Implementation of FRSH contract API on top of FRES contracts.
53  * 
54  * 
55  */
56 #include <fres_contract.h>
57 #include <fres_contract_idl.h>
58 #include <frsh_core.h>
59 #include <frsh_error.h>
60 #include <fres_blocks.h>
61 #include <string.h>
62 #include <fcb.h>
63 #include "frsh_forb.h"
64 #include <fra_generic.h>
65 #include <frsh_energy_management.h>
66
67 /**********************************/
68 /* -----===== FRSH API =====----- */
69 /**********************************/
70
71 int
72 frsh_contract_init(frsh_contract_t *contract)
73 {
74         frsh_rel_time_t zero_msec = fosa_msec_to_rel_time(0);
75         if (!contract) return FRSH_ERR_BAD_ARGUMENT;
76         
77         *contract = fres_contract_new();
78         if (!(*contract)) goto err;
79
80         /* Set default parameters */
81         frsh_contract_set_resource_and_label(contract,
82                                              FRSH_RT_PROCESSOR,
83                                              0,
84                                              NULL);
85         frsh_contract_set_basic_params(contract,
86                                        &zero_msec,
87                                        &zero_msec,
88                                        FRSH_WT_INDETERMINATE,
89                                        FRSH_CT_REGULAR);
90         return 0;
91 err:
92         return errno;
93 }
94
95 int frsh_contract_set_basic_params
96   (frsh_contract_t *contract,
97    const frsh_rel_time_t      *budget_min,
98    const frsh_rel_time_t      *period_max,
99    const frsh_workload_t      workload,
100    const frsh_contract_type_t contract_type)
101 {
102         fres_block_basic *b;
103         int ret;
104         if (!contract ||
105             !*contract ||
106             !budget_min ||
107             !period_max) {
108                 return FRSH_ERR_BAD_ARGUMENT;
109         }
110
111         if ((fosa_rel_time_is_null(*period_max) &&
112              !fosa_rel_time_is_null(*budget_min)) ||
113             (!fosa_rel_time_is_null(*period_max) &&
114              fosa_rel_time_is_null(*budget_min)) ||
115             fosa_rel_time_smaller(*period_max, *budget_min))
116                 return FRSH_ERR_BAD_ARGUMENT;
117
118         if (workload != FRSH_WT_BOUNDED &&
119             workload != FRSH_WT_INDETERMINATE)
120                 return FRSH_ERR_BAD_ARGUMENT;
121
122         if (contract_type != FRSH_CT_REGULAR &&
123             workload != FRSH_CT_BACKGROUND &&
124             workload != FRSH_CT_DUMMY)
125                 return FRSH_ERR_BAD_ARGUMENT;
126
127         b = malloc(sizeof(*b));
128         if (!b) return ENOMEM; 
129
130         b->budget = *budget_min;
131         b->period = *period_max;
132         b->workload = workload;
133         b->contract_type = contract_type;
134
135         fres_contract_del_basic(*contract);
136         ret = fres_contract_add_basic(*contract, b);
137
138         if (ret) {
139                 free(b);
140                 return errno;
141         }
142
143         return 0;
144 }
145
146 int frsh_contract_get_basic_params
147   (const frsh_contract_t *contract,
148    frsh_rel_time_t *budget_min,
149    frsh_rel_time_t *period_max,
150    frsh_workload_t *workload,
151    frsh_contract_type_t *contract_type)
152 {
153         fres_block_basic *b;
154
155         if (!contract || !*contract)
156                 return FRSH_ERR_BAD_ARGUMENT;
157
158         b = fres_contract_get_basic(*contract);
159
160         if (workload)
161                 *workload = b->workload;
162         if (budget_min)
163                 *budget_min = b->budget;
164         if (period_max)
165                 *period_max = b->period;
166         if (contract_type)
167                 *contract_type = b->contract_type;
168
169         return 0;
170 }
171
172 int frsh_contract_set_resource_and_label
173   (frsh_contract_t *contract,
174    const frsh_resource_type_t resource_type,
175    const frsh_resource_id_t resource_id,
176    const frsh_contract_label_t contract_label)
177 {
178         fres_block_label *label;
179         fres_block_resource *r;
180         int ret;
181         
182         if (!contract || !*contract) return FRSH_ERR_BAD_ARGUMENT;
183
184         r = malloc(sizeof(*r));
185         if (!r) return ENOMEM;
186         
187         r->resource_type = resource_type;
188         r->resource_id = resource_id;
189         fres_contract_del_resource(*contract);
190         ret = fres_contract_add_resource(*contract, r);
191
192         if (ret != 0) {
193                 free(r);
194                 return errno;
195         }
196         
197
198         if (contract_label) {
199                 label = malloc(sizeof(*label));
200                 if (!label) return ENOMEM;
201                 strncpy(label->label, contract_label, sizeof(label->label));
202                 label->label[sizeof(label->label)-1] = '\0';
203                 fres_contract_del_label(*contract);
204                 ret = fres_contract_add_label(*contract, label);
205                 if (ret) {
206                         free(label);
207                         return errno;
208                 }
209         }
210         return 0;
211 }
212
213 int frsh_contract_get_resource_and_label
214   (const frsh_contract_t *contract,
215    frsh_resource_type_t *resource_type,
216    frsh_resource_id_t *resource_id,
217    frsh_contract_label_t contract_label)
218 {
219         fres_block_resource *r;
220         fres_block_label *label;
221
222         if (!contract || !*contract)
223                 return FRSH_ERR_BAD_ARGUMENT;
224
225         if (resource_type || resource_id) {
226                 r = fres_contract_get_resource(*contract);
227                 if (resource_type)
228                         *resource_type = r->resource_type;
229                 if (resource_id)
230                         *resource_id = r->resource_id;
231         }
232
233         if (contract_label) {
234                 label = fres_contract_get_label(*contract);
235                 strncpy(contract_label, label->label, sizeof(label->label));
236                 contract_label[sizeof(label->label)-1] = '\0';
237         }
238
239         return 0;
240 }
241
242 int frsh_contract_set_timing_reqs
243   (frsh_contract_t *contract,
244    const bool                   d_equals_t,
245    const frsh_rel_time_t        *deadline,
246    const frsh_signal_t          budget_overrun_signal,
247    const frsh_signal_info_t     budget_overrun_siginfo,
248    const frsh_signal_t          deadline_miss_signal,
249    const frsh_signal_info_t     deadline_miss_siginfo)
250 {
251         int ret;
252         fres_block_basic *b;
253         fres_block_timing_reqs *t;
254
255         if (!contract  || !*contract)
256                 return FRSH_ERR_BAD_ARGUMENT;
257
258         /* deadline and period must be coherent between each other */
259         b = fres_contract_get_basic(*contract);
260
261         if ((d_equals_t && deadline != FRSH_NULL_DEADLINE) ||
262             (!d_equals_t && (deadline == FRSH_NULL_DEADLINE)))
263                 return FRSH_ERR_BAD_ARGUMENT;
264
265         /* signal delivery can only be requested for BUONDED workloads */
266         if (b->workload == FRSH_WT_INDETERMINATE &&
267             (deadline_miss_signal != FRSH_NULL_SIGNAL ||
268              budget_overrun_signal != FRSH_NULL_SIGNAL))
269                 return FRSH_ERR_BAD_ARGUMENT;
270
271         t = malloc(sizeof(*t));
272         if (!t) return ENOMEM;
273         
274         t->d_equals_t = d_equals_t;
275         if (!d_equals_t) {
276                 if (deadline) {
277                         t->deadline = *deadline;
278                 } else {
279                         free(t);
280                         return FRSH_ERR_BAD_ARGUMENT;
281                 }
282         }
283
284         /* Signals are currently ignored by this implementation as
285          * they are better implemented in frsh_thread_bind() */
286         /*t->budget_overrun_signal = budget_overrun_signal;
287         t->budget_overrun_siginfo = budget_overrun_siginfo;
288         t->deadline_miss_signal = deadline_miss_signal;
289         t->deadline_miss_siginfo = deadline_miss_siginfo;*/
290         fres_contract_del_timing_reqs(*contract);
291         ret = fres_contract_add_timing_reqs(*contract, t);
292         if (ret) {
293                 free(t);
294                 return errno;
295         }
296         return 0;
297 }
298
299 int frsh_contract_get_timing_reqs
300   (const frsh_contract_t *contract,
301    bool *d_equals_t,
302    frsh_rel_time_t *deadline,
303    frsh_signal_t *budget_overrun_signal,
304    frsh_signal_info_t *budget_overrun_siginfo,
305    frsh_signal_t *deadline_miss_signal,
306    frsh_signal_info_t *deadline_miss_siginfo)
307 {
308         fres_block_timing_reqs *t;
309
310         if (!contract || !*contract)
311                 return FRSH_ERR_BAD_ARGUMENT;
312
313         t = fres_contract_get_timing_reqs(*contract);   
314
315         if (d_equals_t)
316                 *d_equals_t = t->d_equals_t;
317
318         if (deadline)
319                 *deadline = t->deadline;
320
321         return 0;
322 }
323
324 static
325 int __contract_check_min_expiration(const frsh_contract_t *contract)
326 {
327         fres_block_power_management *p;
328         int ret = 0;
329
330         p = fres_contract_get_power_management(*contract);
331         if (p && !fosa_rel_time_is_null(p->min_expiration)) {
332                 frsh_abs_time_t req_time, exp_time;
333
334                 fosa_clock_get_time(FOSA_CLOCK_REALTIME, &req_time);
335                 req_time = fosa_abs_time_incr(req_time, p->min_expiration);
336
337                 ret = frsh_battery_get_expiration(&exp_time);
338                 if (ret) goto err;
339
340                 if (fosa_abs_time_smaller(exp_time, req_time))
341                         ret = FRSH_ERR_CONTRACT_REJECTED;
342         }
343
344 err:
345         return ret;
346 }
347
348
349 int frsh_contract_negotiate
350   (const frsh_contract_t *contract,
351    frsh_vres_id_t        *vres)
352 {
353         struct forb_env env;
354         int ret;
355         fres_contract_ptr_seq contracts;
356         fres_contract_ptr contracts_buf[1];
357         fres_contract_id_seq *ids;
358         fres_block_resource *r;
359
360         if (!contract || !*contract || !vres) {
361                 ret = FRSH_ERR_BAD_ARGUMENT;
362                 goto err;
363         }
364
365         /* TODO: Battery time check should be moved to
366          * FCB. Implementation of FRSH API is meant only as a thin
367          * wrapper of FRES framework and the FRES framework could
368          * theoretically be used without FRSH API. Moreover, if there
369          * is some logging mechanism in FCB, this contract rejection
370          * will not be logged. */
371         ret = __contract_check_min_expiration(contract);
372         if (ret) goto err;
373
374         /* Activate allocator */
375         r = fres_contract_get_resource(*contract);
376         if (r) {
377                 fra_activate(r->resource_type,
378                              r->resource_id);
379         }
380
381         /* Negotiate contract */
382         contracts_buf[0] = *contract;
383         contracts._buffer = contracts_buf;
384         contracts._length = contracts._maximum = 1;
385         ret = fres_contract_broker_negotiate_contracts(frsh_forb_global.fcb,
386                                                        &contracts,
387                                                        &ids, &env);
388         if (forb_exception_occurred(&env)) {
389                 ret = FRES_ERR_FORB_EXCEPTION;
390                 goto err;
391         }
392
393         if (ret == 0) {
394                 assert(ids->_length == 1);
395                 *vres = fra_get_vres(&ids->_buffer[0]);
396         }
397         if (CORBA_sequence_get_release(ids))
398                 CORBA_free(ids->_buffer);
399         CORBA_free(ids);
400
401 err:    
402         return ret;
403 }
404
405 int frsh_contract_cancel (const frsh_vres_id_t vres)
406 {
407         int ret;
408         struct forb_env env;
409         struct fres_contract *empty_contract;
410         fres_contract_ptr_seq contracts;
411         fres_contract_id_seq *ids;
412         
413         if (!vres) {
414                 ret = FRSH_ERR_BAD_ARGUMENT;
415                 goto err;
416         }
417
418         empty_contract = fres_contract_new();
419         empty_contract->id = vres->id;
420         
421         contracts._buffer = &empty_contract;
422         contracts._length = contracts._maximum = 1;
423         ret = fres_contract_broker_negotiate_contracts(frsh_forb_global.fcb,
424                                                        &contracts,
425                                                        &ids, &env);
426         if (forb_exception_occurred(&env)) {
427                 ret = FRES_ERR_FORB_EXCEPTION;
428                 goto err;
429         }
430
431         /* The returned ID is the same as of vres */
432         if (CORBA_sequence_get_release(ids))
433                 CORBA_free(ids->_buffer);
434         CORBA_free(ids);
435 err:
436         return ret;
437 }
438
439 int frsh_contract_renegotiate_sync
440   (const frsh_contract_t *new_contract,
441    frsh_vres_id_t vres_id)
442 {
443         struct forb_env env;
444         struct fres_contract *contract;
445         int ret = 0;
446         fres_contract_ptr contracts_buf[1];
447         fres_contract_ptr_seq contracts;
448         fres_contract_id_seq *ids;
449         
450         if (!new_contract || !*new_contract || !vres_id) {
451                 ret = FRSH_ERR_BAD_ARGUMENT;
452                 goto out;
453         }
454
455         ret = __contract_check_min_expiration(new_contract);
456         if (ret) goto out;
457
458         contract = fres_contract_duplicate(*new_contract);
459         if (!contract) {
460                 ret = errno;
461                 goto out;
462         }
463
464         /* Assign the ID, so that FCB recognises that this is
465          * renegotiation */
466         contract->id = vres_id->id;
467
468         /* Renegotiate with FCB contract */
469         contracts_buf[0] = contract;
470         contracts._buffer = contracts_buf;
471         contracts._length = contracts._maximum = 1;
472         ret = fres_contract_broker_negotiate_contracts(frsh_forb_global.fcb,
473                                                        &contracts,
474                                                        &ids, &env);
475         if (forb_exception_occurred(&env)) {
476                 ret = FRES_ERR_FORB_EXCEPTION;
477                 goto err;
478         }
479
480         if (CORBA_sequence_get_release(ids))
481                 CORBA_free(ids->_buffer);
482         CORBA_free(ids);
483 err:
484         fres_contract_destroy(contract);
485 out:
486         return ret;;
487 }
488
489 int frsh_contract_renegotiate_async
490   (const frsh_contract_t *new_contract,
491    frsh_vres_id_t vres,
492    frsh_signal_t signal_to_notify,
493    frsh_signal_info_t signal_info)
494 {
495         return FRSH_ERR_NOT_IMPLEMENTED;
496 }
497
498 int frsh_group_change_mode_sync
499   (const frsh_contracts_group_t *contracts_to_neg,
500    const frsh_contracts_group_t *contracts_to_reneg,
501    const frsh_vres_group_t      *vres_to_reneg,
502    const frsh_vres_group_t      *vres_to_cancel,
503    frsh_vres_group_t            *new_vres)
504 {
505         return FRSH_ERR_NOT_IMPLEMENTED;
506 }
507
508 int frsh_group_change_mode_async
509   (const frsh_contracts_group_t *contracts_to_neg,
510    const frsh_contracts_group_t *contracts_to_reneg,
511    const frsh_vres_group_t      *vres_to_reneg,
512    const frsh_vres_group_t      *vres_to_cancel,
513    const frsh_signal_t          signal,
514    const frsh_signal_info_t     signal_info,
515    frsh_group_id_t              *group)
516 {
517         return FRSH_ERR_NOT_IMPLEMENTED;
518 }
519