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,
96 frsh_contract_destroy(frsh_contract_t *contract)
99 fres_contract_destroy(*contract);
102 int frsh_contract_set_basic_params
103 (frsh_contract_t *contract,
104 const frsh_rel_time_t *budget_min,
105 const frsh_rel_time_t *period_max,
106 const frsh_workload_t workload,
107 const frsh_contract_type_t contract_type)
115 return FRSH_ERR_BAD_ARGUMENT;
118 if ((fosa_rel_time_is_null(*period_max) &&
119 !fosa_rel_time_is_null(*budget_min)) ||
120 (!fosa_rel_time_is_null(*period_max) &&
121 fosa_rel_time_is_null(*budget_min)) ||
122 fosa_rel_time_smaller(*period_max, *budget_min))
123 return FRSH_ERR_BAD_ARGUMENT;
125 if (workload != FRSH_WT_BOUNDED &&
126 workload != FRSH_WT_INDETERMINATE)
127 return FRSH_ERR_BAD_ARGUMENT;
129 if (contract_type != FRSH_CT_REGULAR &&
130 contract_type != FRSH_CT_BACKGROUND &&
131 contract_type != FRSH_CT_DUMMY)
132 return FRSH_ERR_BAD_ARGUMENT;
134 b = malloc(sizeof(*b));
135 if (!b) return ENOMEM;
137 b->budget = *budget_min;
138 b->period = *period_max;
139 b->workload = workload;
140 b->contract_type = contract_type;
142 fres_contract_del_basic(*contract);
143 ret = fres_contract_add_basic(*contract, b);
153 int frsh_contract_get_basic_params
154 (const frsh_contract_t *contract,
155 frsh_rel_time_t *budget_min,
156 frsh_rel_time_t *period_max,
157 frsh_workload_t *workload,
158 frsh_contract_type_t *contract_type)
162 if (!contract || !*contract)
163 return FRSH_ERR_BAD_ARGUMENT;
165 b = fres_contract_get_basic(*contract);
168 *workload = b->workload;
170 *budget_min = b->budget;
172 *period_max = b->period;
174 *contract_type = b->contract_type;
179 int frsh_contract_set_resource_and_label
180 (frsh_contract_t *contract,
181 const frsh_resource_type_t resource_type,
182 const frsh_resource_id_t resource_id,
183 const frsh_contract_label_t contract_label)
185 fres_block_label *label;
186 fres_block_resource *r;
189 if (!contract || !*contract) return FRSH_ERR_BAD_ARGUMENT;
191 r = malloc(sizeof(*r));
192 if (!r) return ENOMEM;
194 r->resource_type = resource_type;
195 r->resource_id = resource_id;
196 fres_contract_del_resource(*contract);
197 ret = fres_contract_add_resource(*contract, r);
205 if (contract_label) {
206 label = malloc(sizeof(*label));
207 if (!label) return ENOMEM;
208 strncpy(label->label, contract_label, sizeof(label->label));
209 label->label[sizeof(label->label)-1] = '\0';
210 fres_contract_del_label(*contract);
211 ret = fres_contract_add_label(*contract, label);
220 int frsh_contract_get_resource_and_label
221 (const frsh_contract_t *contract,
222 frsh_resource_type_t *resource_type,
223 frsh_resource_id_t *resource_id,
224 frsh_contract_label_t contract_label)
226 fres_block_resource *r;
227 fres_block_label *label;
229 if (!contract || !*contract)
230 return FRSH_ERR_BAD_ARGUMENT;
232 if (resource_type || resource_id) {
233 r = fres_contract_get_resource(*contract);
235 *resource_type = r->resource_type;
237 *resource_id = r->resource_id;
240 if (contract_label) {
241 label = fres_contract_get_label(*contract);
242 strncpy(contract_label, label->label, sizeof(label->label));
243 contract_label[sizeof(label->label)-1] = '\0';
249 int frsh_contract_set_timing_reqs
250 (frsh_contract_t *contract,
251 const bool d_equals_t,
252 const frsh_rel_time_t *deadline,
253 const frsh_signal_t budget_overrun_signal,
254 const frsh_signal_info_t budget_overrun_siginfo,
255 const frsh_signal_t deadline_miss_signal,
256 const frsh_signal_info_t deadline_miss_siginfo)
260 fres_block_timing_reqs *t;
262 if (!contract || !*contract)
263 return FRSH_ERR_BAD_ARGUMENT;
265 /* deadline and period must be coherent between each other */
266 b = fres_contract_get_basic(*contract);
268 if ((d_equals_t && deadline != FRSH_NULL_DEADLINE) ||
269 (!d_equals_t && (deadline == FRSH_NULL_DEADLINE)))
270 return FRSH_ERR_BAD_ARGUMENT;
272 /* signal delivery can only be requested for BUONDED workloads */
273 if (b->workload == FRSH_WT_INDETERMINATE &&
274 (deadline_miss_signal != FRSH_NULL_SIGNAL ||
275 budget_overrun_signal != FRSH_NULL_SIGNAL))
276 return FRSH_ERR_BAD_ARGUMENT;
278 t = malloc(sizeof(*t));
279 if (!t) return ENOMEM;
281 t->d_equals_t = d_equals_t;
284 t->deadline = *deadline;
287 return FRSH_ERR_BAD_ARGUMENT;
291 /* Signals are currently ignored by this implementation as
292 * they are better implemented in frsh_thread_bind() */
293 /*t->budget_overrun_signal = budget_overrun_signal;
294 t->budget_overrun_siginfo = budget_overrun_siginfo;
295 t->deadline_miss_signal = deadline_miss_signal;
296 t->deadline_miss_siginfo = deadline_miss_siginfo;*/
297 fres_contract_del_timing_reqs(*contract);
298 ret = fres_contract_add_timing_reqs(*contract, t);
306 int frsh_contract_get_timing_reqs
307 (const frsh_contract_t *contract,
309 frsh_rel_time_t *deadline,
310 frsh_signal_t *budget_overrun_signal,
311 frsh_signal_info_t *budget_overrun_siginfo,
312 frsh_signal_t *deadline_miss_signal,
313 frsh_signal_info_t *deadline_miss_siginfo)
315 fres_block_timing_reqs *t;
317 if (!contract || !*contract)
318 return FRSH_ERR_BAD_ARGUMENT;
320 t = fres_contract_get_timing_reqs(*contract);
323 *d_equals_t = t->d_equals_t;
326 *deadline = t->deadline;
332 int __contract_check_min_expiration(const frsh_contract_t *contract)
334 fres_block_power_management *p;
337 p = fres_contract_get_power_management(*contract);
338 if (p && !fosa_rel_time_is_null(p->min_expiration)) {
339 frsh_abs_time_t req_time, exp_time;
341 fosa_clock_get_time(FOSA_CLOCK_REALTIME, &req_time);
342 req_time = fosa_abs_time_incr(req_time, p->min_expiration);
344 ret = frsh_battery_get_expiration(&exp_time);
347 if (fosa_abs_time_smaller(exp_time, req_time))
348 ret = FRSH_ERR_CONTRACT_REJECTED;
356 int frsh_contract_negotiate
357 (const frsh_contract_t *contract,
358 frsh_vres_id_t *vres)
362 fres_contract_ptr_seq contracts;
363 fres_contract_ptr contracts_buf[1];
364 fres_contract_id_seq *ids;
365 fres_block_resource *r;
367 if (!contract || !*contract || !vres) {
368 ret = FRSH_ERR_BAD_ARGUMENT;
372 /* TODO: Battery time check should be moved to
373 * FCB. Implementation of FRSH API is meant only as a thin
374 * wrapper of FRES framework and the FRES framework could
375 * theoretically be used without FRSH API. Moreover, if there
376 * is some logging mechanism in FCB, this contract rejection
377 * will not be logged. */
378 ret = __contract_check_min_expiration(contract);
381 /* Activate allocator */
382 r = fres_contract_get_resource(*contract);
384 ret = fra_activate(r->resource_type,
389 /* Negotiate contract */
390 contracts_buf[0] = *contract;
391 contracts._buffer = contracts_buf;
392 contracts._length = contracts._maximum = 1;
393 ret = fres_contract_broker_negotiate_contracts(frsh_forb_global.fcb,
396 if (forb_exception_occurred(&env)) {
397 ret = fres_forbex2err(&env);
402 assert(ids->_length == 1);
403 *vres = fra_get_vres(&ids->_buffer[0]);
405 if (CORBA_sequence_get_release(ids))
406 CORBA_free(ids->_buffer);
413 int frsh_contract_cancel (const frsh_vres_id_t vres)
417 struct fres_contract *empty_contract;
418 fres_contract_ptr_seq contracts;
419 fres_contract_id_seq *ids;
422 ret = FRSH_ERR_BAD_ARGUMENT;
426 empty_contract = fres_contract_new();
427 empty_contract->id = vres->id;
429 contracts._buffer = &empty_contract;
430 contracts._length = contracts._maximum = 1;
431 ret = fres_contract_broker_negotiate_contracts(frsh_forb_global.fcb,
434 if (forb_exception_occurred(&env)) {
435 ret = fres_forbex2err(&env);
439 /* The returned ID is the same as of vres */
440 if (CORBA_sequence_get_release(ids))
441 CORBA_free(ids->_buffer);
447 int frsh_contract_renegotiate_sync
448 (const frsh_contract_t *new_contract,
449 frsh_vres_id_t vres_id)
452 struct fres_contract *contract;
454 fres_contract_ptr contracts_buf[1];
455 fres_contract_ptr_seq contracts;
456 fres_contract_id_seq *ids;
458 if (!new_contract || !*new_contract || !vres_id) {
459 ret = FRSH_ERR_BAD_ARGUMENT;
463 ret = __contract_check_min_expiration(new_contract);
466 contract = fres_contract_duplicate(*new_contract);
472 /* Assign the ID, so that FCB recognises that this is
474 contract->id = vres_id->id;
476 /* Renegotiate with FCB contract */
477 contracts_buf[0] = contract;
478 contracts._buffer = contracts_buf;
479 contracts._length = contracts._maximum = 1;
480 ret = fres_contract_broker_negotiate_contracts(frsh_forb_global.fcb,
483 if (forb_exception_occurred(&env)) {
484 ret = fres_forbex2err(&env);
488 if (CORBA_sequence_get_release(ids))
489 CORBA_free(ids->_buffer);
492 fres_contract_destroy(contract);
497 int frsh_contract_renegotiate_async
498 (const frsh_contract_t *new_contract,
500 frsh_signal_t signal_to_notify,
501 frsh_signal_info_t signal_info)
503 return FRSH_ERR_NOT_IMPLEMENTED;
506 int frsh_group_change_mode_sync
507 (const frsh_contracts_group_t *contracts_to_neg,
508 const frsh_contracts_group_t *contracts_to_reneg,
509 const frsh_vres_group_t *vres_to_reneg,
510 const frsh_vres_group_t *vres_to_cancel,
511 frsh_vres_group_t *new_vres)
513 return FRSH_ERR_NOT_IMPLEMENTED;
516 int frsh_group_change_mode_async
517 (const frsh_contracts_group_t *contracts_to_neg,
518 const frsh_contracts_group_t *contracts_to_reneg,
519 const frsh_vres_group_t *vres_to_reneg,
520 const frsh_vres_group_t *vres_to_cancel,
521 const frsh_signal_t signal,
522 const frsh_signal_info_t signal_info,
523 frsh_group_id_t *group)
525 return FRSH_ERR_NOT_IMPLEMENTED;