]> rtime.felk.cvut.cz Git - frescor/fna.git/blob - src_frescan/frescan_requests_queue.c
joining threads module
[frescor/fna.git] / src_frescan / frescan_requests_queue.c
1 /*!
2  * @file frescan_requests_queue.c
3  *
4  * @brief FRESCAN requests queue
5  *
6  * This module contains an operation to create the queue, an operation to
7  * enqueue a message (with a request), and an operation to
8  * dequeue a message.
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 <misc/linux_list.h>
20 #include "frescan.h"
21 #include "frescan_requests_queue.h"
22 #include "frescan_config.h"
23 #include "frescan_debug.h"
24 #include "fosa_mutexes_and_condvars.h"
25
26 static bool is_initialized = false;
27
28 /**
29  * the_requests_pool
30  *
31  * We will use a freelist to allocate and free the requests.
32  *
33  **/
34
35 struct request_t {
36         frescan_req_type_t  type;
37         frescan_robj_id_t   reply;
38         frescan_contract_t  *contract;
39         frescan_node_t      src;
40         void                *return_info;
41         struct list_head    request_list;
42         int pool_pos;
43 };
44
45 static fosa_mutex_t requests_mutex;
46 static fosa_cond_t  requests_cond;
47
48 static struct request_t the_requests_pool[FRESCAN_MX_REQUESTS];
49 static freelist_t freelist;
50 static struct request_t the_requests_list;
51
52 /**
53  * frescan_requests_init()
54  *
55  * Init the freelist, requests list, cond var and mutex.
56  *
57  **/
58
59 int frescan_requests_init(int max_ceiling)
60 {
61         int err;
62
63         err = fosa_mutex_init(&requests_mutex, max_ceiling);
64         if (err != 0) return err;
65
66         err = fosa_cond_init(&requests_cond);
67         if (err != 0) return err;
68
69         err = freelist_init(&freelist, FRESCAN_MX_REQUESTS);
70         if (err != 0) return err;
71
72         INIT_LIST_HEAD(&the_requests_list.request_list);
73
74         is_initialized = true;
75         return 0;
76 }
77
78 /**
79  * frescan_request_alloc()
80  *
81  * Allocate a request with the mutex locked
82  *
83  **/
84
85 int frescan_request_alloc(frescan_request_id_t *id)
86 {
87         int err, pos;
88
89         if (is_initialized == false) return -1;
90
91         err = fosa_mutex_lock(&requests_mutex);
92         if (err != 0) return err;
93
94                 pos = freelist_alloc(&freelist);
95                 if (pos < 0) goto locked_error;
96
97         err = fosa_mutex_unlock(&requests_mutex);
98         if (err != 0) return err;
99
100         *id = (unsigned int)pos;
101         the_requests_pool[*id].pool_pos = pos;
102
103         return 0;
104
105 locked_error:
106         fosa_mutex_unlock(&requests_mutex);
107         return pos;
108 }
109
110 /**
111  * frescan_request_free()
112  *
113  * free the request from the pool
114  *
115  **/
116
117 int frescan_request_free(frescan_request_id_t id)
118 {
119         int err;
120
121         if (is_initialized == false) return -1;
122
123         err = fosa_mutex_lock(&requests_mutex);
124         if (err != 0) return err;
125
126                 err = freelist_free(&freelist, id);
127                 if (err != 0) goto locked_error;
128
129         err = fosa_mutex_unlock(&requests_mutex);
130         if (err != 0) return err;
131
132         return 0;
133
134 locked_error:
135         fosa_mutex_unlock(&requests_mutex);
136         return err;
137 }
138
139 /**
140  * frescan_request_set_type()
141  *
142  **/
143
144 int frescan_request_set_type(frescan_request_id_t id, frescan_req_type_t type)
145 {
146         DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG, "id:%d, type:%d\n", id, type);
147         the_requests_pool[id].type = type;
148         return 0;
149 }
150
151 /**
152  * frescan_request_set_reply()
153  *
154  **/
155
156 int frescan_request_set_reply(frescan_request_id_t id, frescan_robj_id_t reply)
157 {
158         the_requests_pool[id].reply = reply;
159         return 0;
160 }
161
162 /**
163  * frescan_request_set_contract()
164  *
165  **/
166
167 int frescan_request_set_contract(frescan_request_id_t id,
168                                  const frescan_contract_t *contract)
169 {
170         the_requests_pool[id].contract = (frescan_contract_t *)contract;
171         return 0;
172 }
173
174 /**
175  * frescan_request_set_src()
176  *
177  **/
178
179 int frescan_request_set_src(frescan_request_id_t id, frescan_node_t src)
180 {
181         the_requests_pool[id].src = src;
182         return 0;
183 }
184
185 /**
186  * frescan_request_set_return_info()
187  *
188  **/
189
190 int frescan_request_set_return_info(frescan_request_id_t id,
191                                     void *return_info)
192 {
193         the_requests_pool[id].return_info = return_info;
194         return 0;
195 }
196
197 /**
198  * frescan_request_get_type()
199  *
200  **/
201
202 int frescan_request_get_type(frescan_request_id_t id, frescan_req_type_t *type)
203 {
204         *type = the_requests_pool[id].type;
205         DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG, "id:%d, type:%d\n", id, *type);
206         return 0;
207 }
208
209 /**
210  * frescan_request_get_reply()
211  *
212  **/
213
214 int frescan_request_get_reply(frescan_request_id_t id, frescan_robj_id_t *reply)
215 {
216         *reply = the_requests_pool[id].reply;
217         return 0;
218 }
219
220 /**
221  * frescan_request_get_contract()
222  *
223  **/
224
225 int frescan_request_get_contract(frescan_request_id_t id,
226                                  frescan_contract_t **contract)
227 {
228         *contract = the_requests_pool[id].contract;
229         return 0;
230 }
231
232 /**
233  * frescan_request_get_src()
234  *
235  **/
236
237 int frescan_request_get_src(frescan_request_id_t id, frescan_node_t *src)
238 {
239         *src = the_requests_pool[id].src;
240         return 0;
241 }
242
243 /**
244  * frescan_request_get_return_info()
245  *
246  **/
247
248 int frescan_request_get_return_info(frescan_request_id_t id,
249                                     void **return_info)
250 {
251         *return_info = the_requests_pool[id].return_info;
252         return 0;
253 }
254
255 /**
256  * frescan_requestqueue_enqueue()
257  *
258  **/
259
260 int frescan_requestqueue_enqueue(frescan_request_id_t id)
261 {
262         int err;
263
264         err = fosa_mutex_lock(&requests_mutex);
265         if (err != 0) return err;
266
267         DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG,
268               "is list empty A? %d\n",
269               list_empty(&the_requests_list.request_list));
270
271         list_add_tail(&the_requests_pool[id].request_list,
272                       &the_requests_list.request_list);
273
274         DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG,
275               "is list empty B? %d\n",
276               list_empty(&the_requests_list.request_list));
277
278         err = fosa_cond_signal(&requests_cond);
279         if (err != 0) goto locked_error;
280
281         err = fosa_mutex_unlock(&requests_mutex);
282         if (err != 0) return err;
283
284         return 0;
285
286 locked_error:
287         fosa_mutex_unlock(&requests_mutex);
288         return err;
289 }
290
291 /**
292  * frescan_requestqueue_dequeue()
293  *
294  **/
295
296 int frescan_requestqueue_dequeue(frescan_request_id_t *id)
297 {
298         int err;
299         struct list_head *pos;
300         struct request_t *request = NULL;
301
302         err = fosa_mutex_lock(&requests_mutex);
303         if (err != 0) return err;
304
305         DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG, "entering\n");
306
307         while (list_empty(&the_requests_list.request_list)) {
308                 err = fosa_cond_wait(&requests_cond, &requests_mutex);
309                 if (err != 0) goto locked_error;
310                 DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG, "received signal\n");
311         }
312
313         DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG, "dequeueing a request\n");
314
315         list_for_each(pos, &the_requests_list.request_list) {
316                 request = list_entry(pos, struct request_t, request_list);
317                 break;
318         }
319
320         list_del(&request->request_list);
321
322         *id = request->pool_pos;
323
324         DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG,
325               "is list empty now? %d\n",
326               list_empty(&the_requests_list.request_list));
327
328         err = fosa_mutex_unlock(&requests_mutex);
329         if (err != 0) return err;
330
331         return 0;
332
333 locked_error:
334         fosa_mutex_unlock(&requests_mutex);
335         return err;
336 }