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 (vres->allocated) {
188 struct fres_contract *last_perceived = vres->perceived;
189 ret = alloc->change_vres(vreses[i], alloc->priv);
190 if (last_perceived == vres->perceived) {
191 ul_logerr("change_vres callback did not change the perceived vres!");
192 vres->perceived = vres->new;
195 ret = alloc->create_vres(vreses[i], alloc->priv);
196 vres->perceived = vres->new;
199 ul_logerr("VRES apply error %d\n", ret);
200 goto err_free_vreses;
205 /* Update the vres structures */
206 for (i=0; i<len; i++) {
207 struct fres_vres *vres = vreses[i];
208 struct fres_contract *tmp;
210 tmp = vres->allocated;
211 vres->allocated = vres->new;
212 if (tmp) fres_contract_destroy(tmp);
223 CORBA_long cancel_vreses(fres_resource_allocator obj,
224 const fres_contract_id_seq* ids,
225 CORBA_Environment *ev)
228 struct fres_allocator *alloc = forb_instance_data(obj);
230 for (i=0; i < ids->_length; i++) {
231 struct fres_vres *vres;
232 fres_contract_id_t *id = &ids->_buffer[i];
234 vres = fres_vreses_find(id);
237 ret = alloc->cancel_vres(vres, alloc->priv);
238 if (ret != 0) goto err;
240 fres_vreses_delete(vres);
241 fres_vres_destroy(vres);
248 static const struct forb_fres_resource_allocator_impl fra_impl = {
249 .change_vreses = change_vreses,
250 .cancel_vreses = cancel_vreses,
255 * Creates allocator object and registeres it with the given executor.
261 * @return Object reference on success or NULL on error.
263 fres_resource_allocator fra_new(forb_orb orb,
264 forb_executor_t *executor,
265 struct fres_allocator *allocator)
268 fres_resource_allocator fra;
270 fra = forb_fres_resource_allocator_new(orb, &fra_impl, allocator);
272 save_errno(ul_logerr("forb_fres_resource_manager_new error"));
276 /* Prepare executor before we register the resource allocator
277 * with contract broker */
278 ret = forb_executor_register_object(executor, fra);
279 if (ret) goto err_release;
283 save_errno(forb_object_release(fra));
289 * Returns pointer to VRes, which corresponds to the contract with the
294 * @return Pointer to VRes, or NULL in the VRes doesn't exist.
296 fres_vres_t *fra_get_vres(fres_contract_id_t *id)
298 return fres_vreses_find(id);
302 int fres_threads_vres_insert(struct fres_thread_vres *th)
306 fosa_mutex_lock(&fres_threads_vres.mutex);
307 ret = fres_threads_vres_nolock_insert(&fres_threads_vres, th);
308 fosa_mutex_unlock(&fres_threads_vres.mutex);
314 int fres_threads_vres_delete(struct fres_thread_vres *th)
318 fosa_mutex_lock(&fres_threads_vres.mutex);
319 ret = fres_threads_vres_nolock_delete(&fres_threads_vres, th);
320 fosa_mutex_unlock(&fres_threads_vres.mutex);
326 struct fres_thread_vres *fres_threads_vres_find(const fosa_thread_id_t *id)
328 struct fres_thread_vres *ret;
330 fosa_mutex_lock(&fres_threads_vres.mutex);
331 ret = fres_threads_vres_nolock_find(&fres_threads_vres, id);
332 fosa_mutex_unlock(&fres_threads_vres.mutex);
338 * Creates binding from a thread to VRES; if binding already exists,
341 * @param id Thread ID bounded to @a vres.
344 * @return Positive number when a new binding was inserted, zero when
345 * binding was changed and -1 on error.
347 int fra_insert_thread_vres(const fosa_thread_id_t *id, fres_vres_t *vres)
349 struct fres_thread_vres *th;
351 th = fres_threads_vres_find(id);
353 fosa_mutex_lock(&fres_threads_vres.mutex);
355 fosa_mutex_unlock(&fres_threads_vres.mutex);
360 th = fres_thread_vres_new(id, vres);
363 return fres_threads_vres_insert(th);
367 * Deletes thread to VRES binding.
369 * @param id Thread ID to unbind.
371 * @return Zero on success, -1 on when the thread was not bound.
373 int fra_delete_thread_vres(const fosa_thread_id_t *id)
375 struct fres_thread_vres *th;
378 fosa_mutex_lock(&fres_threads_vres.mutex);
379 th = fres_threads_vres_nolock_find(&fres_threads_vres, id);
381 fres_threads_vres_nolock_delete(&fres_threads_vres, th);
385 fosa_mutex_unlock(&fres_threads_vres.mutex);
387 fres_thread_vres_destroy(th);
393 * Returns VRES bounded to a thread.
395 * @param id Thread ID
397 * @return VRES on NULL in the thread is not bound.
399 * @todo Is this function needed if we have
400 * fra_get_vres_thread_vres()?
402 fres_thread_vres_t *fra_get_thread_vres(const fosa_thread_id_t *id)
404 return fres_threads_vres_find(id);
408 * Returns VRES bounded to a thread.
410 * @param id Thread ID
412 * @return VRES on NULL in the thread is not bound.
414 fres_vres_t *fra_get_vres_thread_vres(const fosa_thread_id_t *id)
416 fres_thread_vres_t *th_vres;
418 th_vres = fres_threads_vres_find(id);
419 if (!th_vres) return NULL;
421 return th_vres->vres;