2 * @file frescan_servers_replenishments.c
4 * @brief the replenishment data and thread for the servers
15 * This module contains the thread that waits for server's replenishment
16 * timer signals and perform the necessary replenishments.
20 * -----------------------------------------------------------------------
21 * Copyright (C) 2006 - 2008 FRESCOR consortium partners:
23 * Universidad de Cantabria, SPAIN
24 * University of York, UK
25 * Scuola Superiore Sant'Anna, ITALY
26 * Kaiserslautern University, GERMANY
27 * Univ. Politécnica Valencia, SPAIN
28 * Czech Technical University in Prague, CZECH REPUBLIC
30 * Thales Communication S.A. FRANCE
31 * Visual Tools S.A. SPAIN
32 * Rapita Systems Ltd UK
35 * See http://www.frescor.org for a link to partners' websites
37 * FRESCOR project (FP6/2005/IST/5-034026) is funded
38 * in part by the European Union Sixth Framework Programme
39 * The European Union is not liable of any use that may be
42 * This file is part of FRESCAN
44 * FRESCAN is free software; you can redistribute it and/or modify
45 * it under the terms of the GNU General Public License as published by
46 * the Free Software Foundation; either version 2, or (at your option)
49 * FRESCAN is distributed in the hope that it will be useful, but
50 * WITHOUT ANY WARRANTY; without even the implied warranty of
51 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
52 * General Public License for more details.
54 * You should have received a copy of the GNU General Public License
55 * distributed with FRESCAN; see file COPYING. If not, write to the
56 * Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
59 * As a special exception, including FRESCAN header files in a file,
60 * instantiating FRESCAN generics or templates, or linking other files
61 * with FRESCAN objects to produce an executable application, does not
62 * by itself cause the resulting executable application to be covered
63 * by the GNU General Public License. This exception does not
64 * however invalidate any other reasons why the executable file might be
65 * covered by the GNU Public License.
66 * -----------------------------------------------------------------------
70 #include <time.h> // clock_gettime
71 #include <assert.h> // assert
73 #include <misc/freelist.h> // freelist_t
74 #include <misc/linux_list.h> // list_add_tail
75 #include <misc/timespec_operations.h>
77 #include "frescan_servers_replenishments.h"
78 #include "frescan_config.h" // FRESCAN_MX_REPL_OPS
79 #include "frescan_debug.h" // ERROR
80 #include "frescan_data.h" // frescan_repl_op_t
81 #include "fosa_threads_and_signals.h" // fosa_thread_attr_init...
83 #if (FRESCAN_MEASURE_REPL_TH || FRESCAN_MEASURE_REPL_PROGRAM)
84 #include <misc/time_measurement_posix.h>
85 #include <misc/logger.h>
86 static time_measure_id_t measure_id;
90 * the_repl_op_pool - pool of replenishment operations
92 * We have a pool of replenishment operation structures and an associated
93 * freelist where we can get/put replenishment operations in O(1) time
95 * @the_repl_op_pool: array with the replenishment operations allocated
96 * @the_repl_op_pool_freelist: freelist for the_repl_op_pool
97 * @frescan_repl_op_init: initializes the freelist
98 * @frescan_repl_op_alloc: get a free replenishment operation structure
99 * @frescan_repl_op_free: free a replenishment operation structure
103 static frescan_repl_op_t the_repl_op_pool[FRESCAN_MX_REPL_OPS];
104 static freelist_t the_repl_op_pool_freelist;
106 static int frescan_repl_op_init()
108 return freelist_init(&the_repl_op_pool_freelist, FRESCAN_MX_REPL_OPS);
111 frescan_repl_op_t *frescan_repl_op_alloc()
115 pos = freelist_alloc(&the_repl_op_pool_freelist);
117 ERROR("could not allocate repl op\n");
120 the_repl_op_pool[pos].pool_pos = pos; // to know how to free it
121 return &the_repl_op_pool[pos];
124 int frescan_repl_op_free(frescan_repl_op_t *repl_op)
126 return freelist_free(&the_repl_op_pool_freelist, repl_op->pool_pos);
130 * frescan_repl_thread - the thread that executes the replenishments
133 static void *frescan_repl_thread(void *arg)
139 frescan_network_t net;
140 struct list_head *pos;
141 frescan_repl_op_t *repl = NULL;
142 frescan_server_data_t *server;
143 struct itimerspec timerdata;
145 net = (frescan_network_t)(uint32_t)arg;
146 timerdata.it_interval.tv_sec = 0;
147 timerdata.it_interval.tv_nsec = 0;
150 sigaddset(&set, FRESCAN_REPL_SIGNAL_NUM);
153 #if FRESCAN_MEASURE_REPL_TH
154 ret = time_measure_posix_begin(measure_id);
157 ret = sigwaitinfo(&set, &siginfo);
159 ERROR("sigwaitinfo failed\n");
163 if (siginfo.si_signo != FRESCAN_REPL_SIGNAL_NUM) continue;
165 DEBUG(FRESCAN_REPLENSH_ENABLE_DEBUG,
166 "net:%u signal:%d code:%d value(server_id):%d\n",
168 siginfo.si_signo, // FRESCAN_REPL_SIGNAL_NUM
169 siginfo.si_code, // SI_TIMER
170 siginfo.si_value.sival_int); // the server id
172 id = siginfo.si_value.sival_int;
173 server = &the_servers_pool[net][id];
175 DEBUG(FRESCAN_REPLENSH_ENABLE_DEBUG,
176 "id:%u, current_budget:%u, budget:%u, current_prio:%u\n",
178 server->current_budget,
179 server->params.values.budget,
180 server->current_priority);
182 server->current_budget++;
184 if (server->current_priority == FRESCAN_BACKGROUND_PRIO) {
185 server->current_priority = server->params.prio;
186 if (!list_empty(&server->packet_list.fifo_list)) {
187 clock_gettime (CLOCK_MONOTONIC,
192 DEBUG(FRESCAN_REPLENSH_ENABLE_DEBUG,
193 "now... current_budget:%u, current_prio:%u\n",
194 server->current_budget,
195 server->current_priority);
197 // delete the replenishment of this call
198 list_for_each(pos, &server->replenishments.repl_list) {
199 repl = list_entry(pos, frescan_repl_op_t, repl_list);
203 list_del(&repl->repl_list);
205 ret = frescan_repl_op_free(repl);
207 ERROR("could not free replenishment op\n");
211 // check if there are pending replenishments
212 if (list_empty(&server->replenishments.repl_list)) continue;
214 list_for_each(pos, &server->replenishments.repl_list) {
215 repl = list_entry(pos, frescan_repl_op_t, repl_list);
219 timerdata.it_value = repl->when;
221 DEBUG(FRESCAN_REPLENSH_ENABLE_DEBUG,
222 "set timer to (%d, %d)\n",
223 repl->when.tv_sec, repl->when.tv_nsec);
225 ret = timer_settime(server->repl_timer,
226 TIMER_ABSTIME, &timerdata, NULL);
228 ERROR("could not set replenishment timer\n");
231 #if FRESCAN_MEASURE_REPL_TH
232 ret = time_measure_posix_end(measure_id, "thread");
235 while (logger_manual_call() > 0);
243 * frescan_replenishments_init - init the replenishment structures and thread
245 * @net: the network instance
247 * Initialize the repl_op pool, set the mask for the timer signals and create
248 * the thread that will await for those signals and replenish the appropiate
252 int frescan_replenishments_init(frescan_network_t net)
255 fosa_signal_t signal_set[1];
256 fosa_thread_attr_t attr;
258 ret = frescan_repl_op_init();
260 ERROR("could not init repl_op pool\n");
264 signal_set[0] = FRESCAN_REPL_SIGNAL_NUM;
266 ret = fosa_set_accepted_signals(signal_set, 1);
268 ERROR("could not set the repl signal\n");
272 // create the replenishment thread
273 #if (FRESCAN_MEASURE_REPL_TH || FRESCAN_MEASURE_REPL_PROGRAM)
274 ret = logger_init(LOG_ETHERNET);
277 ret = time_measure_posix_create("repl",
278 CLOCK_THREAD_CPUTIME_ID,
283 ret = fosa_thread_attr_init(&attr);
285 ERROR("could not init thread attributes\n");
289 ret = fosa_thread_attr_set_prio(&attr, FRESCAN_REPL_THREAD_PRIO);
291 ERROR("could not set repl thread prio %d\n",
292 FRESCAN_REPL_THREAD_PRIO);
296 ret = fosa_thread_create(&the_networks[net].repl_thread_id,
299 (void *)(uint32_t)net);
301 ERROR("could not create the replenishment thread\n");
305 ret = fosa_thread_attr_destroy(&attr);
307 ERROR("could not destroy thread attributes\n");
315 * frescan_replenishment_program - set a replenishment operation
317 * @net: the network instance
321 int frescan_replenishment_program(frescan_network_t net,
323 const struct timespec *timestamp)
326 frescan_repl_op_t *repl;
328 struct itimerspec timerdata;
329 frescan_server_data_t *server;
331 #if FRESCAN_MEASURE_REPL_PROGRAM
332 ret = time_measure_posix_begin(measure_id);
336 server = &the_servers_pool[net][ss];
338 repl = frescan_repl_op_alloc();
340 ERROR("could not allocate a repl operation\n");
344 repl->when = *timestamp;
345 incr_timespec (&repl->when, &server->params.values.period);
348 empty = list_empty(&server->replenishments.repl_list);
349 DEBUG(FRESCAN_REPLENSH_ENABLE_DEBUG, "ss:%u, empty:%u\n", ss, empty);
351 list_add_tail(&repl->repl_list,
352 &server->replenishments.repl_list);
355 timerdata.it_interval.tv_sec = 0;
356 timerdata.it_interval.tv_nsec = 0;
357 timerdata.it_value = repl->when;
359 DEBUG(FRESCAN_REPLENSH_ENABLE_DEBUG,
360 "set timer to %d sec, %d nsec\n",
361 repl->when.tv_sec, repl->when.tv_nsec);
363 ret = timer_settime(server->repl_timer,
364 TIMER_ABSTIME, &timerdata, NULL);
366 ERROR("could not set the replenishment timer\n");
371 #if FRESCAN_MEASURE_REPL_PROGRAM
372 ret = time_measure_posix_end(measure_id, "program");
375 while (logger_manual_call() > 0);