]> rtime.felk.cvut.cz Git - frescor/frsh-forb.git/blob - src/fna/src_frescan/frescan_bwres_robjs.c
Add 'src/fna/' from commit '493e9e8be9c3761691b96e8366d036d6b3c314fb'
[frescor/frsh-forb.git] / src / fna / src_frescan / frescan_bwres_robjs.c
1 /*!
2  * @file frescan_bwres_robjs.c
3  *
4  * @brief FRESCAN bandwith reservation layer: reply objects
5  *
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.
9  *
10  * @version 0.01
11  *
12  * @date 1-Apr-2008
13  *
14  * @author Daniel Sangorrin <daniel.sangorrin@unican.es>
15  *
16  * @license
17  *
18 //----------------------------------------------------------------------
19 //  Copyright (C) 2006 - 2009 by the FRESCOR consortium:
20 //
21 //    Universidad de Cantabria,              SPAIN
22 //    University of York,                    UK
23 //    Scuola Superiore Sant'Anna,            ITALY
24 //    Kaiserslautern University,             GERMANY
25 //    Univ. Politecnica  Valencia,           SPAIN
26 //    Czech Technical University in Prague,  CZECH REPUBLIC
27 //    ENEA                                   SWEDEN
28 //    Thales Communication S.A.              FRANCE
29 //    Visual Tools S.A.                      SPAIN
30 //    Rapita Systems Ltd                     UK
31 //    Evidence                               ITALY
32 //
33 //    See http://www.frescor.org
34 //
35 //        The 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
38 //        made of this code.
39 //
40 //
41 //  based on previous work (FSF) done in the FIRST project
42 //
43 //   Copyright (C) 2005  Mälardalen University, SWEDEN
44 //                       Scuola Superiore S.Anna, ITALY
45 //                       Universidad de Cantabria, SPAIN
46 //                       University of York, UK
47 //
48 // This file is part of FNA (Frescor Network Adaptation)
49 //
50 // FNA is free software; you can redistribute it and/or modify it
51 // under terms of the GNU General Public License as published by the
52 // Free Software Foundation; either version 2, or (at your option) any
53 // later version.  FNA is distributed in the hope that it will be
54 // useful, but WITHOUT ANY WARRANTY; without even the implied warranty
55 // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
56 // General Public License for more details. You should have received a
57 // copy of the GNU General Public License along with FNA; see file
58 // COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,
59 // Cambridge, MA 02139, USA.
60 //
61 // As a special exception, including FNA header files in a file,
62 // instantiating FNA generics or templates, or linking other files
63 // with FNA objects to produce an executable application, does not
64 // by itself cause the resulting executable application to be covered
65 // by the GNU General Public License. This exception does not
66 // however invalidate any other reasons why the executable file might be
67 // covered by the GNU Public License.
68 // -----------------------------------------------------------------------
69  *
70  */
71
72 #include <misc/freelist.h>
73 #include "frescan_bwres_robjs.h"
74 #include "fosa_mutexes_and_condvars.h"
75 #include "frescan_config.h"
76 #include "frescan_debug.h"
77
78 static bool is_initialized = false;
79
80 /**
81  * the_reply_objects
82  *
83  * We will use a freelist to allocate and free the reply object. Reply objects
84  * are FOSA conditional variables (we can't use synchobjects because they are
85  * only for bound-workload) stored in an array together with their condition
86  * and a mutex variable to control the access and to be able to wait and
87  * signal the conditional variables. We could have used semaphores instead, but
88  * it would introduce a dependency on the OS because they are not in FOSA.
89  *
90  **/
91
92 static fosa_mutex_t freelist_mutex;
93
94 struct replyobj_t {
95         bool is_work_done;
96         fosa_cond_t cond;
97         fosa_mutex_t mutex;
98 };
99
100 static struct replyobj_t the_reply_objects[FRESCAN_BWRES_MX_REPLY_OBJECTS];
101 static freelist_t freelist;
102
103 /**
104  * frescan_bwres_robjs_init()
105  *
106  * Init the freelist and its mutex. The conditional variables are not
107  * initialized here but when allocating a reply object. This can be more
108  * efficient for memory usage in some OS (not in MaRTE OS though).
109  *
110  **/
111
112 int frescan_bwres_robjs_init(int max_ceiling)
113 {
114         int err;
115
116         err = fosa_mutex_init(&freelist_mutex, max_ceiling);
117         if (err != 0) return err;
118
119         err = freelist_init(&freelist, FRESCAN_BWRES_MX_REPLY_OBJECTS);
120         if (err != 0) return err;
121
122         is_initialized = true;
123         return 0;
124 }
125
126 /**
127  * frescan_bwres_robjs_alloc()
128  *
129  * Allocate an reply object with the freelist_mutex locked and then initialize
130  * its cond variable, condition (predicate) and mutex. The ID of the allocated
131  * reply object represents the position in the array the_reply_objects.
132  *
133  **/
134
135 int frescan_bwres_robjs_alloc(frescan_bwres_robj_id_t *id, int ceiling)
136 {
137         int err, pos;
138
139         DEBUG(FRESCAN_BWRES_ROBJS_ENABLE_DEBUG,
140               "allocating reply object, is_initialized=%d\n", is_initialized);
141
142         if (is_initialized == false) return -1;
143
144         err = fosa_mutex_lock(&freelist_mutex);
145         if (err != 0) return err;
146
147                 pos = freelist_alloc(&freelist);
148                 if (pos < 0) goto locked_error;
149
150         err = fosa_mutex_unlock(&freelist_mutex);
151         if (err != 0) return err;
152
153         err = fosa_cond_init(&the_reply_objects[pos].cond);
154         if (err != 0) return err;
155
156         the_reply_objects[pos].is_work_done = false;
157         *id = (unsigned int)pos;
158
159         err = fosa_mutex_init(&the_reply_objects[pos].mutex, ceiling);
160         if (err != 0) return err;
161
162         DEBUG(FRESCAN_BWRES_ROBJS_ENABLE_DEBUG,
163               "reply object allocated, id=%d\n", *id);
164
165         return 0;
166
167 locked_error:
168         fosa_mutex_unlock(&freelist_mutex);
169         return pos;
170 }
171
172 /**
173  * frescan_bwres_robjs_free()
174  *
175  * Destroy the cond variable and then free the replyobject
176  *
177  **/
178
179 int frescan_bwres_robjs_free(frescan_bwres_robj_id_t id)
180 {
181         int err;
182
183         DEBUG(FRESCAN_BWRES_ROBJS_ENABLE_DEBUG,
184               "free reply id=%d, is_initialized=%d\n", id, is_initialized);
185
186         if (is_initialized == false) return -1;
187
188         err = fosa_mutex_lock(&freelist_mutex);
189         if (err != 0) return err;
190
191                 err = freelist_free(&freelist, id);
192                 if (err != 0) goto locked_error;
193
194                 err = fosa_cond_destroy(&the_reply_objects[id].cond);
195                 if (err != 0) return err;
196
197                 err = fosa_mutex_destroy(&the_reply_objects[id].mutex);
198                 if (err != 0) return err;
199
200                 the_reply_objects[id].is_work_done = false;
201
202         err = fosa_mutex_unlock(&freelist_mutex);
203         if (err != 0) return err;
204
205         return 0;
206
207 locked_error:
208         fosa_mutex_unlock(&freelist_mutex);
209         return err;
210 }
211
212 /**
213  * frescan_bwres_robjs_signal()
214  *
215  * Signal the cond variable
216  *
217  **/
218
219 int frescan_bwres_robjs_signal(frescan_bwres_robj_id_t id)
220 {
221         int err;
222
223         DEBUG(FRESCAN_BWRES_ROBJS_ENABLE_DEBUG,
224               "is_initialized=%d\n", is_initialized);
225         if (is_initialized == false) return -1;
226
227         DEBUG(FRESCAN_BWRES_ROBJS_ENABLE_DEBUG,
228               "taking mutex of the reply id=%d\n", id);
229         err = fosa_mutex_lock(&the_reply_objects[id].mutex);
230         if (err != 0) return err;
231
232                 the_reply_objects[id].is_work_done = true;
233
234                 DEBUG(FRESCAN_BWRES_ROBJS_ENABLE_DEBUG,
235                       "signal the cond variable\n");
236                 err = fosa_cond_signal(&the_reply_objects[id].cond);
237                 if (err != 0) goto locked_error;
238
239         err = fosa_mutex_unlock(&the_reply_objects[id].mutex);
240         if (err != 0) return err;
241
242         return 0;
243
244 locked_error:
245         FRESCAN_ERROR("locked error %d\n", err);
246         fosa_mutex_unlock(&the_reply_objects[id].mutex);
247         return err;
248 }
249
250 /**
251  * frescan_bwres_robjs_wait()
252  *
253  * Wait on the cond variable.
254  *
255  **/
256
257 int frescan_bwres_robjs_wait(frescan_bwres_robj_id_t id)
258 {
259         int err;
260
261         if (is_initialized == false) return -1;
262
263         err = fosa_mutex_lock(&the_reply_objects[id].mutex);
264         if (err != 0) return err;
265
266                 while (the_reply_objects[id].is_work_done == false) {
267                         err = fosa_cond_wait(&the_reply_objects[id].cond,
268                                              &the_reply_objects[id].mutex);
269                         if (err != 0) goto locked_error;
270                 }
271
272                 the_reply_objects[id].is_work_done = false;
273
274         err = fosa_mutex_unlock(&the_reply_objects[id].mutex);
275         if (err != 0) return err;
276
277         return 0;
278
279 locked_error:
280         fosa_mutex_unlock(&the_reply_objects[id].mutex);
281         return err;
282 }
283
284 /**
285  * frescan_bwres_robjs_timedwait()
286  *
287  * Wait on the cond variable with a timeout.
288  *
289  **/
290
291 int frescan_bwres_robjs_timedwait(frescan_bwres_robj_id_t id,
292                                   const struct timespec *abstime)
293 {
294         int err;
295
296         if (is_initialized == false) return -1;
297
298         err = fosa_mutex_lock(&the_reply_objects[id].mutex);
299         if (err != 0) return err;
300
301         while (the_reply_objects[id].is_work_done == false) {
302                 err = fosa_cond_timedwait(&the_reply_objects[id].cond,
303                                           &the_reply_objects[id].mutex,
304                                           abstime);
305                 if (err != 0) goto locked_error;
306         }
307
308         the_reply_objects[id].is_work_done = false;
309
310         err = fosa_mutex_unlock(&the_reply_objects[id].mutex);
311         if (err != 0) return err;
312
313         return 0;
314
315 locked_error:
316         fosa_mutex_unlock(&the_reply_objects[id].mutex);
317         return err;
318 }