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 "fra_generic.h"
62 UL_LOG_CUST(ulogd_fra);
63 ul_log_domain_t ulogd_fra = {UL_LOGL_MSG, "fra"};
66 * Global "registry" of all virtual resources in one application.
68 struct fres_vreses fres_vreses;
70 GAVL_CUST_NODE_INT_IMP(fres_vreses_nolock /* cust_prefix */,
71 struct fres_vreses /* cust_root_t */,
72 struct fres_vres /* cust_item_t */,
73 fres_contract_id_t /* cust_key_t */,
74 vreses /* cust_root_node */,
75 node /* cust_item_node */,
76 id /* cust_item_key */,
77 fres_contract_id_cmp /* cust_cmp_fnc */);
81 * * Global "registry" of all bound threads in one application.
83 struct fres_threads_vres fres_threads_vres;
85 GAVL_CUST_NODE_INT_IMP(fres_threads_vres_nolock /* cust_prefix */,
86 struct fres_threads_vres /* cust_root_t */,
87 struct fres_thread_vres /* cust_item_t */,
88 fres_thread_vres_key_t /* cust_key_t */,
89 threads /* cust_root_node */,
90 node /* cust_item_node */,
91 thread_vres /* cust_item_key */,
92 fres_thread_vres_cmp /* cust_cmp_fnc */);
95 * Inserts vres to the global vres "registry".
99 * @return Positive value on success, -1 on error.
102 fres_vreses_insert(struct fres_vres *vres)
105 fosa_mutex_lock(&fres_vreses.mutex);
106 ret = fres_vreses_nolock_insert(&fres_vreses, vres);
107 fosa_mutex_unlock(&fres_vreses.mutex);
112 fres_vreses_delete(struct fres_vres *vres)
115 fosa_mutex_lock(&fres_vreses.mutex);
116 ret = fres_vreses_nolock_delete(&fres_vreses, vres);
117 fosa_mutex_unlock(&fres_vreses.mutex);
121 static struct fres_vres *
122 fres_vreses_find(fres_contract_id_t *id)
124 struct fres_vres *ret;
125 fosa_mutex_lock(&fres_vreses.mutex);
126 ret = fres_vreses_nolock_find(&fres_vreses, id);
127 fosa_mutex_unlock(&fres_vreses.mutex);
132 fres_vreses_find_label(fres_block_label *label, fres_block_resource *res)
134 struct fres_vres *item;
136 gavl_cust_for_each(fres_vreses_nolock, &fres_vreses, item) {
137 struct fres_contract *c = item->perceived;
138 fres_block_label *l = fres_contract_get_label(c);
139 fres_block_resource *r = fres_contract_get_resource(c);
141 if (!strncmp(l->label, label->label, strlen(label->label)) &&
142 res->resource_type == r->resource_type &&
143 res->resource_id == r->resource_id)
151 #define save_errno(cmd) do { int _e = errno; cmd; errno = _e; } while(0)
153 CORBA_long change_vreses(fres_resource_allocator obj,
154 const fres_contract_ptr_seq* contracts,
155 CORBA_Environment *ev)
158 unsigned len = contracts->_length;
160 struct fres_allocator *alloc = forb_instance_data(obj);
161 struct fres_vres **vreses;
163 /* Prepare the vres structures */
164 vreses = malloc(len*sizeof(vreses[0]));
170 for (i=0; i<len; i++) {
171 struct fres_contract *contract;
172 struct fres_vres *vres;
173 contract = fres_contract_duplicate(contracts->_buffer[i]);
176 goto err_free_vreses;
178 vres = fres_vreses_find(&contract->id);
180 vres = fres_vres_new(&contract->id);
183 goto err_free_vreses;
185 ret = fres_vreses_insert(vres);
186 assert(ret > 0); /* Nobody else inserted the same vres. */
188 vres->new = contract;
189 vres->allocator = alloc;
193 /* Apply the changes */
194 if (alloc->apply_vres_changes) {
196 ret = alloc->apply_vres_changes(vreses, len, alloc->priv);
198 ul_logerr("apply_vres_changes failed %d\n", ret);
199 goto err_free_vreses;
202 /* Simple interface */
203 for (i=0; i<len; i++) {
204 struct fres_vres *vres = vreses[i];
205 if (fres_contract_get_num_blocks(vres->new) == 0) {
206 /* VRES cancleation */
207 ret = alloc->cancel_vres(vres, alloc->priv);
209 fres_vreses_delete(vres);
210 fres_vres_destroy(vres);
212 } else if (vres->allocated) {
214 struct fres_contract *last_perceived = vres->perceived;
215 ret = alloc->change_vres(vreses[i], alloc->priv);
216 if (last_perceived == vres->perceived) {
217 ul_logerr("change_vres callback did not change the perceived vres!\n");
218 vres->perceived = vres->new;
222 ret = alloc->create_vres(vreses[i], alloc->priv);
223 vres->perceived = vres->new;
226 ul_logerr("VRES apply error %d\n", ret);
227 goto err_free_vreses;
232 /* Update the vres structures (move new to allocated) */
233 for (i=0; i<len; i++) {
234 struct fres_vres *vres = vreses[i];
235 struct fres_contract *tmp;
238 tmp = vres->allocated;
239 vres->allocated = vres->new;
240 if (tmp) fres_contract_destroy(tmp);
252 static const struct forb_fres_resource_allocator_impl fra_impl = {
253 .change_vreses = change_vreses,
258 * Creates allocator object and registeres it with the given executor.
264 * @return Object reference on success or NULL on error.
266 fres_resource_allocator fra_new(forb_orb orb,
267 forb_executor_t *executor,
268 struct fres_allocator *allocator)
271 fres_resource_allocator fra;
273 fra = forb_fres_resource_allocator_new(orb, &fra_impl, allocator);
275 save_errno(ul_logerr("forb_fres_resource_manager_new error"));
279 /* Prepare executor before we register the resource allocator
280 * with contract broker */
281 ret = forb_executor_register_object(executor, fra);
282 if (ret) goto err_release;
286 save_errno(forb_object_release(fra));
292 * Returns pointer to VRes, which corresponds to the contract with the
297 * @return Pointer to VRes, or NULL in the VRes doesn't exist.
299 fres_vres_t *fra_get_vres(fres_contract_id_t *id)
301 return fres_vreses_find(id);
305 int fres_threads_vres_insert(struct fres_thread_vres *tv)
309 fosa_mutex_lock(&fres_threads_vres.mutex);
310 ret = fres_threads_vres_nolock_insert(&fres_threads_vres, tv);
311 fosa_mutex_unlock(&fres_threads_vres.mutex);
317 int fres_threads_vres_delete(struct fres_thread_vres *tv)
321 fosa_mutex_lock(&fres_threads_vres.mutex);
322 ret = fres_threads_vres_nolock_delete(&fres_threads_vres, tv);
323 fosa_mutex_unlock(&fres_threads_vres.mutex);
329 struct fres_thread_vres *fres_threads_vres_find(const fres_thread_vres_key_t *key)
331 struct fres_thread_vres *ret;
333 fosa_mutex_lock(&fres_threads_vres.mutex);
334 ret = fres_threads_vres_nolock_find(&fres_threads_vres, key);
335 fosa_mutex_unlock(&fres_threads_vres.mutex);
341 * Creates binding from a thread to VRES of specified type;
342 * if binding already exists, it fails... The old one should be
345 * @param id Thread ID bounded to @a vres of type @vres_type.
348 * @return Positive number when a new binding was inserted, zero when
349 * binding was changed and -1 on error.
351 int fra_insert_thread_vres(const fosa_thread_id_t *id,
355 fres_thread_vres_key_t key;
356 struct fres_thread_vres *tv;
359 key.vres_type = vres_type;
361 tv = fres_threads_vres_find(&key);
364 tv = fres_thread_vres_new(id, vres_type, vres);
367 return !fres_threads_vres_insert(tv);
371 * Deletes thread to VRES binding.
373 * @param id Thread ID to unbind.
375 * @return Zero on success, -1 on when the thread was not bound.
377 int fra_delete_thread_vres(const fosa_thread_id_t *id, int vres_type)
379 struct fres_thread_vres *tv;
380 fres_thread_vres_key_t key;
384 key.vres_type = vres_type;
386 fosa_mutex_lock(&fres_threads_vres.mutex);
387 tv = fres_threads_vres_nolock_find(&fres_threads_vres, &key);
393 ret = fres_threads_vres_nolock_delete(&fres_threads_vres, tv);
394 fosa_mutex_unlock(&fres_threads_vres.mutex);
397 ret = !fres_threads_vres_delete(tv);
404 * Returns VRES bounded to a thread.
406 * @param id Thread ID
408 * @return VRES on NULL in the thread is not bound.
410 * @todo Is this function needed if we have
411 * fra_get_vres_thread_vres()?
413 fres_thread_vres_t *fra_get_thread_vres
414 (const fosa_thread_id_t *id,
417 fres_thread_vres_key_t key;
420 key.vres_type = vres_type;
422 return fres_threads_vres_find(&key);
426 * Returns VRES bounded to a thread.
428 * @param id Thread ID
430 * @return VRES on NULL in the thread is not bound.
432 fres_vres_t *fra_get_vres_thread_vres
433 (const fosa_thread_id_t *id,
436 fres_thread_vres_key_t key;
437 fres_thread_vres_t *tv;
440 key.vres_type = vres_type;
442 tv = fres_threads_vres_find(&key);
443 if (!tv) return NULL;