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 #include <misc/freelist.h>
19 #include "frescan_bwres_robjs.h"
20 #include "fosa_mutexes_and_condvars.h"
21 #include "frescan_config.h"
22 #include "frescan_debug.h"
24 static bool is_initialized = false;
29 * We will use a freelist to allocate and free the reply object. Reply objects
30 * are FOSA conditional variables (we can't use synchobjects because they are
31 * only for bound-workload) stored in an array together with their condition
32 * and a mutex variable to control the access and to be able to wait and
33 * signal the conditional variables. We could have used semaphores instead, but
34 * it would introduce a dependency on the OS because they are not in FOSA.
38 static fosa_mutex_t freelist_mutex;
46 static struct replyobj_t the_reply_objects[FRESCAN_MX_REPLY_OBJECTS];
47 static freelist_t freelist;
50 * frescan_bwres_robjs_init()
52 * Init the freelist and its mutex. The conditional variables are not
53 * initialized here but when allocating a reply object. This can be more
54 * efficient for memory usage in some OS (not in MaRTE OS though).
58 int frescan_bwres_robjs_init(int max_ceiling)
62 err = fosa_mutex_init(&freelist_mutex, max_ceiling);
63 if (err != 0) return err;
65 err = freelist_init(&freelist, FRESCAN_MX_REPLY_OBJECTS);
66 if (err != 0) return err;
68 is_initialized = true;
73 * frescan_bwres_robjs_alloc()
75 * Allocate an reply object with the freelist_mutex locked and then initialize
76 * its cond variable, condition (predicate) and mutex. The ID of the allocated
77 * reply object represents the position in the array the_reply_objects.
81 int frescan_bwres_robjs_alloc(frescan_robj_id_t *id, int ceiling)
85 DEBUG(FRESCAN_REPLYOBJ_ENABLE_DEBUG,
86 "allocating reply object, is_initialized=%d\n", is_initialized);
88 if (is_initialized == false) return -1;
90 err = fosa_mutex_lock(&freelist_mutex);
91 if (err != 0) return err;
93 pos = freelist_alloc(&freelist);
94 if (pos < 0) goto locked_error;
96 err = fosa_mutex_unlock(&freelist_mutex);
97 if (err != 0) return err;
99 err = fosa_cond_init(&the_reply_objects[pos].cond);
100 if (err != 0) return err;
102 the_reply_objects[pos].is_work_done = false;
103 *id = (unsigned int)pos;
105 err = fosa_mutex_init(&the_reply_objects[pos].mutex, ceiling);
106 if (err != 0) return err;
108 DEBUG(FRESCAN_REPLYOBJ_ENABLE_DEBUG,
109 "reply object allocated, id=%d\n", *id);
114 fosa_mutex_unlock(&freelist_mutex);
119 * frescan_bwres_robjs_free()
121 * Destroy the cond variable and then free the replyobject
125 int frescan_bwres_robjs_free(frescan_robj_id_t id)
129 DEBUG(FRESCAN_REPLYOBJ_ENABLE_DEBUG,
130 "free reply id=%d, is_initialized=%d\n", id, is_initialized);
132 if (is_initialized == false) return -1;
134 err = fosa_mutex_lock(&freelist_mutex);
135 if (err != 0) return err;
137 err = freelist_free(&freelist, id);
138 if (err != 0) goto locked_error;
140 err = fosa_cond_destroy(&the_reply_objects[id].cond);
141 if (err != 0) return err;
143 err = fosa_mutex_destroy(&the_reply_objects[id].mutex);
144 if (err != 0) return err;
146 the_reply_objects[id].is_work_done = false;
148 err = fosa_mutex_unlock(&freelist_mutex);
149 if (err != 0) return err;
154 fosa_mutex_unlock(&freelist_mutex);
159 * frescan_bwres_robjs_signal()
161 * Signal the cond variable
165 int frescan_bwres_robjs_signal(frescan_robj_id_t id)
169 DEBUG(FRESCAN_REPLYOBJ_ENABLE_DEBUG,
170 "is_initialized=%d\n", is_initialized);
171 if (is_initialized == false) return -1;
173 DEBUG(FRESCAN_REPLYOBJ_ENABLE_DEBUG,
174 "taking mutex of the reply id=%d\n", id);
175 err = fosa_mutex_lock(&the_reply_objects[id].mutex);
176 if (err != 0) return err;
178 the_reply_objects[id].is_work_done = true;
180 DEBUG(FRESCAN_REPLYOBJ_ENABLE_DEBUG,
181 "signal the cond variable\n");
182 err = fosa_cond_signal(&the_reply_objects[id].cond);
183 if (err != 0) goto locked_error;
185 err = fosa_mutex_unlock(&the_reply_objects[id].mutex);
186 if (err != 0) return err;
191 ERROR("locked error %d\n", err);
192 fosa_mutex_unlock(&the_reply_objects[id].mutex);
197 * frescan_bwres_robjs_wait()
199 * Wait on the cond variable.
203 int frescan_bwres_robjs_wait(frescan_robj_id_t id)
207 if (is_initialized == false) return -1;
209 err = fosa_mutex_lock(&the_reply_objects[id].mutex);
210 if (err != 0) return err;
212 while (the_reply_objects[id].is_work_done == false) {
213 err = fosa_cond_wait(&the_reply_objects[id].cond,
214 &the_reply_objects[id].mutex);
215 if (err != 0) goto locked_error;
218 the_reply_objects[id].is_work_done = false;
220 err = fosa_mutex_unlock(&the_reply_objects[id].mutex);
221 if (err != 0) return err;
226 fosa_mutex_unlock(&the_reply_objects[id].mutex);
231 * frescan_bwres_robjs_timedwait()
233 * Wait on the cond variable with a timeout.
237 int frescan_bwres_robjs_timedwait(frescan_robj_id_t id,
238 const struct timespec *abstime)
242 if (is_initialized == false) return -1;
244 err = fosa_mutex_lock(&the_reply_objects[id].mutex);
245 if (err != 0) return err;
247 while (the_reply_objects[id].is_work_done == false) {
248 err = fosa_cond_timedwait(&the_reply_objects[id].cond,
249 &the_reply_objects[id].mutex,
251 if (err != 0) goto locked_error;
254 the_reply_objects[id].is_work_done = false;
256 err = fosa_mutex_unlock(&the_reply_objects[id].mutex);
257 if (err != 0) return err;
262 fosa_mutex_unlock(&the_reply_objects[id].mutex);