1 /**************************************************************************/
2 /* ---------------------------------------------------------------------- */
3 /* Copyright (C) 2006 - 2008 FRESCOR consortium partners: */
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 */
12 /* Thales Communication S.A. FRANCE */
13 /* Visual Tools S.A. SPAIN */
14 /* Rapita Systems Ltd UK */
17 /* See http://www.frescor.org for a link to partners' websites */
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. */
25 /* This file is part of FRSH (FRescor ScHeduler) */
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. */
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 /**************************************************************************/
48 * @file frsh_contract.c
49 * @author Michal Sojka <sojkam1@fel.cvut.cz>
50 * Dario Faggioli <faggioli@gandalf.sssup.it>
52 * @brief Implementation of FRSH contract API on top of FRES contracts.
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>
63 #include "frsh_forb.h"
64 #include <fra_generic.h>
65 #include <frsh_energy_management.h>
67 /**********************************/
68 /* -----===== FRSH API =====----- */
69 /**********************************/
72 frsh_contract_init(frsh_contract_t *contract)
74 frsh_rel_time_t zero_msec = fosa_msec_to_rel_time(0);
75 if (!contract) return FRSH_ERR_BAD_ARGUMENT;
77 *contract = fres_contract_new();
78 if (!(*contract)) goto err;
80 /* Set default parameters */
81 frsh_contract_set_resource_and_label(contract,
85 frsh_contract_set_basic_params(contract,
88 FRSH_WT_INDETERMINATE,
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)
108 return FRSH_ERR_BAD_ARGUMENT;
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;
118 if (workload != FRSH_WT_BOUNDED &&
119 workload != FRSH_WT_INDETERMINATE)
120 return FRSH_ERR_BAD_ARGUMENT;
122 if (contract_type != FRSH_CT_REGULAR &&
123 workload != FRSH_CT_BACKGROUND &&
124 workload != FRSH_CT_DUMMY)
125 return FRSH_ERR_BAD_ARGUMENT;
127 b = malloc(sizeof(*b));
128 if (!b) return ENOMEM;
130 b->budget = *budget_min;
131 b->period = *period_max;
132 b->workload = workload;
133 b->contract_type = contract_type;
135 fres_contract_del_basic(*contract);
136 ret = fres_contract_add_basic(*contract, b);
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)
155 if (!contract || !*contract)
156 return FRSH_ERR_BAD_ARGUMENT;
158 b = fres_contract_get_basic(*contract);
161 *workload = b->workload;
163 *budget_min = b->budget;
165 *period_max = b->period;
167 *contract_type = b->contract_type;
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)
178 fres_block_label *label;
179 fres_block_resource *r;
182 if (!contract || !*contract) return FRSH_ERR_BAD_ARGUMENT;
184 r = malloc(sizeof(*r));
185 if (!r) return ENOMEM;
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);
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);
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)
219 fres_block_resource *r;
220 fres_block_label *label;
222 if (!contract || !*contract)
223 return FRSH_ERR_BAD_ARGUMENT;
225 if (resource_type || resource_id) {
226 r = fres_contract_get_resource(*contract);
228 *resource_type = r->resource_type;
230 *resource_id = r->resource_id;
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';
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)
253 fres_block_timing_reqs *t;
255 if (!contract || !*contract)
256 return FRSH_ERR_BAD_ARGUMENT;
258 /* deadline and period must be coherent between each other */
259 b = fres_contract_get_basic(*contract);
261 if ((d_equals_t && deadline != FRSH_NULL_DEADLINE) ||
262 (!d_equals_t && (deadline == FRSH_NULL_DEADLINE)))
263 return FRSH_ERR_BAD_ARGUMENT;
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;
271 t = malloc(sizeof(*t));
272 if (!t) return ENOMEM;
274 t->d_equals_t = d_equals_t;
277 t->deadline = *deadline;
280 return FRSH_ERR_BAD_ARGUMENT;
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);
299 int frsh_contract_get_timing_reqs
300 (const frsh_contract_t *contract,
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)
308 fres_block_timing_reqs *t;
310 if (!contract || !*contract)
311 return FRSH_ERR_BAD_ARGUMENT;
313 t = fres_contract_get_timing_reqs(*contract);
316 *d_equals_t = t->d_equals_t;
319 *deadline = t->deadline;
325 int __contract_check_min_expiration(const frsh_contract_t *contract)
327 fres_block_power_management *p;
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;
334 fosa_clock_get_time(FOSA_CLOCK_REALTIME, &req_time);
335 req_time = fosa_abs_time_incr(req_time, p->min_expiration);
337 ret = frsh_battery_get_expiration(&exp_time);
340 if (fosa_abs_time_smaller(exp_time, req_time))
341 ret = FRSH_ERR_CONTRACT_REJECTED;
349 int frsh_contract_negotiate
350 (const frsh_contract_t *contract,
351 frsh_vres_id_t *vres)
355 fres_contract_ptr_seq contracts;
356 fres_contract_ptr contracts_buf[1];
357 fres_contract_id_seq *ids;
358 fres_block_resource *r;
360 if (!contract || !*contract || !vres) {
361 ret = FRSH_ERR_BAD_ARGUMENT;
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);
374 /* Activate allocator */
375 r = fres_contract_get_resource(*contract);
377 fra_activate(r->resource_type,
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,
388 if (forb_exception_occurred(&env)) {
389 ret = FRES_ERR_FORB_EXCEPTION;
394 assert(ids->_length == 1);
395 *vres = fra_get_vres(&ids->_buffer[0]);
397 if (CORBA_sequence_get_release(ids))
398 CORBA_free(ids->_buffer);
405 int frsh_contract_cancel (const frsh_vres_id_t vres)
409 struct fres_contract *empty_contract;
410 fres_contract_ptr_seq contracts;
411 fres_contract_id_seq *ids;
414 ret = FRSH_ERR_BAD_ARGUMENT;
418 empty_contract = fres_contract_new();
419 empty_contract->id = vres->id;
421 contracts._buffer = &empty_contract;
422 contracts._length = contracts._maximum = 1;
423 ret = fres_contract_broker_negotiate_contracts(frsh_forb_global.fcb,
426 if (forb_exception_occurred(&env)) {
427 ret = FRES_ERR_FORB_EXCEPTION;
431 /* The returned ID is the same as of vres */
432 if (CORBA_sequence_get_release(ids))
433 CORBA_free(ids->_buffer);
439 int frsh_contract_renegotiate_sync
440 (const frsh_contract_t *new_contract,
441 frsh_vres_id_t vres_id)
444 struct fres_contract *contract;
446 fres_contract_ptr contracts_buf[1];
447 fres_contract_ptr_seq contracts;
448 fres_contract_id_seq *ids;
450 if (!new_contract || !*new_contract || !vres_id) {
451 ret = FRSH_ERR_BAD_ARGUMENT;
455 ret = __contract_check_min_expiration(new_contract);
458 contract = fres_contract_duplicate(*new_contract);
464 /* Assign the ID, so that FCB recognises that this is
466 contract->id = vres_id->id;
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,
475 if (forb_exception_occurred(&env)) {
476 ret = FRES_ERR_FORB_EXCEPTION;
480 if (CORBA_sequence_get_release(ids))
481 CORBA_free(ids->_buffer);
484 fres_contract_destroy(contract);
489 int frsh_contract_renegotiate_async
490 (const frsh_contract_t *new_contract,
492 frsh_signal_t signal_to_notify,
493 frsh_signal_info_t signal_info)
495 return FRSH_ERR_NOT_IMPLEMENTED;
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)
505 return FRSH_ERR_NOT_IMPLEMENTED;
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)
517 return FRSH_ERR_NOT_IMPLEMENTED;