2 * @file frescan_bwres_robjs.c
4 * @brief FRESCAN bandwith reservation layer: reply objects
6 * This module contains the definition of the data object and operations to
7 * create a pool of objects, obtain the id of an unused object, wait upon it,
8 * signal it, and finish using it.
14 * @author Daniel Sangorrin <daniel.sangorrin@unican.es>
18 * -----------------------------------------------------------------------
19 * Copyright (C) 2006 - 2008 FRESCOR consortium partners:
21 * Universidad de Cantabria, SPAIN
22 * University of York, UK
23 * Scuola Superiore Sant'Anna, ITALY
24 * Kaiserslautern University, GERMANY
25 * Univ. Politécnica Valencia, SPAIN
26 * Czech Technical University in Prague, CZECH REPUBLIC
28 * Thales Communication S.A. FRANCE
29 * Visual Tools S.A. SPAIN
30 * Rapita Systems Ltd UK
33 * See http://www.frescor.org for a link to partners' websites
35 * FRESCOR project (FP6/2005/IST/5-034026) is funded
36 * in part by the European Union Sixth Framework Programme
37 * The European Union is not liable of any use that may be
40 * This file is part of FRESCAN
42 * FRESCAN is free software; you can redistribute it and/or modify
43 * it under the terms of the GNU General Public License as published by
44 * the Free Software Foundation; either version 2, or (at your option)
47 * FRESCAN is distributed in the hope that it will be useful, but
48 * WITHOUT ANY WARRANTY; without even the implied warranty of
49 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
50 * General Public License for more details.
52 * You should have received a copy of the GNU General Public License
53 * distributed with FRESCAN; see file COPYING. If not, write to the
54 * Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
57 * As a special exception, including FRESCAN header files in a file,
58 * instantiating FRESCAN generics or templates, or linking other files
59 * with FRESCAN objects to produce an executable application, does not
60 * by itself cause the resulting executable application to be covered
61 * by the GNU General Public License. This exception does not
62 * however invalidate any other reasons why the executable file might be
63 * covered by the GNU Public License.
64 * -----------------------------------------------------------------------
68 #include <misc/freelist.h>
69 #include "frescan_bwres_robjs.h"
70 #include "fosa_mutexes_and_condvars.h"
71 #include "frescan_config.h"
72 #include "frescan_debug.h"
74 static bool is_initialized = false;
79 * We will use a freelist to allocate and free the reply object. Reply objects
80 * are FOSA conditional variables (we can't use synchobjects because they are
81 * only for bound-workload) stored in an array together with their condition
82 * and a mutex variable to control the access and to be able to wait and
83 * signal the conditional variables. We could have used semaphores instead, but
84 * it would introduce a dependency on the OS because they are not in FOSA.
88 static fosa_mutex_t freelist_mutex;
96 static struct replyobj_t the_reply_objects[FRESCAN_BWRES_MX_REPLY_OBJECTS];
97 static freelist_t freelist;
100 * frescan_bwres_robjs_init()
102 * Init the freelist and its mutex. The conditional variables are not
103 * initialized here but when allocating a reply object. This can be more
104 * efficient for memory usage in some OS (not in MaRTE OS though).
108 int frescan_bwres_robjs_init(int max_ceiling)
112 err = fosa_mutex_init(&freelist_mutex, max_ceiling);
113 if (err != 0) return err;
115 err = freelist_init(&freelist, FRESCAN_BWRES_MX_REPLY_OBJECTS);
116 if (err != 0) return err;
118 is_initialized = true;
123 * frescan_bwres_robjs_alloc()
125 * Allocate an reply object with the freelist_mutex locked and then initialize
126 * its cond variable, condition (predicate) and mutex. The ID of the allocated
127 * reply object represents the position in the array the_reply_objects.
131 int frescan_bwres_robjs_alloc(frescan_bwres_robj_id_t *id, int ceiling)
135 DEBUG(FRESCAN_BWRES_ROBJS_ENABLE_DEBUG,
136 "allocating reply object, is_initialized=%d\n", is_initialized);
138 if (is_initialized == false) return -1;
140 err = fosa_mutex_lock(&freelist_mutex);
141 if (err != 0) return err;
143 pos = freelist_alloc(&freelist);
144 if (pos < 0) goto locked_error;
146 err = fosa_mutex_unlock(&freelist_mutex);
147 if (err != 0) return err;
149 err = fosa_cond_init(&the_reply_objects[pos].cond);
150 if (err != 0) return err;
152 the_reply_objects[pos].is_work_done = false;
153 *id = (unsigned int)pos;
155 err = fosa_mutex_init(&the_reply_objects[pos].mutex, ceiling);
156 if (err != 0) return err;
158 DEBUG(FRESCAN_BWRES_ROBJS_ENABLE_DEBUG,
159 "reply object allocated, id=%d\n", *id);
164 fosa_mutex_unlock(&freelist_mutex);
169 * frescan_bwres_robjs_free()
171 * Destroy the cond variable and then free the replyobject
175 int frescan_bwres_robjs_free(frescan_bwres_robj_id_t id)
179 DEBUG(FRESCAN_BWRES_ROBJS_ENABLE_DEBUG,
180 "free reply id=%d, is_initialized=%d\n", id, is_initialized);
182 if (is_initialized == false) return -1;
184 err = fosa_mutex_lock(&freelist_mutex);
185 if (err != 0) return err;
187 err = freelist_free(&freelist, id);
188 if (err != 0) goto locked_error;
190 err = fosa_cond_destroy(&the_reply_objects[id].cond);
191 if (err != 0) return err;
193 err = fosa_mutex_destroy(&the_reply_objects[id].mutex);
194 if (err != 0) return err;
196 the_reply_objects[id].is_work_done = false;
198 err = fosa_mutex_unlock(&freelist_mutex);
199 if (err != 0) return err;
204 fosa_mutex_unlock(&freelist_mutex);
209 * frescan_bwres_robjs_signal()
211 * Signal the cond variable
215 int frescan_bwres_robjs_signal(frescan_bwres_robj_id_t id)
219 DEBUG(FRESCAN_BWRES_ROBJS_ENABLE_DEBUG,
220 "is_initialized=%d\n", is_initialized);
221 if (is_initialized == false) return -1;
223 DEBUG(FRESCAN_BWRES_ROBJS_ENABLE_DEBUG,
224 "taking mutex of the reply id=%d\n", id);
225 err = fosa_mutex_lock(&the_reply_objects[id].mutex);
226 if (err != 0) return err;
228 the_reply_objects[id].is_work_done = true;
230 DEBUG(FRESCAN_BWRES_ROBJS_ENABLE_DEBUG,
231 "signal the cond variable\n");
232 err = fosa_cond_signal(&the_reply_objects[id].cond);
233 if (err != 0) goto locked_error;
235 err = fosa_mutex_unlock(&the_reply_objects[id].mutex);
236 if (err != 0) return err;
241 FRESCAN_ERROR("locked error %d\n", err);
242 fosa_mutex_unlock(&the_reply_objects[id].mutex);
247 * frescan_bwres_robjs_wait()
249 * Wait on the cond variable.
253 int frescan_bwres_robjs_wait(frescan_bwres_robj_id_t id)
257 if (is_initialized == false) return -1;
259 err = fosa_mutex_lock(&the_reply_objects[id].mutex);
260 if (err != 0) return err;
262 while (the_reply_objects[id].is_work_done == false) {
263 err = fosa_cond_wait(&the_reply_objects[id].cond,
264 &the_reply_objects[id].mutex);
265 if (err != 0) goto locked_error;
268 the_reply_objects[id].is_work_done = false;
270 err = fosa_mutex_unlock(&the_reply_objects[id].mutex);
271 if (err != 0) return err;
276 fosa_mutex_unlock(&the_reply_objects[id].mutex);
281 * frescan_bwres_robjs_timedwait()
283 * Wait on the cond variable with a timeout.
287 int frescan_bwres_robjs_timedwait(frescan_bwres_robj_id_t id,
288 const struct timespec *abstime)
292 if (is_initialized == false) return -1;
294 err = fosa_mutex_lock(&the_reply_objects[id].mutex);
295 if (err != 0) return err;
297 while (the_reply_objects[id].is_work_done == false) {
298 err = fosa_cond_timedwait(&the_reply_objects[id].cond,
299 &the_reply_objects[id].mutex,
301 if (err != 0) goto locked_error;
304 the_reply_objects[id].is_work_done = false;
306 err = fosa_mutex_unlock(&the_reply_objects[id].mutex);
307 if (err != 0) return err;
312 fosa_mutex_unlock(&the_reply_objects[id].mutex);