2 * @file frescan_requests_queue.c
4 * @brief FRESCAN requests queue
6 * This module contains an operation to create the queue, an operation to
7 * enqueue a message (with a request), and an operation to
14 * @author Daniel Sangorrin <daniel.sangorrin@unican.es>
18 #include <misc/freelist.h>
19 #include <misc/linux_list.h>
21 #include "frescan_requests_queue.h"
22 #include "frescan_config.h"
23 #include "frescan_debug.h"
24 #include "fosa_mutexes_and_condvars.h"
26 static bool is_initialized = false;
31 * We will use a freelist to allocate and free the requests.
36 frescan_req_type_t type;
37 frescan_robj_id_t reply;
38 frescan_contract_t *contract;
41 struct list_head request_list;
45 static fosa_mutex_t requests_mutex;
46 static fosa_cond_t requests_cond;
48 static struct request_t the_requests_pool[FRESCAN_MX_REQUESTS];
49 static freelist_t freelist;
50 static struct request_t the_requests_list;
53 * frescan_requests_init()
55 * Init the freelist, requests list, cond var and mutex.
59 int frescan_requests_init(int max_ceiling)
63 err = fosa_mutex_init(&requests_mutex, max_ceiling);
64 if (err != 0) return err;
66 err = fosa_cond_init(&requests_cond);
67 if (err != 0) return err;
69 err = freelist_init(&freelist, FRESCAN_MX_REQUESTS);
70 if (err != 0) return err;
72 INIT_LIST_HEAD(&the_requests_list.request_list);
74 is_initialized = true;
79 * frescan_request_alloc()
81 * Allocate a request with the mutex locked
85 int frescan_request_alloc(frescan_request_id_t *id)
89 if (is_initialized == false) return -1;
91 err = fosa_mutex_lock(&requests_mutex);
92 if (err != 0) return err;
94 pos = freelist_alloc(&freelist);
95 if (pos < 0) goto locked_error;
97 err = fosa_mutex_unlock(&requests_mutex);
98 if (err != 0) return err;
100 *id = (unsigned int)pos;
101 the_requests_pool[*id].pool_pos = pos;
106 fosa_mutex_unlock(&requests_mutex);
111 * frescan_request_free()
113 * free the request from the pool
117 int frescan_request_free(frescan_request_id_t id)
121 if (is_initialized == false) return -1;
123 err = fosa_mutex_lock(&requests_mutex);
124 if (err != 0) return err;
126 err = freelist_free(&freelist, id);
127 if (err != 0) goto locked_error;
129 err = fosa_mutex_unlock(&requests_mutex);
130 if (err != 0) return err;
135 fosa_mutex_unlock(&requests_mutex);
140 * frescan_request_set_type()
144 int frescan_request_set_type(frescan_request_id_t id, frescan_req_type_t type)
146 DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG, "id:%d, type:%d\n", id, type);
147 the_requests_pool[id].type = type;
152 * frescan_request_set_reply()
156 int frescan_request_set_reply(frescan_request_id_t id, frescan_robj_id_t reply)
158 the_requests_pool[id].reply = reply;
163 * frescan_request_set_contract()
167 int frescan_request_set_contract(frescan_request_id_t id,
168 const frescan_contract_t *contract)
170 the_requests_pool[id].contract = (frescan_contract_t *)contract;
175 * frescan_request_set_src()
179 int frescan_request_set_src(frescan_request_id_t id, frescan_node_t src)
181 the_requests_pool[id].src = src;
186 * frescan_request_set_return_info()
190 int frescan_request_set_return_info(frescan_request_id_t id,
193 the_requests_pool[id].return_info = return_info;
198 * frescan_request_get_type()
202 int frescan_request_get_type(frescan_request_id_t id, frescan_req_type_t *type)
204 *type = the_requests_pool[id].type;
205 DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG, "id:%d, type:%d\n", id, *type);
210 * frescan_request_get_reply()
214 int frescan_request_get_reply(frescan_request_id_t id, frescan_robj_id_t *reply)
216 *reply = the_requests_pool[id].reply;
221 * frescan_request_get_contract()
225 int frescan_request_get_contract(frescan_request_id_t id,
226 frescan_contract_t **contract)
228 *contract = the_requests_pool[id].contract;
233 * frescan_request_get_src()
237 int frescan_request_get_src(frescan_request_id_t id, frescan_node_t *src)
239 *src = the_requests_pool[id].src;
244 * frescan_request_get_return_info()
248 int frescan_request_get_return_info(frescan_request_id_t id,
251 *return_info = the_requests_pool[id].return_info;
256 * frescan_requestqueue_enqueue()
260 int frescan_requestqueue_enqueue(frescan_request_id_t id)
264 err = fosa_mutex_lock(&requests_mutex);
265 if (err != 0) return err;
267 DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG,
268 "is list empty A? %d\n",
269 list_empty(&the_requests_list.request_list));
271 list_add_tail(&the_requests_pool[id].request_list,
272 &the_requests_list.request_list);
274 DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG,
275 "is list empty B? %d\n",
276 list_empty(&the_requests_list.request_list));
278 err = fosa_cond_signal(&requests_cond);
279 if (err != 0) goto locked_error;
281 err = fosa_mutex_unlock(&requests_mutex);
282 if (err != 0) return err;
287 fosa_mutex_unlock(&requests_mutex);
292 * frescan_requestqueue_dequeue()
296 int frescan_requestqueue_dequeue(frescan_request_id_t *id)
299 struct list_head *pos;
300 struct request_t *request = NULL;
302 err = fosa_mutex_lock(&requests_mutex);
303 if (err != 0) return err;
305 DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG, "entering\n");
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");
313 DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG, "dequeueing a request\n");
315 list_for_each(pos, &the_requests_list.request_list) {
316 request = list_entry(pos, struct request_t, request_list);
320 list_del(&request->request_list);
322 *id = request->pool_pos;
324 DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG,
325 "is list empty now? %d\n",
326 list_empty(&the_requests_list.request_list));
328 err = fosa_mutex_unlock(&requests_mutex);
329 if (err != 0) return err;
334 fosa_mutex_unlock(&requests_mutex);