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 fosa_thread_id_t /* cust_key_t */,
89 threads /* cust_root_node */,
90 node /* cust_item_node */,
91 id /* cust_item_key */,
92 fres_thread_vres_cmp /* cust_cmp_fnc */);
96 * Inserts vres to the global vres "registry".
100 * @return Positive value on success, -1 on error.
103 fres_vreses_insert(struct fres_vres *vres)
106 fosa_mutex_lock(&fres_vreses.mutex);
107 ret = fres_vreses_nolock_insert(&fres_vreses, vres);
108 fosa_mutex_unlock(&fres_vreses.mutex);
113 fres_vreses_delete(struct fres_vres *vres)
116 fosa_mutex_lock(&fres_vreses.mutex);
117 ret = fres_vreses_nolock_delete(&fres_vreses, vres);
118 fosa_mutex_unlock(&fres_vreses.mutex);
122 static struct fres_vres *
123 fres_vreses_find(fres_contract_id_t *id)
125 struct fres_vres *ret;
126 fosa_mutex_lock(&fres_vreses.mutex);
127 ret = fres_vreses_nolock_find(&fres_vreses, id);
128 fosa_mutex_unlock(&fres_vreses.mutex);
133 #define save_errno(cmd) do { int _e = errno; cmd; errno = _e; } while(0)
135 CORBA_long change_vreses(fres_resource_allocator obj,
136 const fres_contract_ptr_seq* contracts,
137 CORBA_Environment *ev)
140 unsigned len = contracts->_length;
142 struct fres_allocator *alloc = forb_instance_data(obj);
143 struct fres_vres **vreses;
145 /* Prepare the vres structures */
146 vreses = malloc(len*sizeof(vreses[0]));
152 for (i=0; i<len; i++) {
153 struct fres_contract *contract;
154 struct fres_vres *vres;
155 contract = fres_contract_duplicate(contracts->_buffer[i]);
158 goto err_free_vreses;
160 vres = fres_vreses_find(&contract->id);
162 vres = fres_vres_new(&contract->id);
165 goto err_free_vreses;
167 ret = fres_vreses_insert(vres);
168 assert(ret > 0); /* Nobody else inserted the same vres. */
170 vres->new = contract;
171 vres->allocator = alloc;
175 /* Apply the changes */
176 if (alloc->apply_vres_changes) {
178 ret = alloc->apply_vres_changes(vreses, len, alloc->priv);
180 ul_logerr("apply_vres_changes failed %d\n", ret);
181 goto err_free_vreses;
184 /* Simple interface */
185 for (i=0; i<len; i++) {
186 struct fres_vres *vres = vreses[i];
187 if (fres_contract_get_num_blocks(vres->new) == 0) {
188 /* VRES cancleation */
189 ret = alloc->cancel_vres(vres, alloc->priv);
191 fres_vreses_delete(vres);
192 fres_vres_destroy(vres);
194 } else if (vres->allocated) {
196 struct fres_contract *last_perceived = vres->perceived;
197 ret = alloc->change_vres(vreses[i], alloc->priv);
198 if (last_perceived == vres->perceived) {
199 ul_logerr("change_vres callback did not change the perceived vres!");
200 vres->perceived = vres->new;
204 ret = alloc->create_vres(vreses[i], alloc->priv);
205 vres->perceived = vres->new;
208 ul_logerr("VRES apply error %d\n", ret);
209 goto err_free_vreses;
214 /* Update the vres structures (move new to allocated) */
215 for (i=0; i<len; i++) {
216 struct fres_vres *vres = vreses[i];
217 struct fres_contract *tmp;
220 tmp = vres->allocated;
221 vres->allocated = vres->new;
222 if (tmp) fres_contract_destroy(tmp);
234 static const struct forb_fres_resource_allocator_impl fra_impl = {
235 .change_vreses = change_vreses,
240 * Creates allocator object and registeres it with the given executor.
246 * @return Object reference on success or NULL on error.
248 fres_resource_allocator fra_new(forb_orb orb,
249 forb_executor_t *executor,
250 struct fres_allocator *allocator)
253 fres_resource_allocator fra;
255 fra = forb_fres_resource_allocator_new(orb, &fra_impl, allocator);
257 save_errno(ul_logerr("forb_fres_resource_manager_new error"));
261 /* Prepare executor before we register the resource allocator
262 * with contract broker */
263 ret = forb_executor_register_object(executor, fra);
264 if (ret) goto err_release;
268 save_errno(forb_object_release(fra));
274 * Returns pointer to VRes, which corresponds to the contract with the
279 * @return Pointer to VRes, or NULL in the VRes doesn't exist.
281 fres_vres_t *fra_get_vres(fres_contract_id_t *id)
283 return fres_vreses_find(id);
287 int fres_threads_vres_insert(struct fres_thread_vres *th)
291 fosa_mutex_lock(&fres_threads_vres.mutex);
292 ret = fres_threads_vres_nolock_insert(&fres_threads_vres, th);
293 fosa_mutex_unlock(&fres_threads_vres.mutex);
299 int fres_threads_vres_delete(struct fres_thread_vres *th)
303 fosa_mutex_lock(&fres_threads_vres.mutex);
304 ret = fres_threads_vres_nolock_delete(&fres_threads_vres, th);
305 fosa_mutex_unlock(&fres_threads_vres.mutex);
311 struct fres_thread_vres *fres_threads_vres_find(const fosa_thread_id_t *id)
313 struct fres_thread_vres *ret;
315 fosa_mutex_lock(&fres_threads_vres.mutex);
316 ret = fres_threads_vres_nolock_find(&fres_threads_vres, id);
317 fosa_mutex_unlock(&fres_threads_vres.mutex);
323 * Creates binding from a thread to VRES; if binding already exists,
326 * @param id Thread ID bounded to @a vres.
329 * @return Positive number when a new binding was inserted, zero when
330 * binding was changed and -1 on error.
332 int fra_insert_thread_vres(const fosa_thread_id_t *id, fres_vres_t *vres)
334 struct fres_thread_vres *th;
336 th = fres_threads_vres_find(id);
338 fosa_mutex_lock(&fres_threads_vres.mutex);
340 fosa_mutex_unlock(&fres_threads_vres.mutex);
345 th = fres_thread_vres_new(id, vres);
348 return fres_threads_vres_insert(th);
352 * Deletes thread to VRES binding.
354 * @param id Thread ID to unbind.
356 * @return Zero on success, -1 on when the thread was not bound.
358 int fra_delete_thread_vres(const fosa_thread_id_t *id)
360 struct fres_thread_vres *th;
363 fosa_mutex_lock(&fres_threads_vres.mutex);
364 th = fres_threads_vres_nolock_find(&fres_threads_vres, id);
366 fres_threads_vres_nolock_delete(&fres_threads_vres, th);
370 fosa_mutex_unlock(&fres_threads_vres.mutex);
372 fres_thread_vres_destroy(th);
378 * Returns VRES bounded to a thread.
380 * @param id Thread ID
382 * @return VRES on NULL in the thread is not bound.
384 * @todo Is this function needed if we have
385 * fra_get_vres_thread_vres()?
387 fres_thread_vres_t *fra_get_thread_vres(const fosa_thread_id_t *id)
389 return fres_threads_vres_find(id);
393 * Returns VRES bounded to a thread.
395 * @param id Thread ID
397 * @return VRES on NULL in the thread is not bound.
399 fres_vres_t *fra_get_vres_thread_vres(const fosa_thread_id_t *id)
401 fres_thread_vres_t *th_vres;
403 th_vres = fres_threads_vres_find(id);
404 if (!th_vres) return NULL;
406 return th_vres->vres;