]> rtime.felk.cvut.cz Git - frescor/fna.git/blob - src_frescan/frescan_bwres_requests.c
added message to notify a budget increase or decrease (due to spare capacity)
[frescor/fna.git] / src_frescan / frescan_bwres_requests.c
1 /*!
2  * @file frescan_bwres_requests.c
3  *
4  * @brief FRESCAN bandwith reservation layer: requests
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  * @license
17  *
18  * -----------------------------------------------------------------------
19  *  Copyright (C) 2006 - 2008 FRESCOR consortium partners:
20  *
21  *    Universidad de Cantabria,              SPAIN
22  *    University of York,                    UK
23  *    Scuola Superiore Sant'Anna,            ITALY
24  *    Kaiserslautern University,             GERMANY
25  *    Univ. Politécnica  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 for a link to partners' websites
34  *
35  *           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  *  This file is part of FRESCAN
41  *
42  *  FRESCAN is free software; you can  redistribute it and/or  modify
43  *  it under the terms of  the GNU General Public License as published by
44  *  the Free Software Foundation;  either  version 2, or (at  your option)
45  *  any later version.
46  *
47  *  FRESCAN  is distributed  in  the hope  that  it  will  be useful,  but
48  *  WITHOUT  ANY  WARRANTY;     without  even the   implied   warranty  of
49  *  MERCHANTABILITY  or  FITNESS FOR  A  PARTICULAR PURPOSE. See  the  GNU
50  *  General Public License for more details.
51  *
52  *  You should have  received a  copy of  the  GNU  General Public License
53  *  distributed  with  FRESCAN;  see file COPYING.   If not,  write to the
54  *  Free Software  Foundation,  59 Temple Place  -  Suite 330,  Boston, MA
55  *  02111-1307, USA.
56  *
57  * As a special exception, including FRESCAN header files in a file,
58  * instantiating FRESCAN generics or templates, or linking other files
59  * with FRESCAN objects to produce an executable application, does not
60  * by itself cause the resulting executable application to be covered
61  * by the GNU General Public License. This exception does not
62  * however invalidate any other reasons why the executable file might be
63  * covered by the GNU Public License.
64  * -----------------------------------------------------------------------
65  *
66  */
67
68 #include <misc/freelist.h>
69 #include <misc/linux_list.h>
70 #include "frescan.h"
71 #include "frescan_bwres_requests.h"
72 #include "frescan_config.h"
73 #include "frescan_debug.h"
74 #include "fosa_mutexes_and_condvars.h"
75
76 static bool is_initialized = false;
77
78 /**
79  * the_requests_pool
80  *
81  * We will use a freelist to allocate and free the requests.
82  *
83  **/
84
85 struct request_t {
86         frescan_request_data_t request_data;
87         struct list_head       request_list;
88         int pool_pos;
89 };
90
91 static fosa_mutex_t requests_mutex;
92 static fosa_cond_t  requests_cond;
93
94 static struct request_t the_requests_pool[FRESCAN_MX_REQUESTS];
95 static freelist_t freelist;
96
97 static struct request_t the_requests_list;
98
99 /**
100  * frescan_requests_init()
101  *
102  * Init the freelist, requests list, cond var and mutex.
103  *
104  **/
105
106 int frescan_requests_init(int max_ceiling)
107 {
108         int err;
109
110         err = fosa_mutex_init(&requests_mutex, max_ceiling);
111         if (err != 0) return err;
112
113         err = fosa_cond_init(&requests_cond);
114         if (err != 0) return err;
115
116         err = freelist_init(&freelist, FRESCAN_MX_REQUESTS);
117         if (err != 0) return err;
118
119         INIT_LIST_HEAD(&the_requests_list.request_list);
120
121         is_initialized = true;
122         return 0;
123 }
124
125 /**
126  * frescan_requests_alloc()
127  *
128  * Allocate a request with the mutex locked
129  *
130  **/
131
132 int frescan_requests_alloc(frescan_request_id_t *req)
133 {
134         int err, pos;
135
136         DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG, "alloc\n");
137
138         if (is_initialized == false) return -1;
139
140         err = fosa_mutex_lock(&requests_mutex);
141         if (err != 0) return err;
142
143                 pos = freelist_alloc(&freelist);
144                 if (pos < 0) goto locked_error;
145
146         err = fosa_mutex_unlock(&requests_mutex);
147         if (err != 0) return err;
148
149         *req = (unsigned int)pos;
150         the_requests_pool[*req].pool_pos = pos;
151
152         return 0;
153
154 locked_error:
155         fosa_mutex_unlock(&requests_mutex);
156         return pos;
157 }
158
159 /**
160  * frescan_requests_free()
161  *
162  * free the request from the pool
163  *
164  **/
165
166 int frescan_requests_free(frescan_request_id_t req)
167 {
168         int err;
169
170         DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG, "free\n");
171
172         if (is_initialized == false) return -1;
173
174         err = fosa_mutex_lock(&requests_mutex);
175         if (err != 0) return err;
176
177                 err = freelist_free(&freelist, req);
178                 if (err != 0) goto locked_error;
179
180         err = fosa_mutex_unlock(&requests_mutex);
181         if (err != 0) return err;
182
183         return 0;
184
185 locked_error:
186         fosa_mutex_unlock(&requests_mutex);
187         return err;
188 }
189
190 /**
191  * frescan_requests_get_data() - gets the data of the request
192  *
193  */
194
195 int frescan_requests_get_data(frescan_request_id_t   req,
196                               frescan_request_data_t **data)
197 {
198         DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG, "request id:%d\n", req);
199         *data = &the_requests_pool[req].request_data;
200         return 0;
201 }
202
203 /**
204  * frescan_requests_enqueue()
205  *
206  **/
207
208 int frescan_requests_enqueue(frescan_request_id_t req)
209 {
210         int err;
211
212         err = fosa_mutex_lock(&requests_mutex);
213         if (err != 0) return err;
214
215         DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG,
216               "is list empty A? %d\n",
217               list_empty(&the_requests_list.request_list));
218
219         list_add_tail(&the_requests_pool[req].request_list,
220                       &the_requests_list.request_list);
221
222         DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG,
223               "is list empty B? %d\n",
224               list_empty(&the_requests_list.request_list));
225
226         err = fosa_cond_signal(&requests_cond);
227         if (err != 0) goto locked_error;
228
229         err = fosa_mutex_unlock(&requests_mutex);
230         if (err != 0) return err;
231
232         return 0;
233
234 locked_error:
235         fosa_mutex_unlock(&requests_mutex);
236         return err;
237 }
238
239 /**
240  * frescan_requestqueue_dequeue()
241  *
242  **/
243
244 int frescan_requests_dequeue(frescan_request_id_t *req)
245 {
246         int err;
247         struct list_head *pos;
248         struct request_t *request = NULL;
249
250         err = fosa_mutex_lock(&requests_mutex);
251         if (err != 0) return err;
252
253         DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG, "entering\n");
254
255         while (list_empty(&the_requests_list.request_list)) {
256                 err = fosa_cond_wait(&requests_cond, &requests_mutex);
257                 if (err != 0) goto locked_error;
258                 DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG, "received signal\n");
259         }
260
261         DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG, "dequeueing a request\n");
262
263         list_for_each(pos, &the_requests_list.request_list) {
264                 request = list_entry(pos, struct request_t, request_list);
265                 break;
266         }
267
268         list_del(&request->request_list);
269
270         *req = request->pool_pos;
271
272         DEBUG(FRESCAN_REQUESTS_ENABLE_DEBUG,
273               "is list empty now? %d\n",
274               list_empty(&the_requests_list.request_list));
275
276         err = fosa_mutex_unlock(&requests_mutex);
277         if (err != 0) return err;
278
279         return 0;
280
281 locked_error:
282         fosa_mutex_unlock(&requests_mutex);
283         return err;
284 }