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 - 2009 by the FRESCOR consortium:
23 // Universidad de Cantabria, SPAIN
24 // University of York, UK
25 // Scuola Superiore Sant'Anna, ITALY
26 // Kaiserslautern University, GERMANY
27 // Univ. Politecnica 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
37 // The 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
43 // based on previous work (FSF) done in the FIRST project
45 // Copyright (C) 2005 Mälardalen University, SWEDEN
46 // Scuola Superiore S.Anna, ITALY
47 // Universidad de Cantabria, SPAIN
48 // University of York, UK
50 // This file is part of FNA (Frescor Network Adaptation)
52 // FNA is free software; you can redistribute it and/or modify it
53 // under terms of the GNU General Public License as published by the
54 // Free Software Foundation; either version 2, or (at your option) any
55 // later version. FNA is distributed in the hope that it will be
56 // useful, but WITHOUT ANY WARRANTY; without even the implied warranty
57 // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
58 // General Public License for more details. You should have received a
59 // copy of the GNU General Public License along with FNA; see file
60 // COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,
61 // Cambridge, MA 02139, USA.
63 // As a special exception, including FNA header files in a file,
64 // instantiating FNA generics or templates, or linking other files
65 // with FNA objects to produce an executable application, does not
66 // by itself cause the resulting executable application to be covered
67 // by the GNU General Public License. This exception does not
68 // however invalidate any other reasons why the executable file might be
69 // covered by the GNU Public License.
70 // -----------------------------------------------------------------------
74 #include <time.h> // clock_gettime
75 #include <assert.h> // assert
77 #include <misc/freelist.h> // freelist_t
78 #include <misc/linux_list.h> // list_add_tail
80 #include "frescan_servers_replenishments.h"
81 #include "frescan_config.h" // FRESCAN_MX_REPL_OPS
82 #include "frescan_debug.h" // FRESCAN_ERROR
83 #include "frescan_data.h" // frescan_repl_op_t
84 #include "fosa.h" // fosa_thread_attr_init, smaller_timespec, incr_timespec
86 #if (FRESCAN_MEASURE_REPL_TH || FRESCAN_MEASURE_REPL_PROGRAM)
87 #include <misc/time_measurement_posix.h>
88 #include <misc/logger.h>
89 static time_measure_id_t measure_id;
93 * the_repl_op_pool - pool of replenishment operations
95 * We have a pool of replenishment operation structures and an associated
96 * freelist where we can get/put replenishment operations in O(1) time
98 * @the_repl_op_pool: array with the replenishment operations allocated
99 * @the_repl_op_pool_freelist: freelist for the_repl_op_pool
100 * @frescan_repl_op_init: initializes the freelist
101 * @frescan_repl_op_alloc: get a free replenishment operation structure
102 * @frescan_repl_op_free: free a replenishment operation structure
106 static frescan_repl_op_t the_repl_op_pool[FRESCAN_MX_REPL_OPS];
107 static freelist_t the_repl_op_pool_freelist;
109 static int frescan_repl_op_init()
111 return freelist_init(&the_repl_op_pool_freelist, FRESCAN_MX_REPL_OPS);
114 frescan_repl_op_t *frescan_repl_op_alloc()
118 pos = freelist_alloc(&the_repl_op_pool_freelist);
120 FRESCAN_ERROR("could not allocate repl op\n");
123 the_repl_op_pool[pos].pool_pos = pos; // to know how to free it
124 return &the_repl_op_pool[pos];
127 int frescan_repl_op_free(frescan_repl_op_t *repl_op)
129 return freelist_free(&the_repl_op_pool_freelist, repl_op->pool_pos);
133 * frescan_repl_thread - the thread that executes the replenishments
136 static void *frescan_repl_thread(void *arg)
142 frescan_network_t net;
143 frescan_ss_data_t *server;
144 struct itimerspec timerdata;
146 net = (frescan_network_t)(uint32_t)arg;
147 timerdata.it_interval.tv_sec = 0;
148 timerdata.it_interval.tv_nsec = 0;
151 sigaddset(&set, FRESCAN_REPL_SIGNAL_NUM);
154 #if FRESCAN_MEASURE_REPL_TH
155 ret = time_measure_posix_begin(measure_id);
158 ret = sigwaitinfo(&set, &siginfo);
161 if (siginfo.si_signo != FRESCAN_REPL_SIGNAL_NUM) continue;
163 DEBUG(FRESCAN_REPLENSH_ENABLE_DEBUG,
164 "net:%u signal:%d code:%d value(server_id):%d\n",
166 siginfo.si_signo, // FRESCAN_REPL_SIGNAL_NUM
167 siginfo.si_code, // SI_TIMER
168 siginfo.si_value.sival_int); // the server id
170 id = siginfo.si_value.sival_int;
171 server = &frescan_data[net].ss_data[id];
173 DEBUG(FRESCAN_REPLENSH_ENABLE_DEBUG,
174 "id:%u current_prio:%u\n", id, server->current_priority);
176 server->current_priority = server->committed_params.prio;
178 if (!list_empty(&server->packet_list.fifo_list)) {
179 clock_gettime (CLOCK_MONOTONIC, &server->act_time);
181 #if FRESCAN_MEASURE_REPL_TH
182 ret = time_measure_posix_end(measure_id, "thread");
185 while (logger_manual_call() > 0);
193 * frescan_replenishments_init - init the replenishment structures and thread
195 * @net: the network instance
197 * Initialize the repl_op pool, set the mask for the timer signals and create
198 * the thread that will await for those signals and replenish the appropiate
202 int frescan_replenishments_init(frescan_network_t net)
205 fosa_signal_t signal_set[1];
206 fosa_thread_attr_t attr;
208 ret = frescan_repl_op_init();
210 FRESCAN_ERROR("could not init repl_op pool\n");
214 signal_set[0] = FRESCAN_REPL_SIGNAL_NUM;
216 ret = fosa_set_accepted_signals(signal_set, 1);
218 FRESCAN_ERROR("could not set the repl signal\n");
222 // create the replenishment thread
223 #if (FRESCAN_MEASURE_REPL_TH || FRESCAN_MEASURE_REPL_PROGRAM)
224 ret = logger_init(LOG_ETHERNET);
227 ret = time_measure_posix_create("repl",
228 CLOCK_THREAD_CPUTIME_ID,
233 ret = fosa_thread_attr_init(&attr);
235 FRESCAN_ERROR("could not init thread attributes\n");
239 ret = fosa_thread_attr_set_prio(&attr, FRESCAN_REPL_THREAD_PRIO);
241 FRESCAN_ERROR("could not set repl thread prio %d\n",
242 FRESCAN_REPL_THREAD_PRIO);
246 ret = fosa_thread_create(&frescan_data[net].repl_thread_id,
249 (void *)(uint32_t)net);
251 FRESCAN_ERROR("could not create the replenishment thread\n");
255 ret = fosa_thread_attr_destroy(&attr);
257 FRESCAN_ERROR("could not destroy thread attributes\n");
265 * frescan_replenishment_program - set a replenishment operation
267 * @net: the network instance
271 int frescan_replenishment_program(frescan_network_t net,
273 const struct timespec *timestamp)
276 frescan_repl_op_t *repl = NULL;
277 struct itimerspec timerdata;
278 frescan_ss_data_t *server;
279 struct list_head *pos;
282 #if FRESCAN_MEASURE_REPL_PROGRAM
283 ret = time_measure_posix_begin(measure_id);
287 server = &frescan_data[net].ss_data[id];
290 list_for_each(pos, &server->replenishments.repl_list) {
291 repl = list_entry(pos, frescan_repl_op_t, repl_list);
294 list_del(&repl->repl_list);
296 // move to tail with new repl value
297 repl->when = *timestamp;
298 incr_timespec(repl->when, server->committed_params.period);
301 list_add_tail(&repl->repl_list,
302 &server->replenishments.repl_list);
304 // check the new head
305 list_for_each(pos, &server->replenishments.repl_list) {
306 repl = list_entry(pos, frescan_repl_op_t, repl_list);
310 clock_gettime (CLOCK_MONOTONIC, &now);
312 if (smaller_timespec(now, repl->when)) {
313 server->current_priority = FRESCAN_BACKGROUND_PRIO;
315 timerdata.it_interval.tv_sec = 0;
316 timerdata.it_interval.tv_nsec = 0;
317 timerdata.it_value = repl->when;
319 DEBUG(FRESCAN_REPLENSH_ENABLE_DEBUG,
320 "set timer to %d sec, %d nsec\n",
321 repl->when.tv_sec, repl->when.tv_nsec);
323 ret = timer_settime(server->repl_timer,
324 TIMER_ABSTIME, &timerdata, NULL);
326 FRESCAN_ERROR("could not set the replenishment timer\n");
331 #if FRESCAN_MEASURE_REPL_PROGRAM
332 ret = time_measure_posix_end(measure_id, "program");
335 while (logger_manual_call() > 0);