2 * @file frescan_bwres_threads.c
4 * @brief FRESCAN bandwidth reservation layer: negotiation threads
6 * This module contains the acceptor threads and the master thread for local
7 * negotiations, with functions to create them.
13 * @author Daniel Sangorrin <daniel.sangorrin@unican.es>
17 //----------------------------------------------------------------------
18 // Copyright (C) 2006 - 2009 by the FRESCOR consortium:
20 // Universidad de Cantabria, SPAIN
21 // University of York, UK
22 // Scuola Superiore Sant'Anna, ITALY
23 // Kaiserslautern University, GERMANY
24 // Univ. Politecnica Valencia, SPAIN
25 // Czech Technical University in Prague, CZECH REPUBLIC
27 // Thales Communication S.A. FRANCE
28 // Visual Tools S.A. SPAIN
29 // Rapita Systems Ltd UK
32 // See http://www.frescor.org
34 // The FRESCOR project (FP6/2005/IST/5-034026) is funded
35 // in part by the European Union Sixth Framework Programme
36 // The European Union is not liable of any use that may be
40 // based on previous work (FSF) done in the FIRST project
42 // Copyright (C) 2005 Mälardalen University, SWEDEN
43 // Scuola Superiore S.Anna, ITALY
44 // Universidad de Cantabria, SPAIN
45 // University of York, UK
47 // This file is part of FNA (Frescor Network Adaptation)
49 // FNA is free software; you can redistribute it and/or modify it
50 // under terms of the GNU General Public License as published by the
51 // Free Software Foundation; either version 2, or (at your option) any
52 // later version. FNA is distributed in the hope that it will be
53 // useful, but WITHOUT ANY WARRANTY; without even the implied warranty
54 // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
55 // General Public License for more details. You should have received a
56 // copy of the GNU General Public License along with FNA; see file
57 // COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,
58 // Cambridge, MA 02139, USA.
60 // As a special exception, including FNA header files in a file,
61 // instantiating FNA generics or templates, or linking other files
62 // with FNA objects to produce an executable application, does not
63 // by itself cause the resulting executable application to be covered
64 // by the GNU General Public License. This exception does not
65 // however invalidate any other reasons why the executable file might be
66 // covered by the GNU Public License.
67 // -----------------------------------------------------------------------
72 #include "fosa_threads_and_signals.h" // fosa_thread_attr_init...
73 #include "frescan_bwres_threads.h"
74 #include "frescan_bwres_messages.h"
75 #include "frescan_bwres_requests.h"
76 #include "frescan_bwres_robjs.h"
77 #include "frescan_bwres_analysis.h"
78 #include "frescan_bwres_mode_change.h"
79 #include "frescan_config.h"
80 #include "frescan_debug.h"
81 #include "frescan_data.h"
82 #include "frescan_servers.h"
84 static void *frescan_manager_thread(void *arg);
85 static void *frescan_acceptor_thread(void *arg);
87 static void frescan_manager_gn_prepare_scenario
88 (frescan_bwres_sa_scenario_t *scenario,
89 frescan_bwres_request_data_t *req_data);
91 static void frescan_manager_gn_restore_scenario
92 (frescan_bwres_sa_scenario_t *scenario,
93 frescan_bwres_request_data_t *req_data);
95 static void frescan_manager_req_gn(frescan_bwres_request_data_t *req_data);
96 static void frescan_manager_rep_gn(frescan_bwres_request_data_t *req_data);
97 static void frescan_manager_req_mc(frescan_bwres_request_data_t *req_data);
100 * frescan_manager_thread_create()
102 * This call creates the manager thread at each node which will be waiting
103 * in a request queue for LOCAL or EXTERNAL requests.
106 int frescan_manager_thread_create(frescan_network_t net)
109 fosa_thread_attr_t attr;
111 ret = fosa_thread_attr_init(&attr);
112 if (ret != 0) return ret;
114 ret = fosa_thread_attr_set_prio(&attr, FRESCAN_BWRES_NEG_THREAD_PRIO);
115 if (ret != 0) return ret;
117 ret = fosa_thread_create(&frescan_data[net].manager_thread_id,
119 frescan_manager_thread,
120 (void *)(uint32_t)net);
121 if (ret != 0) return ret;
123 ret = fosa_thread_attr_destroy(&attr);
124 if (ret != 0) return ret;
130 * frescan_acceptor_thread_create()
132 * This call creates the acceptor thread which will be waiting negotiation
133 * messages from the network and converting them into requests.
136 int frescan_acceptor_thread_create(frescan_network_t net)
139 fosa_thread_attr_t attr;
141 ret = fosa_thread_attr_init(&attr);
142 if (ret != 0) return ret;
144 ret = fosa_thread_attr_set_prio(&attr, FRESCAN_BWRES_ACCEPTOR_PRIO);
145 if (ret != 0) return ret;
147 ret = fosa_thread_create(&frescan_data[net].acceptor_thread_id,
149 frescan_acceptor_thread,
150 (void *)(uint32_t)net);
151 if (ret != 0) return ret;
153 ret = fosa_thread_attr_destroy(&attr);
154 if (ret != 0) return ret;
160 * frescan_manager_thread
163 static void *frescan_manager_thread(void *arg)
166 frescan_bwres_request_id_t req;
167 frescan_bwres_request_data_t *req_data;
168 frescan_network_t net = (uint32_t)arg;
170 DEBUG(FRESCAN_BWRES_MANAGER_ENABLE_DEBUG, "manager thread starts\n");
173 DEBUG(FRESCAN_BWRES_MANAGER_ENABLE_DEBUG, "wait for a request\n");
175 ret = frescan_bwres_requests_dequeue(&req);
178 ret = frescan_bwres_requests_get_data(req, &req_data);
181 switch(req_data->type) {
182 case FRESCAN_BWRES_REQ_GN:
183 frescan_manager_req_gn(req_data);
185 case FRESCAN_BWRES_REP_GN:
186 frescan_manager_rep_gn(req_data);
188 case FRESCAN_BWRES_REQ_MC:
189 frescan_manager_req_mc(req_data);
191 case FRESCAN_BWRES_REQ_RES:
192 case FRESCAN_BWRES_REQ_RES_GET:
193 case FRESCAN_BWRES_REP_RES_GET:
194 case FRESCAN_BWRES_REQ_RES_SET:
195 case FRESCAN_BWRES_REQ_RES_COMMIT:
196 case FRESCAN_BWRES_REQ_RES_CANCEL:
198 FRESCAN_ERROR("request type not supported\n");
202 if(req_data->request_node != frescan_data[net].local_node) {
203 ret = frescan_bwres_requests_free(req);
210 * frescan_acceptor_thread()
213 static void *frescan_acceptor_thread(void *arg)
216 frescan_bwres_request_id_t req;
217 frescan_network_t net = (uint32_t)arg;
219 DEBUG(FRESCAN_BWRES_ACCEPTOR_ENABLE_DEBUG, "acceptor thread starts\n");
222 ret = frescan_messages_recv_request(net, &req);
225 ret = frescan_bwres_requests_enqueue(req);
233 * frescan_manager_req_gn
236 static void frescan_manager_req_gn(frescan_bwres_request_data_t *req_data)
241 frescan_bwres_sa_scenario_t *scenario;
243 frescan_server_params_t server_params;
244 frescan_bwres_vres_t *vres;
246 me = frescan_data[req_data->net].local_node;
248 if (me != FRESCAN_BWRES_MASTER_NODE) {
249 DEBUG(FRESCAN_BWRES_MANAGER_ENABLE_DEBUG,
250 "send gn req to master\n");
251 ret = frescan_messages_send_request(req_data);
256 scenario = &frescan_data[req_data->net].scenario;
258 DEBUG(FRESCAN_BWRES_MANAGER_ENABLE_DEBUG, "prepare new scenario\n");
259 frescan_manager_gn_prepare_scenario(scenario, req_data);
261 DEBUG(FRESCAN_BWRES_MANAGER_ENABLE_DEBUG, "perform sched analysis\n");
262 ret = frescan_bwres_sa_sched_test(scenario, &accepted);
266 DEBUG(FRESCAN_BWRES_MANAGER_ENABLE_DEBUG, "ACCEPTED!\n");
267 req_data->return_value = FRESCAN_BWRES_REQ_ACCEPTED;
269 DEBUG(FRESCAN_BWRES_MANAGER_ENABLE_DEBUG,
270 "spare capacity and mode change\n");
272 ret = frescan_bwres_sa_spare_capacity(scenario);
275 ret = frescan_bwres_mode_change_protocol(req_data);
278 DEBUG(FRESCAN_BWRES_MANAGER_ENABLE_DEBUG, "FAILED!\n");
279 req_data->return_value = FRESCAN_BWRES_REQ_NOT_ACCEPTED;
280 frescan_manager_gn_restore_scenario(scenario, req_data);
283 if (req_data->request_node != me) {
284 DEBUG(FRESCAN_BWRES_MANAGER_ENABLE_DEBUG, "send reply\n");
285 req_data->type = FRESCAN_BWRES_REP_GN;
287 ret = frescan_messages_send_request(req_data);
292 if (req_data->return_value == FRESCAN_BWRES_REQ_ACCEPTED) {
293 // create servers for new contracts
294 req_data->ss_new->size = req_data->contracts_to_neg->size;
295 for(i=0; i<req_data->ss_new->size; i++) {
296 vres = &frescan_data[req_data->net].scenario.
298 [req_data->ss_new->ss[i]];
300 server_params.budget = frsh_rel_time_to_usec(
301 frsh_sa_time_to_rel_time(vres->old_c)) /
302 FRESCAN_FRAME_TX_TIME_US;
304 server_params.period = frsh_sa_time_to_rel_time
306 server_params.prio = vres->old_p;
309 ret = frescan_servers_create(req_data->net,
313 assert (req_data->ss_new->ss[i] == ss);
317 DEBUG(FRESCAN_BWRES_MANAGER_ENABLE_DEBUG, "signal robj\n");
318 ret = frescan_bwres_robjs_signal(req_data->robj);
323 * frescan_manager_gn_prepare_scenario
326 static void frescan_manager_gn_prepare_scenario
327 (frescan_bwres_sa_scenario_t *scenario,
328 frescan_bwres_request_data_t *req_data)
333 for(i=0; i<req_data->contracts_to_neg->size; i++) {
334 ret = freelist_alloc(&frescan_data[req_data->net].scenario.
335 ss_id_freelist[req_data->request_node]);
338 req_data->ss_new->ss[i] = (frescan_ss_t)ret;
340 DEBUG(FRESCAN_BWRES_MANAGER_ENABLE_DEBUG,
341 "prealloc net:%d node:%d ss_new->ss[%d]:%d\n",
342 req_data->net, req_data->request_node,
343 i, req_data->ss_new->ss[i]);
345 ret = frescan_bwres_sa_add_contract
347 req_data->ss_new->ss[i],
348 req_data->request_node,
349 &req_data->contracts_to_neg->contracts[i]);
353 req_data->ss_new->size = req_data->contracts_to_neg->size;
356 scenario->backup_contracts_to_reneg.size =
357 req_data->contracts_to_reneg->size;
359 for(i=0; i<req_data->contracts_to_reneg->size; i++) {
360 ret = frescan_bwres_sa_update_contract
362 req_data->ss_to_reneg->ss[i],
363 req_data->request_node,
364 &req_data->contracts_to_reneg->contracts[i],
365 &scenario->backup_contracts_to_reneg.contracts[i]);
370 scenario->backup_contracts_to_cancel.size =
371 req_data->ss_to_cancel->size;
373 for(i=0; i<req_data->ss_to_cancel->size; i++) {
374 ret = frescan_bwres_sa_remove_contract
376 req_data->ss_to_cancel->ss[i],
377 req_data->request_node,
378 &scenario->backup_contracts_to_cancel.contracts[i]);
384 * frescan_manager_gn_restore_scenario
387 static void frescan_manager_gn_restore_scenario
388 (frescan_bwres_sa_scenario_t *scenario,
389 frescan_bwres_request_data_t *req_data)
394 for(i=0; i<req_data->contracts_to_neg->size; i++) {
395 ret = frescan_bwres_sa_remove_contract
397 req_data->ss_new->ss[i],
398 req_data->request_node,
402 ret = freelist_free(&frescan_data[req_data->net].scenario.
403 ss_id_freelist[req_data->request_node],
404 req_data->ss_new->ss[i]);
409 for(i=0; i<req_data->contracts_to_reneg->size; i++) {
410 ret = frescan_bwres_sa_update_contract
412 req_data->ss_to_reneg->ss[i],
413 req_data->request_node,
414 &scenario->backup_contracts_to_reneg.contracts[i],
420 for(i=0; i<req_data->ss_to_cancel->size; i++) {
421 ret = frescan_bwres_sa_add_contract
423 req_data->ss_to_cancel->ss[i],
424 req_data->request_node,
425 &scenario->backup_contracts_to_cancel.contracts[i]);
431 * frescan_manager_rep_gn
434 static void frescan_manager_rep_gn(frescan_bwres_request_data_t *req_data)
437 frescan_bwres_request_data_t *caller_req;
439 ret = frescan_bwres_requests_get_data(req_data->req, &caller_req);
442 caller_req->return_value = req_data->return_value;
444 DEBUG(FRESCAN_BWRES_MANAGER_ENABLE_DEBUG,
445 "ret:%d -> %s\n", req_data->return_value,
446 (req_data->return_value ==
447 FRESCAN_BWRES_REQ_ACCEPTED) ? "OK" : "FAIL");
449 if (req_data->return_value == FRESCAN_BWRES_REQ_ACCEPTED) {
450 assert (req_data->ss_new->size ==
451 caller_req->contracts_to_neg->size);
452 caller_req->ss_new->size = req_data->ss_new->size;
454 DEBUG(FRESCAN_BWRES_MANAGER_ENABLE_DEBUG,
455 "ss_new->size:%u\n", caller_req->ss_new->size);
457 for (i=0; i<caller_req->ss_new->size; i++) {
458 caller_req->ss_new->ss[i] = req_data->ss_new->ss[i];
462 ret = frescan_bwres_robjs_signal(caller_req->robj);
467 * frescan_manager_req_mc
470 static void frescan_manager_req_mc(frescan_bwres_request_data_t *req_data)
474 ret = frescan_bwres_mode_change_local(req_data->net,
475 req_data->mode_change_type,
476 req_data->ss_to_cancel);