2 * @file frescan_requests.c
4 * @brief FRESCAN requests
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.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;
42 struct list_head request_list;
46 static fosa_mutex_t requests_mutex;
47 static fosa_cond_t requests_cond;
49 static struct request_t the_requests_pool[FRESCAN_MX_REQUESTS];
50 static freelist_t freelist;
51 static struct request_t the_requests_list;
54 * frescan_requests_init()
56 * Init the freelist, requests list, cond var and mutex.
60 int frescan_requests_init(int max_ceiling)
64 err = fosa_mutex_init(&requests_mutex, max_ceiling);
65 if (err != 0) return err;
67 err = fosa_cond_init(&requests_cond);
68 if (err != 0) return err;
70 err = freelist_init(&freelist, FRESCAN_MX_REQUESTS);
71 if (err != 0) return err;
73 INIT_LIST_HEAD(&the_requests_list.request_list);
75 is_initialized = true;
80 * frescan_request_alloc()
82 * Allocate a request with the mutex locked
86 int frescan_request_alloc(frescan_request_id_t *id)
90 if (is_initialized == false) return -1;
92 err = fosa_mutex_lock(&requests_mutex);
93 if (err != 0) return err;
95 pos = freelist_alloc(&freelist);
96 if (pos < 0) goto locked_error;
98 err = fosa_mutex_unlock(&requests_mutex);
99 if (err != 0) return err;
101 *id = (unsigned int)pos;
102 the_requests_pool[*id].pool_pos = pos;
107 fosa_mutex_unlock(&requests_mutex);
112 * frescan_request_free()
114 * free the request from the pool
118 int frescan_request_free(frescan_request_id_t id)
122 if (is_initialized == false) return -1;
124 err = fosa_mutex_lock(&requests_mutex);
125 if (err != 0) return err;
127 err = freelist_free(&freelist, id);
128 if (err != 0) goto locked_error;
130 err = fosa_mutex_unlock(&requests_mutex);
131 if (err != 0) return err;
136 fosa_mutex_unlock(&requests_mutex);
141 * frescan_request_set_type()
145 int frescan_request_set_type(frescan_request_id_t id, frescan_req_type_t type)
147 DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG, "id:%d, type:%d\n", id, type);
148 the_requests_pool[id].type = type;
153 * frescan_request_set_reply()
157 int frescan_request_set_reply(frescan_request_id_t id, frescan_robj_id_t reply)
159 the_requests_pool[id].reply = reply;
164 * frescan_request_set_contract()
168 int frescan_request_set_contract(frescan_request_id_t id,
169 const frescan_contract_t *contract)
171 the_requests_pool[id].contract = (frescan_contract_t *)contract;
176 * frescan_request_set_ss()
180 int frescan_request_set_ss(frescan_request_id_t id,
183 the_requests_pool[id].ss = ss;
188 * frescan_request_set_src()
192 int frescan_request_set_src(frescan_request_id_t id, frescan_node_t src)
194 the_requests_pool[id].src = src;
199 * frescan_request_set_return_info()
203 int frescan_request_set_return_info(frescan_request_id_t id,
206 the_requests_pool[id].return_info = return_info;
211 * frescan_request_get_type()
215 int frescan_request_get_type(frescan_request_id_t id, frescan_req_type_t *type)
217 *type = the_requests_pool[id].type;
218 DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG, "id:%d, type:%d\n", id, *type);
223 * frescan_request_get_reply()
227 int frescan_request_get_reply(frescan_request_id_t id, frescan_robj_id_t *reply)
229 *reply = the_requests_pool[id].reply;
234 * frescan_request_get_contract()
238 int frescan_request_get_contract(frescan_request_id_t id,
239 frescan_contract_t **contract)
241 *contract = the_requests_pool[id].contract;
246 * frescan_request_get_src()
250 int frescan_request_get_src(frescan_request_id_t id, frescan_node_t *src)
252 *src = the_requests_pool[id].src;
257 * frescan_request_get_return_info()
261 int frescan_request_get_return_info(frescan_request_id_t id,
264 *return_info = the_requests_pool[id].return_info;
269 * frescan_requestqueue_enqueue()
273 int frescan_requestqueue_enqueue(frescan_request_id_t id)
277 err = fosa_mutex_lock(&requests_mutex);
278 if (err != 0) return err;
280 DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG,
281 "is list empty A? %d\n",
282 list_empty(&the_requests_list.request_list));
284 list_add_tail(&the_requests_pool[id].request_list,
285 &the_requests_list.request_list);
287 DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG,
288 "is list empty B? %d\n",
289 list_empty(&the_requests_list.request_list));
291 err = fosa_cond_signal(&requests_cond);
292 if (err != 0) goto locked_error;
294 err = fosa_mutex_unlock(&requests_mutex);
295 if (err != 0) return err;
300 fosa_mutex_unlock(&requests_mutex);
305 * frescan_requestqueue_dequeue()
309 int frescan_requestqueue_dequeue(frescan_request_id_t *id)
312 struct list_head *pos;
313 struct request_t *request = NULL;
315 err = fosa_mutex_lock(&requests_mutex);
316 if (err != 0) return err;
318 DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG, "entering\n");
320 while (list_empty(&the_requests_list.request_list)) {
321 err = fosa_cond_wait(&requests_cond, &requests_mutex);
322 if (err != 0) goto locked_error;
323 DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG, "received signal\n");
326 DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG, "dequeueing a request\n");
328 list_for_each(pos, &the_requests_list.request_list) {
329 request = list_entry(pos, struct request_t, request_list);
333 list_del(&request->request_list);
335 *id = request->pool_pos;
337 DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG,
338 "is list empty now? %d\n",
339 list_empty(&the_requests_list.request_list));
341 err = fosa_mutex_unlock(&requests_mutex);
342 if (err != 0) return err;
347 fosa_mutex_unlock(&requests_mutex);