]> rtime.felk.cvut.cz Git - frescor/fna.git/blob - src_frescan/frescan_servers.c_posix
readme
[frescor/fna.git] / src_frescan / frescan_servers.c_posix
1 /*!
2  * @file frescan_servers.c
3  *
4  * @brief FRESCAN sporadic servers
5  *
6  * @version 0.01
7  *
8  * @date 27-Feb-2008
9  *
10  * @author
11  *      Daniel Sangorrin
12  *
13  * @comments
14  *
15  * This file contains the FRESCAN sporadic servers that allow to isolate
16  * different streams of data by assigning them a budget and replenishment
17  * period.
18  *
19  * @license
20  *
21  * See MaRTE OS license
22  *
23  */
24
25 #include "frescan_servers.h"
26 #include "frescan_servers_replenishments.h" // frescan_replenishments_xxx
27 #include "frescan_debug.h"
28 #include "frescan_data.h"
29 #include <misc/linux_list.h>
30 #include <misc/timespec_operations.h>
31 #include <signal.h>
32 #include <time.h>
33
34 /**
35  * frescan_servers_init() - initialize server structures
36  *
37  * @net: the network instance
38  */
39
40 int frescan_servers_init(frescan_network_t net)
41 {
42         int ret, i;
43
44         DEBUG(FRESCAN_SERVERS_ENABLE_DEBUG, "initializing servers\n");
45
46         ret = freelist_init(&the_servers_pool_freelist[net], FRESCAN_MX_IDS);
47         if (ret != 0) return ret;
48
49         for (i=0; i<FRESCAN_MX_NETWORKS; i++) {
50                 INIT_LIST_HEAD(&the_active_servers[net].servers_list);
51         }
52
53         ret = frescan_replenishments_init(net);
54         if (ret != 0) {
55                 ERROR("could not initialize the replenishments\n");
56                 return -1;
57         }
58
59         return 0;
60 }
61
62 /**
63  * frescan_servers_create() - create a sporadic server
64  *
65  * @net: the network instance
66  * @params: the parameters for the server
67  * @id: the identificator for the server as a return value
68  *
69  */
70
71 int frescan_servers_create(frescan_network_t net,
72                            const frescan_server_params_t *params,
73                            frescan_ss_t *id)
74 {
75         int ret, pos;
76         struct sigevent evp;
77
78         FRESCAN_ACQUIRE_LOCK(&the_networks[net].lock);
79         pos = freelist_alloc(&the_servers_pool_freelist[net]);
80         FRESCAN_RELEASE_LOCK(&the_networks[net].lock);
81
82         if (pos == -1) {
83                 ERROR("could not allocate servers\n");
84                 return -1;
85         }
86
87         *id = (frescan_ss_t)pos;
88
89         the_servers_pool[net][*id].net = net;
90         the_servers_pool[net][*id].id  = *id;
91         the_servers_pool[net][*id].params = *params;
92         the_servers_pool[net][*id].current_budget = params->values.budget;
93         the_servers_pool[net][*id].current_priority = params->prio;
94         the_servers_pool[net][*id].pending_packets = 0;
95
96         // the first act_time is set to the server creation time
97         clock_gettime (CLOCK_MONOTONIC, &the_servers_pool[net][*id].act_time);
98
99         INIT_LIST_HEAD(&the_servers_pool[net][*id].replenishments.repl_list);
100         INIT_LIST_HEAD(&the_servers_pool[net][*id].packet_list.fifo_list);
101
102         // the repl timer sends a signal when it expires with the server id
103         evp.sigev_notify = SIGEV_SIGNAL;
104         evp.sigev_signo  = FRESCAN_REPL_SIGNAL_NUM;
105         evp.sigev_value.sival_int  = (int)*id;
106
107         ret = timer_create (CLOCK_MONOTONIC,
108                             &evp, &the_servers_pool[net][*id].repl_timer);
109         if (ret != 0) {
110                 ERROR("could not create timer\n");
111                 return ret;
112         }
113
114         DEBUG(FRESCAN_SERVERS_ENABLE_DEBUG,
115               "server created, id:%u budget:%u prio:%u\n",
116               *id,
117               the_servers_pool[net][*id].params.values.budget,
118               the_servers_pool[net][*id].params.prio);
119
120         return 0;
121 }
122
123 /**
124  * frescan_servers_update() - update a sporadic server data
125  *
126  * @net: the network instance
127  * @params: the parameters for the server
128  * @id: the identificator for the server
129  *
130  */
131
132 int frescan_servers_update(frescan_network_t net,
133                            const frescan_server_params_t *params,
134                            frescan_ss_t id)
135 {
136         the_servers_pool[net][id].params = *params;
137         return 0;
138 }
139
140 /**
141  * frescan_servers_destroy() - delete a sporadic server
142  *
143  * @net: the network instance
144  * @id: the identificator for the server
145  *
146  */
147
148 int frescan_servers_destroy(frescan_network_t net, frescan_ss_t id)
149 {
150         int ret;
151
152         // TODO: free the replenishment operations and the packets for the
153         // server.
154
155         ret = timer_delete (the_servers_pool[net][id].repl_timer);
156         if (ret != 0) {
157                 ERROR("could not delete timer\n");
158                 return ret;
159         }
160
161         FRESCAN_ACQUIRE_LOCK(&the_networks[net].lock);
162         list_del(&the_servers_pool[net][id].servers_list);
163
164         ret = freelist_free(&the_servers_pool_freelist[net], id);
165         FRESCAN_RELEASE_LOCK(&the_networks[net].lock);
166         if (ret != 0) {
167                 ERROR("could not free server data from pool\n");
168                 return ret;
169         }
170
171         return 0;
172 }
173
174 /**
175  * frescan_servers_get_data() - get a sporadic server data
176  *
177  * @net: the network instance
178  * @params: the parameters of the server
179  * @id: the identificator for the server
180  *
181  */
182
183 int frescan_servers_get_data(frescan_network_t net,
184                              frescan_server_params_t *params,
185                              frescan_ss_t id)
186 {
187         *params = the_servers_pool[net][id].params;
188         return 0;
189 }
190
191 /**
192  * frescan_servers_get_current_budget() - get the current sporadic server budget
193  *
194  * @net: the network instance
195  * @id: the identificator for the server
196  * @current_budget: the current budget of the server
197  *
198  */
199
200 int frescan_servers_get_current_budget(frescan_network_t net,
201                                        frescan_ss_t id,
202                                        frescan_budget_t *current_budget)
203 {
204         *current_budget = the_servers_pool[net][id].current_budget;
205         return 0;
206 }
207
208 /**
209  * frescan_servers_get_highest_prio() - get the server with highest priority
210  *
211  * @net: the network instance
212  * @id: the identificator for the server
213  * @prio: the priority of that server
214  *
215  * For each active server, check the priority.
216  * If "id" is returned with a value of FRESCAN_MX_IDS,
217  * there are no active servers.
218  * NOTE: id=FRESCAN_MX_IDS is the identifier for fixed priority messages
219  * TODO: use a priority queue of active servers
220  *
221  */
222
223 int frescan_servers_get_highest_prio(frescan_network_t net,
224                                      frescan_ss_t *id,
225                                      frescan_prio_t *prio)
226 {
227         frescan_server_data_t *server;
228
229         if (list_empty(&the_active_servers->servers_list)) {
230                 DEBUG(FRESCAN_SERVERS_ENABLE_DEBUG, "server list is empty\n");
231                 *id = FRESCAN_MX_IDS;
232                 return 0;
233         }
234
235         *prio = 0;
236         list_for_each_entry(server, &the_active_servers[net].servers_list,
237                             servers_list) {
238                 if (server->current_priority >= *prio) {
239                         *id = server->id;
240                         *prio = server->current_priority;
241                 }
242         }
243
244         DEBUG(FRESCAN_SERVERS_ENABLE_DEBUG,
245               "highest prio:%u id:%u\n", *prio, *id);
246
247         return 0;
248 }
249
250 /**
251  * frescan_servers_frame_sent() - hook to control the server budget and prio
252  *
253  * @net: the network instance
254  * @id: the identificator for the server
255  *
256  * This function is called when a frame has been effectively sent through the
257  * CAN bus and that frame is associated to a certain server. The function
258  * decreases the capacity of the server and sets the priority to background
259  * in case the budget is exhausted.
260  *
261  * NOTE: the replenishment operation is programmed using the corresponding
262  * function at frescan_servers_replenishments module
263  */
264
265 int frescan_servers_frame_sent(frescan_network_t net,
266                                frescan_ss_t id,
267                                frescan_packet_t *packet)
268 {
269         int ret;
270         struct timespec *repl_time;
271         frescan_server_data_t *server;
272
273         server = &the_servers_pool[net][id];
274
275         DEBUG(FRESCAN_SERVERS_ENABLE_DEBUG,
276               "before.. id:%u, current_budget:%u, current_priority:%u\n",
277               id, server->current_budget, server->current_priority);
278
279         if (server->current_budget > 0) {
280                 server->current_budget--;
281                 if (server->current_budget == 0) {
282                         server->current_priority = FRESCAN_BACKGROUND_PRIO;
283                 }
284
285                 if (smaller_timespec(&packet->timestamp, &server->act_time)) {
286                         DEBUG(FRESCAN_SERVERS_ENABLE_DEBUG, "using act_time\n");
287                         repl_time = &server->act_time;
288                 } else {
289                         repl_time = &packet->timestamp;
290                 }
291
292                 ret = frescan_replenishment_program(net, id, repl_time);
293                 if (ret != 0) return -1;
294         }
295
296         DEBUG(FRESCAN_SERVERS_ENABLE_DEBUG,
297               "after.. id:%u, current_budget:%u, current_priority:%u\n",
298               id, server->current_budget, server->current_priority);
299
300         return 0;
301 }