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 /**************************************************************************/
49 * @author Michal Sojka <sojkam1@fel.cvut.cz>
50 * @date Thu Oct 23 15:26:19 2008
52 * @brief FORB interface of FRES Resource Allocator
60 #include <ul_logreg.h>
61 #include "fra_generic.h"
63 UL_LOG_CUST(ulogd_fra);
64 ul_log_domain_t ulogd_fra = {UL_LOGL_MSG, "fra"};
65 UL_LOGREG_SINGLE_DOMAIN_INIT_FUNCTION(fra_logreg_domains, ulogd_fra);
68 * Global "registry" of all virtual resources in one application.
70 struct fres_vreses fres_vreses;
72 GAVL_CUST_NODE_INT_IMP(fres_vreses_nolock /* cust_prefix */,
73 struct fres_vreses /* cust_root_t */,
74 struct fres_vres /* cust_item_t */,
75 fres_contract_id_t /* cust_key_t */,
76 vreses /* cust_root_node */,
77 node /* cust_item_node */,
78 id /* cust_item_key */,
79 fres_contract_id_cmp /* cust_cmp_fnc */);
83 * * Global "registry" of all bound threads in one application.
85 struct fres_threads_vres fres_threads_vres;
87 GAVL_CUST_NODE_INT_IMP(fres_threads_vres_nolock /* cust_prefix */,
88 struct fres_threads_vres /* cust_root_t */,
89 struct fres_thread_vres /* cust_item_t */,
90 fres_thread_vres_key_t /* cust_key_t */,
91 threads /* cust_root_node */,
92 node /* cust_item_node */,
93 thread_vres /* cust_item_key */,
94 fres_thread_vres_cmp /* cust_cmp_fnc */);
97 * Inserts vres to the global vres "registry".
101 * @return Positive value on success, -1 on error.
104 fres_vreses_insert(struct fres_vres *vres)
107 fosa_mutex_lock(&fres_vreses.mutex);
108 ret = fres_vreses_nolock_insert(&fres_vreses, vres);
109 fosa_mutex_unlock(&fres_vreses.mutex);
114 fres_vreses_delete(struct fres_vres *vres)
117 fosa_mutex_lock(&fres_vreses.mutex);
118 ret = fres_vreses_nolock_delete(&fres_vreses, vres);
119 fosa_mutex_unlock(&fres_vreses.mutex);
123 static struct fres_vres *
124 fres_vreses_find(fres_contract_id_t *id)
126 struct fres_vres *ret;
127 fosa_mutex_lock(&fres_vreses.mutex);
128 ret = fres_vreses_nolock_find(&fres_vreses, id);
129 fosa_mutex_unlock(&fres_vreses.mutex);
134 fres_vreses_find_label(fres_block_label *label, fres_block_resource *res)
136 struct fres_vres *item;
138 gavl_cust_for_each(fres_vreses_nolock, &fres_vreses, item) {
139 struct fres_contract *c = item->perceived;
140 fres_block_label *l = fres_contract_get_label(c);
141 fres_block_resource *r = fres_contract_get_resource(c);
143 if (!strncmp(l->label, label->label, strlen(label->label)) &&
144 res->resource_type == r->resource_type &&
145 res->resource_id == r->resource_id)
153 #define save_errno(cmd) do { int _e = errno; cmd; errno = _e; } while(0)
155 CORBA_long change_vreses(fres_resource_allocator obj,
156 const fres_contract_ptr_seq* contracts,
157 CORBA_Environment *ev)
160 unsigned len = contracts->_length;
162 struct fres_allocator *alloc = forb_instance_data(obj);
163 struct fres_vres **vreses;
165 /* Prepare the vres structures */
166 vreses = malloc(len*sizeof(vreses[0]));
172 for (i=0; i<len; i++) {
173 struct fres_contract *contract;
174 struct fres_vres *vres;
175 contract = fres_contract_duplicate(contracts->_buffer[i]);
178 goto err_free_vreses;
180 vres = fres_vreses_find(&contract->id);
182 vres = fres_vres_new(&contract->id);
185 goto err_free_vreses;
187 ret = fres_vreses_insert(vres);
188 assert(ret > 0); /* Nobody else inserted the same vres. */
190 vres->new = contract;
191 vres->allocator = alloc;
195 /* Apply the changes */
196 if (alloc->apply_vres_changes) {
198 ret = alloc->apply_vres_changes(vreses, len, alloc->priv);
200 ul_logerr("apply_vres_changes failed %d\n", ret);
201 goto err_free_vreses;
204 /* Simple interface */
205 for (i=0; i<len; i++) {
206 struct fres_vres *vres = vreses[i];
207 if (fres_contract_get_num_blocks(vres->new) == 0) {
208 /* VRES cancleation */
209 ret = alloc->cancel_vres(vres, alloc->priv);
211 fres_vreses_delete(vres);
212 fres_vres_destroy(vres);
214 } else if (vres->allocated) {
216 struct fres_contract *last_perceived = vres->perceived;
217 ret = alloc->change_vres(vreses[i], alloc->priv);
218 if (last_perceived == vres->perceived) {
219 ul_logerr("change_vres callback did not change the perceived vres!\n");
220 vres->perceived = vres->new;
224 ret = alloc->create_vres(vreses[i], alloc->priv);
225 vres->perceived = vres->new;
228 ul_logerr("VRES apply error %d\n", ret);
229 goto err_free_vreses;
234 /* Update the vres structures (move new to allocated) */
235 for (i=0; i<len; i++) {
236 struct fres_vres *vres = vreses[i];
237 struct fres_contract *tmp;
240 tmp = vres->allocated;
241 vres->allocated = vres->new;
242 if (tmp) fres_contract_destroy(tmp);
254 static const struct forb_fres_resource_allocator_impl fra_impl = {
255 .change_vreses = change_vreses,
260 * Creates allocator object and registeres it with the given executor.
266 * @return Object reference on success or NULL on error.
268 fres_resource_allocator fra_new(forb_orb orb,
269 forb_executor_t *executor,
270 struct fres_allocator *allocator)
273 fres_resource_allocator fra;
275 fra = forb_fres_resource_allocator_new(orb, &fra_impl, allocator);
277 save_errno(ul_logerr("forb_fres_resource_manager_new error"));
281 /* Prepare executor before we register the resource allocator
282 * with contract broker */
283 ret = forb_executor_register_object(executor, fra);
284 if (ret) goto err_release;
288 save_errno(forb_object_release(fra));
294 * Returns pointer to VRes, which corresponds to the contract with the
299 * @return Pointer to VRes, or NULL in the VRes doesn't exist.
301 fres_vres_t *fra_get_vres(fres_contract_id_t *id)
303 return fres_vreses_find(id);
307 int fres_threads_vres_insert(struct fres_thread_vres *tv)
311 fosa_mutex_lock(&fres_threads_vres.mutex);
312 ret = fres_threads_vres_nolock_insert(&fres_threads_vres, tv);
313 fosa_mutex_unlock(&fres_threads_vres.mutex);
319 int fres_threads_vres_delete(struct fres_thread_vres *tv)
323 fosa_mutex_lock(&fres_threads_vres.mutex);
324 ret = fres_threads_vres_nolock_delete(&fres_threads_vres, tv);
325 fosa_mutex_unlock(&fres_threads_vres.mutex);
331 struct fres_thread_vres *fres_threads_vres_find(const fres_thread_vres_key_t *key)
333 struct fres_thread_vres *ret;
335 fosa_mutex_lock(&fres_threads_vres.mutex);
336 ret = fres_threads_vres_nolock_find(&fres_threads_vres, key);
337 fosa_mutex_unlock(&fres_threads_vres.mutex);
343 * Creates binding from a thread to VRES of specified type;
344 * if binding already exists, it fails... The old one should be
347 * @param id Thread ID bounded to @a vres of type @vres_type.
350 * @return Positive number when a new binding was inserted, zero when
351 * binding was changed and -1 on error.
353 int fra_insert_thread_vres(const fosa_thread_id_t *id,
357 fres_thread_vres_key_t key;
358 struct fres_thread_vres *tv;
361 key.vres_type = vres_type;
363 tv = fres_threads_vres_find(&key);
366 tv = fres_thread_vres_new(id, vres_type, vres);
369 return !fres_threads_vres_insert(tv);
373 * Deletes thread to VRES binding.
375 * @param id Thread ID to unbind.
377 * @return Zero on success, -1 on when the thread was not bound.
379 int fra_delete_thread_vres(const fosa_thread_id_t *id, int vres_type)
381 struct fres_thread_vres *tv;
382 fres_thread_vres_key_t key;
386 key.vres_type = vres_type;
388 fosa_mutex_lock(&fres_threads_vres.mutex);
389 tv = fres_threads_vres_nolock_find(&fres_threads_vres, &key);
395 ret = fres_threads_vres_nolock_delete(&fres_threads_vres, tv);
396 fosa_mutex_unlock(&fres_threads_vres.mutex);
399 ret = !fres_threads_vres_delete(tv);
406 * Returns VRES bounded to a thread.
408 * @param id Thread ID
410 * @return VRES on NULL in the thread is not bound.
412 * @todo Is this function needed if we have
413 * fra_get_vres_thread_vres()?
415 fres_thread_vres_t *fra_get_thread_vres
416 (const fosa_thread_id_t *id,
419 fres_thread_vres_key_t key;
422 key.vres_type = vres_type;
424 return fres_threads_vres_find(&key);
428 * Returns VRES bounded to a thread.
430 * @param id Thread ID
432 * @return VRES on NULL in the thread is not bound.
434 fres_vres_t *fra_get_vres_thread_vres
435 (const fosa_thread_id_t *id,
438 fres_thread_vres_key_t key;
439 fres_thread_vres_t *tv;
442 key.vres_type = vres_type;
444 tv = fres_threads_vres_find(&key);
445 if (!tv) return NULL;