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 /* FIXME: Do not call this hook for DUMMY contracts */
199 ret = alloc->apply_vres_changes(vreses, len, alloc->priv);
201 ul_logerr("apply_vres_changes failed %d\n", ret);
202 goto err_free_vreses;
205 /* Simple interface */
206 for (i=0; i<len; i++) {
207 struct fres_vres *vres = vreses[i];
208 if (fres_contract_get_type(&vres->new) == FRSH_CT_DUMMY)
210 if (fres_contract_get_num_blocks(vres->new) == 0) {
211 /* VRES cancleation */
212 ret = alloc->cancel_vres(vres, alloc->priv);
214 fres_vreses_delete(vres);
215 fres_vres_destroy(vres);
217 } else if (vres->allocated) {
219 struct fres_contract *last_perceived = vres->perceived;
220 ret = alloc->change_vres(vreses[i], alloc->priv);
221 if (last_perceived == vres->perceived) {
222 ul_logerr("change_vres callback did not change the perceived vres!\n");
223 vres->perceived = vres->new;
227 ret = alloc->create_vres(vreses[i], alloc->priv);
228 vres->perceived = vres->new;
231 ul_logerr("VRES apply error %d\n", ret);
232 goto err_free_vreses;
237 /* Update the vres structures (move new to allocated) */
238 for (i=0; i<len; i++) {
239 struct fres_vres *vres = vreses[i];
240 struct fres_contract *tmp;
243 tmp = vres->allocated;
244 vres->allocated = vres->new;
245 if (tmp) fres_contract_destroy(tmp);
257 static const struct forb_fres_resource_allocator_impl fra_impl = {
258 .change_vreses = change_vreses,
263 * Creates allocator object and registeres it with the given executor.
269 * @return Object reference on success or NULL on error.
271 fres_resource_allocator fra_new(forb_orb orb,
272 forb_executor_t *executor,
273 struct fres_allocator *allocator)
276 fres_resource_allocator fra;
278 fra = forb_fres_resource_allocator_new(orb, &fra_impl, allocator);
280 save_errno(ul_logerr("forb_fres_resource_manager_new error"));
284 /* Prepare executor before we register the resource allocator
285 * with contract broker */
286 ret = forb_executor_register_object(executor, fra);
287 if (ret) goto err_release;
291 save_errno(forb_object_release(fra));
297 * Returns pointer to VRes, which corresponds to the contract with the
302 * @return Pointer to VRes, or NULL in the VRes doesn't exist.
304 fres_vres_t *fra_get_vres(fres_contract_id_t *id)
306 return fres_vreses_find(id);
310 int fres_threads_vres_insert(struct fres_thread_vres *tv)
314 fosa_mutex_lock(&fres_threads_vres.mutex);
315 ret = fres_threads_vres_nolock_insert(&fres_threads_vres, tv);
316 fosa_mutex_unlock(&fres_threads_vres.mutex);
322 int fres_threads_vres_delete(struct fres_thread_vres *tv)
326 fosa_mutex_lock(&fres_threads_vres.mutex);
327 ret = fres_threads_vres_nolock_delete(&fres_threads_vres, tv);
328 fosa_mutex_unlock(&fres_threads_vres.mutex);
334 struct fres_thread_vres *fres_threads_vres_find(const fres_thread_vres_key_t *key)
336 struct fres_thread_vres *ret;
338 fosa_mutex_lock(&fres_threads_vres.mutex);
339 ret = fres_threads_vres_nolock_find(&fres_threads_vres, key);
340 fosa_mutex_unlock(&fres_threads_vres.mutex);
346 * Creates binding from a thread to VRES of specified type;
347 * if binding already exists, it fails... The old one should be
350 * @param id Thread ID bounded to @a vres of type @vres_type.
353 * @return Positive number when a new binding was inserted, zero when
354 * binding was changed and -1 on error.
356 int fra_insert_thread_vres(const fosa_thread_id_t *id,
360 fres_thread_vres_key_t key;
361 struct fres_thread_vres *tv;
364 key.vres_type = vres_type;
366 tv = fres_threads_vres_find(&key);
369 tv = fres_thread_vres_new(id, vres_type, vres);
372 return !fres_threads_vres_insert(tv);
376 * Deletes thread to VRES binding.
378 * @param id Thread ID to unbind.
380 * @return Zero on success, -1 on when the thread was not bound.
382 int fra_delete_thread_vres(const fosa_thread_id_t *id, int vres_type)
384 struct fres_thread_vres *tv;
385 fres_thread_vres_key_t key;
389 key.vres_type = vres_type;
391 fosa_mutex_lock(&fres_threads_vres.mutex);
392 tv = fres_threads_vres_nolock_find(&fres_threads_vres, &key);
398 ret = fres_threads_vres_nolock_delete(&fres_threads_vres, tv);
399 fosa_mutex_unlock(&fres_threads_vres.mutex);
402 ret = !fres_threads_vres_delete(tv);
409 * Returns VRES bounded to a thread.
411 * @param id Thread ID
413 * @return VRES on NULL in the thread is not bound.
415 * @todo Is this function needed if we have
416 * fra_get_vres_thread_vres()?
418 fres_thread_vres_t *fra_get_thread_vres
419 (const fosa_thread_id_t *id,
422 fres_thread_vres_key_t key;
425 key.vres_type = vres_type;
427 return fres_threads_vres_find(&key);
431 * Returns VRES bounded to a thread.
433 * @param id Thread ID
435 * @return VRES on NULL in the thread is not bound.
437 fres_vres_t *fra_get_vres_thread_vres
438 (const fosa_thread_id_t *id,
441 fres_thread_vres_key_t key;
442 fres_thread_vres_t *tv;
445 key.vres_type = vres_type;
447 tv = fres_threads_vres_find(&key);
448 if (!tv) return NULL;