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)
255 fres_block_timing_reqs *t;
257 if (!contract || !*contract)
258 return FRSH_ERR_BAD_ARGUMENT;
260 if ((d_equals_t && deadline != FRSH_NULL_DEADLINE) ||
261 (!d_equals_t && (deadline == FRSH_NULL_DEADLINE)))
262 return FRSH_ERR_BAD_ARGUMENT;
264 t = malloc(sizeof(*t));
265 if (!t) return ENOMEM;
267 t->d_equals_t = d_equals_t;
270 t->deadline = *deadline;
273 return FRSH_ERR_BAD_ARGUMENT;
277 fres_contract_del_timing_reqs(*contract);
278 ret = fres_contract_add_timing_reqs(*contract, t);
286 int frsh_contract_get_timing_reqs
287 (const frsh_contract_t *contract,
289 frsh_rel_time_t *deadline)
291 fres_block_timing_reqs *t;
293 if (!contract || !*contract)
294 return FRSH_ERR_BAD_ARGUMENT;
296 t = fres_contract_get_timing_reqs(*contract);
299 *d_equals_t = t->d_equals_t;
302 *deadline = t->deadline;
308 int __contract_check_min_expiration(const frsh_contract_t *contract)
310 fres_block_power_management *p;
313 p = fres_contract_get_power_management(*contract);
314 if (p && !fosa_rel_time_is_null(p->min_expiration)) {
315 frsh_abs_time_t req_time, exp_time;
317 fosa_clock_get_time(FOSA_CLOCK_REALTIME, &req_time);
318 req_time = fosa_abs_time_incr(req_time, p->min_expiration);
320 ret = frsh_battery_get_expiration(&exp_time);
323 if (fosa_abs_time_smaller(exp_time, req_time))
324 ret = FRSH_ERR_CONTRACT_REJECTED;
332 int frsh_contract_negotiate
333 (const frsh_contract_t *contract,
334 frsh_vres_id_t *vres)
338 fres_contract_ptr_seq contracts;
339 fres_contract_ptr contracts_buf[1];
340 fres_contract_id_seq *ids;
341 fres_block_resource *r;
343 if (!contract || !*contract || !vres) {
344 ret = FRSH_ERR_BAD_ARGUMENT;
348 /* TODO: Battery time check should be moved to
349 * FCB. Implementation of FRSH API is meant only as a thin
350 * wrapper of FRES framework and the FRES framework could
351 * theoretically be used without FRSH API. Moreover, if there
352 * is some logging mechanism in FCB, this contract rejection
353 * will not be logged. */
354 ret = __contract_check_min_expiration(contract);
357 /* Activate allocator */
358 r = fres_contract_get_resource(*contract);
360 ret = fra_activate(r->resource_type,
365 /* Negotiate contract */
366 contracts_buf[0] = *contract;
367 contracts._buffer = contracts_buf;
368 contracts._length = contracts._maximum = 1;
369 ret = fres_contract_broker_negotiate_contracts(frsh_forb_global.fcb,
372 if (forb_exception_occurred(&env)) {
373 ret = fres_forbex2err(&env);
378 assert(ids->_length == 1);
379 *vres = fra_get_vres(&ids->_buffer[0]);
380 assert(*vres != NULL);
382 if (CORBA_sequence_get_release(ids))
383 CORBA_free(ids->_buffer);
390 int frsh_contract_cancel (const frsh_vres_id_t vres)
394 struct fres_contract *empty_contract;
395 fres_contract_ptr_seq contracts;
396 fres_contract_id_seq *ids;
399 ret = FRSH_ERR_BAD_ARGUMENT;
403 empty_contract = fres_contract_new();
404 empty_contract->id = vres->id;
406 contracts._buffer = &empty_contract;
407 contracts._length = contracts._maximum = 1;
408 ret = fres_contract_broker_negotiate_contracts(frsh_forb_global.fcb,
411 if (forb_exception_occurred(&env)) {
412 ret = fres_forbex2err(&env);
416 /* The returned ID is the same as of vres */
417 if (CORBA_sequence_get_release(ids))
418 CORBA_free(ids->_buffer);
424 int frsh_contract_renegotiate_sync
425 (const frsh_contract_t *new_contract,
426 frsh_vres_id_t vres_id)
429 struct fres_contract *contract;
431 fres_contract_ptr contracts_buf[1];
432 fres_contract_ptr_seq contracts;
433 fres_contract_id_seq *ids;
435 if (!new_contract || !*new_contract || !vres_id) {
436 ret = FRSH_ERR_BAD_ARGUMENT;
440 ret = __contract_check_min_expiration(new_contract);
443 contract = fres_contract_duplicate(*new_contract);
449 /* Assign the ID, so that FCB recognises that this is
451 contract->id = vres_id->id;
453 /* Renegotiate with FCB contract */
454 contracts_buf[0] = contract;
455 contracts._buffer = contracts_buf;
456 contracts._length = contracts._maximum = 1;
457 ret = fres_contract_broker_negotiate_contracts(frsh_forb_global.fcb,
460 if (forb_exception_occurred(&env)) {
461 ret = fres_forbex2err(&env);
465 if (CORBA_sequence_get_release(ids))
466 CORBA_free(ids->_buffer);
469 fres_contract_destroy(contract);
474 int frsh_contract_renegotiate_async
475 (const frsh_contract_t *new_contract,
477 frsh_signal_t signal_to_notify,
478 frsh_signal_info_t signal_info)
480 return FRSH_ERR_NOT_IMPLEMENTED;
483 int frsh_group_change_mode_sync
484 (const frsh_contracts_group_t *contracts_to_neg,
485 const frsh_contracts_group_t *contracts_to_reneg,
486 const frsh_vres_group_t *vres_to_reneg,
487 const frsh_vres_group_t *vres_to_cancel,
488 frsh_vres_group_t *new_vres)
490 return FRSH_ERR_NOT_IMPLEMENTED;
493 int frsh_group_change_mode_async
494 (const frsh_contracts_group_t *contracts_to_neg,
495 const frsh_contracts_group_t *contracts_to_reneg,
496 const frsh_vres_group_t *vres_to_reneg,
497 const frsh_vres_group_t *vres_to_cancel,
498 const frsh_signal_t signal,
499 const frsh_signal_info_t signal_info,
500 frsh_group_id_t *group)
502 return FRSH_ERR_NOT_IMPLEMENTED;