]> rtime.felk.cvut.cz Git - frescor/fna.git/blob - src_frescan/frescan_reply_objects.c
d741397494ef7f3951ddd9867fc174908860c73d
[frescor/fna.git] / src_frescan / frescan_reply_objects.c
1 /*!
2  * @file frescan_reply_objects.h
3  *
4  * @brief FRESCAN 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  */
17
18 #include <misc/freelist.h>
19 #include "frescan_reply_objects.h"
20 #include "fosa_mutexes_and_condvars.h"
21 #include "frescan_config.h"
22 #include "frescan_debug.h"
23
24 static bool is_initialized = false;
25
26 /**
27  * the_reply_objects
28  *
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.
35  *
36  **/
37
38 static fosa_mutex_t freelist_mutex;
39
40 struct replyobj_t {
41         bool is_work_done;
42         fosa_cond_t cond;
43         fosa_mutex_t mutex;
44 };
45
46 static struct replyobj_t the_reply_objects[FRESCAN_MX_REPLY_OBJECTS];
47 static freelist_t freelist;
48
49 /**
50  * frescan_replyobjects_init()
51  *
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).
55  *
56  **/
57
58 int frescan_replyobjects_init(int max_ceiling)
59 {
60         int err;
61
62         err = fosa_mutex_init(&freelist_mutex, max_ceiling);
63         if (err != 0) return err;
64
65         err = freelist_init(&freelist, FRESCAN_MX_REPLY_OBJECTS);
66         if (err != 0) return err;
67
68         is_initialized = true;
69         return 0;
70 }
71
72 /**
73  * frescan_replyobject_alloc()
74  *
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.
78  *
79  **/
80
81 int frescan_replyobject_alloc(frescan_robj_id_t *id, int ceiling)
82 {
83         int err, pos;
84
85         DEBUG(FRESCAN_REPLYOBJ_ENABLE_DEBUG,
86               "allocating reply object, is_initialized=%d\n", is_initialized);
87
88         if (is_initialized == false) return -1;
89
90         err = fosa_mutex_lock(&freelist_mutex);
91         if (err != 0) return err;
92
93                 pos = freelist_alloc(&freelist);
94                 if (pos < 0) goto locked_error;
95
96         err = fosa_mutex_unlock(&freelist_mutex);
97         if (err != 0) return err;
98
99         err = fosa_cond_init(&the_reply_objects[pos].cond);
100         if (err != 0) return err;
101
102         the_reply_objects[pos].is_work_done = false;
103         *id = (unsigned int)pos;
104
105         err = fosa_mutex_init(&the_reply_objects[pos].mutex, ceiling);
106         if (err != 0) return err;
107
108         DEBUG(FRESCAN_REPLYOBJ_ENABLE_DEBUG,
109               "reply object allocated, id=%d\n", *id);
110
111         return 0;
112
113 locked_error:
114         fosa_mutex_unlock(&freelist_mutex);
115         return pos;
116 }
117
118 /**
119  * frescan_replyobject_free()
120  *
121  * Destroy the cond variable and then free the replyobject
122  *
123  **/
124
125 int frescan_replyobject_free(frescan_robj_id_t id)
126 {
127         int err;
128
129         DEBUG(FRESCAN_REPLYOBJ_ENABLE_DEBUG,
130               "free reply id=%d, is_initialized=%d\n", id, is_initialized);
131
132         if (is_initialized == false) return -1;
133
134         err = fosa_mutex_lock(&freelist_mutex);
135         if (err != 0) return err;
136
137                 err = freelist_free(&freelist, id);
138                 if (err != 0) goto locked_error;
139
140                 err = fosa_cond_destroy(&the_reply_objects[id].cond);
141                 if (err != 0) return err;
142
143                 err = fosa_mutex_destroy(&the_reply_objects[id].mutex);
144                 if (err != 0) return err;
145
146                 the_reply_objects[id].is_work_done = false;
147
148         err = fosa_mutex_unlock(&freelist_mutex);
149         if (err != 0) return err;
150
151         return 0;
152
153 locked_error:
154         fosa_mutex_unlock(&freelist_mutex);
155         return err;
156 }
157
158 /**
159  * frescan_replyobject_signal()
160  *
161  * Signal the cond variable
162  *
163  **/
164
165 int frescan_replyobject_signal(frescan_robj_id_t id)
166 {
167         int err;
168
169         DEBUG(FRESCAN_REPLYOBJ_ENABLE_DEBUG,
170               "is_initialized=%d\n", is_initialized);
171         if (is_initialized == false) return -1;
172
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;
177
178                 the_reply_objects[id].is_work_done = true;
179
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;
184
185         err = fosa_mutex_unlock(&the_reply_objects[id].mutex);
186         if (err != 0) return err;
187
188         return 0;
189
190 locked_error:
191         ERROR("locked error %d\n", err);
192         fosa_mutex_unlock(&the_reply_objects[id].mutex);
193         return err;
194 }
195
196 /**
197  * frescan_replyobject_wait()
198  *
199  * Wait on the cond variable.
200  *
201  **/
202
203 int frescan_replyobject_wait(frescan_robj_id_t id)
204 {
205         int err;
206
207         if (is_initialized == false) return -1;
208
209         err = fosa_mutex_lock(&the_reply_objects[id].mutex);
210         if (err != 0) return err;
211
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;
216                 }
217
218                 the_reply_objects[id].is_work_done = false;
219
220         err = fosa_mutex_unlock(&the_reply_objects[id].mutex);
221         if (err != 0) return err;
222
223         return 0;
224
225 locked_error:
226         fosa_mutex_unlock(&the_reply_objects[id].mutex);
227         return err;
228 }
229
230 /**
231  * frescan_replyobject_timedwait()
232  *
233  * Wait on the cond variable with a timeout.
234  *
235  **/
236
237 int frescan_replyobject_timedwait(frescan_robj_id_t id,
238                                   const struct timespec *abstime)
239 {
240         int err;
241
242         if (is_initialized == false) return -1;
243
244         err = fosa_mutex_lock(&the_reply_objects[id].mutex);
245         if (err != 0) return err;
246
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,
250                                           abstime);
251                 if (err != 0) goto locked_error;
252         }
253
254         the_reply_objects[id].is_work_done = false;
255
256         err = fosa_mutex_unlock(&the_reply_objects[id].mutex);
257         if (err != 0) return err;
258
259         return 0;
260
261 locked_error:
262         fosa_mutex_unlock(&the_reply_objects[id].mutex);
263         return err;
264 }