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 * See MaRTE OS license
24 #include <time.h> // clock_gettime
26 #include <misc/freelist.h> // freelist_t
27 #include <misc/linux_list.h> // list_add_tail
28 #include <misc/timespec_operations.h>
30 #include "frescan_servers_replenishments.h"
31 #include "frescan_config.h" // FRESCAN_MX_REPL_OPS
32 #include "frescan_debug.h" // ERROR
33 #include "frescan_data.h" // frescan_repl_op_t
36 * the_repl_op_pool - pool of replenishment operations
38 * We have a pool of replenishment operation structures and an associated
39 * freelist where we can get/put replenishment operations in O(1) time
41 * @the_repl_op_pool: array with the replenishment operations allocated
42 * @the_repl_op_pool_freelist: freelist for the_repl_op_pool
43 * @frescan_repl_op_init: initializes the freelist
44 * @frescan_repl_op_alloc: get a free replenishment operation structure
45 * @frescan_repl_op_free: free a replenishment operation structure
49 static frescan_repl_op_t the_repl_op_pool[FRESCAN_MX_REPL_OPS];
50 static freelist_t the_repl_op_pool_freelist;
52 static int frescan_repl_op_init()
54 return freelist_init(&the_repl_op_pool_freelist, FRESCAN_MX_REPL_OPS);
57 static frescan_repl_op_t *frescan_repl_op_alloc()
61 pos = freelist_alloc(&the_repl_op_pool_freelist);
63 ERROR("could not allocate repl op\n");
66 the_repl_op_pool[pos].pool_pos = pos; // to know how to free it
67 return &the_repl_op_pool[pos];
70 static int frescan_repl_op_free(frescan_repl_op_t *repl_op)
72 return freelist_free(&the_repl_op_pool_freelist, repl_op->pool_pos);
76 * frescan_repl_thread - the thread that executes the replenishments
79 static void *frescan_repl_thread(void *arg)
85 frescan_network_t net;
86 struct list_head *pos;
87 frescan_repl_op_t *repl;
88 frescan_server_data_t *server;
89 struct itimerspec timerdata;
91 net = (frescan_network_t)(uint32_t)arg;
92 timerdata.it_interval.tv_sec = 0;
93 timerdata.it_interval.tv_nsec = 0;
96 sigaddset(&set, FRESCAN_REPL_SIGNAL_NUM);
99 ret = sigwaitinfo(&set, &siginfo);
101 ERROR("sigwaitinfo failed\n");
105 if (siginfo.si_signo != FRESCAN_REPL_SIGNAL_NUM) continue;
107 DEBUG(FRESCAN_REPL_ENABLE_DEBUG,
108 "net:%u signal:%d code:%d value(server_id):%d\n",
110 siginfo.si_signo, // FRESCAN_REPL_SIGNAL_NUM
111 siginfo.si_code, // SI_TIMER
112 siginfo.si_value.sival_int); // the server id
114 id = siginfo.si_value.sival_int;
115 server = &the_servers_pool[net][id];
117 DEBUG(FRESCAN_REPL_ENABLE_DEBUG,
118 "id:%u, current_budget:%u, budget:%u, current_prio:%u\n",
120 server->current_budget,
121 server->params.budget,
122 server->current_priority);
124 server->current_budget++;
126 if (server->current_priority == FRESCAN_BACKGROUND_PRIO) {
127 server->current_priority = server->params.prio;
130 DEBUG(FRESCAN_REPL_ENABLE_DEBUG,
131 "now... current_budget:%u, current_prio:%u\n",
132 server->current_budget,
133 server->current_priority);
135 // delete the replenishment of this call
136 list_for_each(pos, &server->replenishments.repl_list) {
137 repl = list_entry(pos, frescan_repl_op_t, repl_list);
141 list_del(&repl->repl_list);
143 ret = frescan_repl_op_free(repl);
145 ERROR("could not free replenishment op\n");
149 // check if there are pending replenishments
150 if (list_empty(&server->replenishments.repl_list)) continue;
152 list_for_each(pos, &server->replenishments.repl_list) {
153 repl = list_entry(pos, frescan_repl_op_t, repl_list);
157 timerdata.it_value = repl->when;
159 DEBUG(FRESCAN_REPL_ENABLE_DEBUG,
160 "set timer to %d sec, %d nsec\n",
161 repl->when.tv_sec, repl->when.tv_nsec);
163 ret = timer_settime(server->repl_timer,
164 TIMER_ABSTIME, &timerdata, NULL);
166 ERROR("could not set replenishment timer\n");
175 * frescan_replenishments_init - init the replenishment structures and thread
177 * @net: the network instance
179 * Initialize the repl_op pool, set the mask for the timer signals and create
180 * the thread that will await for those signals and replenish the appropiate
184 int frescan_replenishments_init(frescan_network_t net)
188 struct sigaction action;
190 ret = frescan_repl_op_init();
192 ERROR("could not init repl_op pool\n");
197 sigaddset(&set, FRESCAN_REPL_SIGNAL_NUM);
199 ret = pthread_sigmask(SIG_BLOCK, &set, NULL);
201 ERROR("could not put the signal mask for replenishments\n");
205 // the following is unnecesary in MaRTE OS because all signals are RT
206 action.sa_handler = SIG_DFL;
207 sigemptyset(&action.sa_mask);
208 action.sa_flags = SA_SIGINFO;
209 ret = sigaction (FRESCAN_REPL_SIGNAL_NUM, &action, NULL);
211 ERROR("could not set action for the repl signal\n");
215 // TODO: set the pthread attributes
216 ret = pthread_create(&the_networks[net].repl_thread_id,
219 (void *)(uint32_t)net);
221 ERROR("could not create the replenishment thread\n");
229 * frescan_replenishment_program - set a replenishment operation
231 * @net: the network instance
235 int frescan_replenishment_program(frescan_network_t net,
239 frescan_repl_op_t *repl;
241 struct itimerspec timerdata;
242 frescan_server_data_t *server;
244 server = &the_servers_pool[net][ss];
246 if (server->current_priority == FRESCAN_BACKGROUND_PRIO) {
247 DEBUG(FRESCAN_REPL_ENABLE_DEBUG, "ss in background\n");
251 repl = frescan_repl_op_alloc();
253 ERROR("could not allocate a repl operation\n");
257 clock_gettime (CLOCK_MONOTONIC, &repl->when);
258 incr_timespec (&repl->when, &server->params.period);
261 empty = list_empty(&server->replenishments.repl_list);
262 DEBUG(FRESCAN_REPL_ENABLE_DEBUG, "ss:%u, empty:%u\n", ss, empty);
264 list_add_tail(&repl->repl_list,
265 &server->replenishments.repl_list);
268 timerdata.it_interval.tv_sec = 0;
269 timerdata.it_interval.tv_nsec = 0;
270 timerdata.it_value = repl->when;
272 DEBUG(FRESCAN_REPL_ENABLE_DEBUG,
273 "set timer to %d sec, %d nsec\n",
274 repl->when.tv_sec, repl->when.tv_nsec);
276 ret = timer_settime(server->repl_timer,
277 TIMER_ABSTIME, &timerdata, NULL);
279 ERROR("could not set the replenishment timer\n");