9 #include <lib/topology.h> 14 #include <lib/jsmn_helper.h> 18 #include <datatypes/heap.h> 26 void UncheckedScheduleNewEvent(
unsigned int gid_receiver,
simtime_t timestamp,
unsigned int event_type,
void *event_content,
unsigned int event_size){
32 SerialScheduleNewEvent(gid_receiver, timestamp, event_type, event_content, event_size);
39 set_gid(receiver, gid_receiver);
49 rootsim_error(
true,
"Warning: the destination LP %u %lf %u is out of range. The event has been ignored\n", receiver.
to_int, timestamp, event_type);
55 rootsim_error(
true,
"LP %u is trying to generate an event (type %d) to %u in the past! (Current LVT = %f, generated event's timestamp = %f) Aborting...\n",
current, event_type, receiver.
to_int,
lvt(
current), timestamp);
70 static unsigned directions_count(
void) {
73 return topology_global.
lp_cnt - 1;
98 static void *load_topology_file(
const char *file_name) {
110 if(load_and_parse_json_file(file_name, &json_base, &root_token) < 0)
111 rootsim_error(
true,
"The specified topology file at \"%s\" is either non accessible, non existing, or is not a properly formed JSON file", file_name);
113 if(parse_unsigned_by_key(root_token, json_base, root_token,
"regions_count", &lp_cnt) < 0)
114 rootsim_error(
true,
"Invalid or missing json value with key \"regions_count\" (must be an unsigned integer)");
116 if(lp_cnt + topology_settings.out_of_topology >
n_prc_tot)
117 rootsim_error(
true,
"This topology needs an higher number of available LPs (%lu versus %lu available LPs)", lp_cnt,
n_prc_tot);
118 if(lp_cnt + topology_settings.out_of_topology <
n_prc_tot)
119 rootsim_error(
true,
"The requested regions are fewer than the available LPs (%lu versus %lu available LPs)", lp_cnt,
n_prc_tot);
122 const char *type_choices[] = {
128 t = get_value_token_by_key(root_token, json_base, root_token,
"type");
130 if((t_type = parse_string_choice(root_token, json_base, t,
sizeof(type_choices)/
sizeof(
const char *), type_choices)) == UINT_MAX)
131 rootsim_error(
true,
"Invalid or missing json value with key \"type\" (must be a recognizable string)");
133 if(t_type != topology_settings.type){
134 rootsim_error(
true,
"The specified topology has a different type from the one requested by the model");
138 const char *geometry_choices[] = {
148 t = get_value_token_by_key(root_token, json_base, root_token,
"geometry");
150 if((geometry = parse_string_choice(root_token, json_base, t,
sizeof(geometry_choices)/
sizeof(
const char *), geometry_choices)) == UINT_MAX)
151 rootsim_error(
true,
"Invalid or missing json value with key \"geometry\" (must be a recognizable string)");
157 topology_global.
directions = directions_count();
161 ret = load_topology_file_probabilities(root_token, json_base);
165 ret = load_topology_file_costs(root_token, json_base);
169 ret = load_topology_file_obstacles(root_token, json_base);
183 static void compute_edge(
void){
185 const unsigned lp_cnt = topology_global.
lp_cnt;
192 if(edge * edge != lp_cnt)
193 rootsim_error(
true,
"Invalid number of regions for this topology geometry (must be a square number)");
208 void topology_init(
void) {
209 if(!&topology_settings)
216 if(topology_settings.out_of_topology >=
n_prc_tot)
217 rootsim_error(
true,
"Not enough LPs to run even a default topology with %u control LPs", topology_settings.out_of_topology);
219 topology_global.
lp_cnt =
n_prc_tot - topology_settings.out_of_topology;
220 topology_global.
geometry = topology_settings.default_geometry;
221 topology_global.
directions = directions_count();
223 if(topology_settings.topology_path)
224 t_data = load_topology_file(topology_settings.topology_path);
228 switch(topology_settings.type){
230 topology_global.
chkp_size = size_checkpoint_costs();
233 topology_global.
chkp_size = size_checkpoint_probabilities();
236 topology_global.
chkp_size = size_checkpoint_obstacles();
241 if(lp->gid.to_int >= topology_global.
lp_cnt){
245 switch(topology_settings.type){
247 lp->topology = topology_costs_init(lp->gid.to_int, t_data);
250 lp->topology = topology_obstacles_init(lp->gid.to_int, t_data);
253 lp->topology = topology_probabilities_init(lp->gid.to_int, t_data);
262 switch_to_platform_mode();
263 const unsigned lp_cnt = topology_global.
lp_cnt;
265 if(
unlikely(!topology_settings.write_enabled))
266 rootsim_error(
true,
"SetValueTopology(): called with write_enable false");
268 if(
unlikely(from >= lp_cnt || to >= lp_cnt))
269 rootsim_error(
true,
"SetValueTopology(): from % u, to %u when lp_cnt is %u", from, to, lp_cnt);
272 rootsim_error(
true,
"SetValueTopology(): negative values are not supported", value);
274 switch (topology_settings.type) {
276 set_value_topology_costs(from, to, value);
279 set_value_topology_probabilities(from, to, value);
282 set_value_topology_obstacles(from, to, value);
285 switch_to_application_mode();
289 switch_to_platform_mode();
290 const unsigned lp_cnt = topology_global.
lp_cnt;
294 if(from >= lp_cnt || to >= lp_cnt)
295 rootsim_error(
true,
"SetValueTopology(): from % u, to %u when lp_cnt is %u", from, to, lp_cnt);
297 switch (topology_settings.type) {
299 ret = get_value_topology_costs(from, to);
302 ret = get_value_topology_probabilities(from, to);
305 ret = get_value_topology_obstacles(from, to);
308 switch_to_application_mode();
312 void ProcessEventTopology(
void){
315 switch (topology_settings.type) {
317 update_topology_costs();
320 update_topology_probabilities();
323 update_topology_obstacles();
326 rootsim_error(
true,
"This shouldn't happen. Contact the maintainer");
330 switch_to_application_mode();
332 switch_to_platform_mode();
336 unsigned int RegionsCount(
void) {
337 return topology_global.
lp_cnt;
340 unsigned int DirectionsCount(
void) {
344 static bool is_reachable(
unsigned int to){
346 switch (topology_settings.type) {
348 result = is_reachable_probabilities(to);
351 result = is_reachable_obstacles(to);
354 result = is_reachable_costs(to);
360 unsigned int NeighboursCount(
unsigned region){
361 switch_to_platform_mode();
369 switch_to_application_mode();
380 unsigned int get_raw_receiver(
unsigned int from,
direction_t direction) {
384 const unsigned sender = from;
386 const unsigned edge = topology_global.
edge;
395 x = sender - y *
edge;
424 if(
likely(x < edge && y < edge))
425 receiver = y * edge + x;
432 x = sender - y *
edge;
451 if(
likely(x < edge && y < edge))
452 receiver = y * edge + x;
459 x = sender - y *
edge;
491 receiver = y * edge + x;
497 receiver = direction;
503 receiver = topology_global.
lp_cnt - 1;
505 receiver =sender - 1;
508 if(sender + 1 == topology_global.
lp_cnt)
511 receiver = sender + 1;
518 receiver = sender + 1;
520 if(receiver == topology_global.
lp_cnt) {
533 if(direction + 1 >= topology_global.
lp_cnt)
535 receiver = direction + 1;
541 rootsim_error(
true,
"This shouldn't happen. Aborting...");
548 unsigned int GetReceiver(
unsigned int from,
direction_t direction,
bool reachable) {
550 switch_to_platform_mode();
553 rootsim_error(
true,
"GetReceiver(): region argument not included in topology!");
555 receiver = get_raw_receiver(from, direction);
556 if(reachable && !is_reachable(receiver))
558 switch_to_application_mode();
562 bool IsReachable(
unsigned int to){
564 switch_to_platform_mode();
565 result = is_reachable(to);
566 switch_to_application_mode();
570 unsigned int FindReceiver(
void) {
571 switch_to_platform_mode();
573 const unsigned lp_cnt = topology_global.
lp_cnt;
576 if(
unlikely(lp_cnt <= current->gid.to_int))
577 rootsim_error(
true,
"FindReceiver(): source region %u when topology includes %u regions",
current->
gid.
to_int, lp_cnt);
579 switch (topology_settings.type) {
581 receiver = find_receiver_probabilities();
584 receiver = find_receiver_obstacles();
587 rootsim_error(
true,
"FindReceiver(): topology type not supported!");
590 switch_to_application_mode();
594 unsigned int FindReceiverToward(
unsigned int to) {
595 switch_to_platform_mode();
597 const unsigned lp_cnt = topology_global.
lp_cnt;
602 rootsim_error(
true,
"Calling FindReceiverToward() from or toward a region not included in the topology");
604 switch (topology_settings.type) {
606 receiver = find_receiver_toward_costs(to);
609 receiver = find_receiver_toward_obstacles(to);
612 rootsim_error(
true,
"FindReceiverToward(): unsupported topology type");
614 switch_to_application_mode();
629 unsigned build_path(
unsigned lp_cnt,
unsigned result[lp_cnt],
const unsigned int previous[lp_cnt],
unsigned source,
unsigned dest) {
633 if(previous[dest] == UINT_MAX) {
638 res_aux = result + lp_cnt - 1;
644 mid_cell = previous[dest];
646 while (mid_cell != source) {
652 mid_cell = previous[mid_cell];
657 memmove(result, res_aux, ((result + lp_cnt) - res_aux) *
sizeof(
unsigned));
661 double ComputeMinTour(
unsigned int source,
unsigned int dest,
unsigned int result[RegionsCount()]) {
662 switch_to_platform_mode();
664 const unsigned lp_cnt = topology_global.
lp_cnt;
668 rootsim_error(
true,
"Invalid source passed to ComputeMinTour(): %u.\n", source);
672 rootsim_error(
true,
"Invalid destination passed to ComputeMinTour(): %u.\n", dest);
676 rootsim_error(
true,
"Asking ComputeMinTour() to find a path from a source equal to the destination\n");
680 switch (topology_settings.type) {
682 ret = compute_min_tour_costs(source, dest, result);
685 ret = compute_min_tour_obstacles(source, dest, result);
688 rootsim_error(
true,
"ComputeMinTour(): unsupported topology type %u", topology_settings.type);
690 switch_to_application_mode();
all crossing costs and probabilities are set to 1, but there can be not crossable regions ...
unsigned long long generate_mark(struct lp_struct *lp)
#define likely(exp)
Optimize the branch as likely taken.
enum _topology_geometry_t geometry
A generic invalid direction.
ROOT-Sim header for model development.
unsigned int to_int
The GID numerical value.
The ROOT-Sim scheduler main module header.
double GetValueTopology(unsigned from, unsigned to)
This is the implementation of a dynamic array, used for managing various data structures.
a torus shaped grid topology (a wrapping around square topology)
__thread struct lp_struct * current
This is a per-thread variable pointing to the block state of the LP currently scheduled.
double simtime_t
This defines the type with whom timestamps are represented.
void SetValueTopology(unsigned from, unsigned to, double value)
simulation_configuration rootsim_config
This global variable holds the configuration for the current simulation.
__thread msg_t * current_evt
decisions are taken at random but are weighted on the palatability of neighbours
unsigned int size
Unique identifier of the message, used for rendez-vous events.
enum _direction_t direction_t
void insert_outgoing_msg(msg_t *msg)
Place a message in the temporary LP outgoing buffer.
void pack_msg(msg_t **msg, GID_t sender, GID_t receiver, int type, simtime_t timestamp, simtime_t send_time, size_t size, void *payload)
Pack a message in a platform-level data structure.
an arbitrary shaped topology
a ring shaped topology direction
GID_t gid
Global ID of the LP.
short unsigned int state
Current execution state of the LP.
arbitrary offset used to distinguish during debug different enums
decisions on next hops are taken based on the costs undertaken to cross the boundaries ...
void(* ProcessEvent)(unsigned int me, simtime_t now, int event_type, void *event_content, unsigned int size, void *state)
a ring shaped topology walkable in a single direction
this is used to store the common characteristics of the topology
unsigned int n_prc_tot
Total number of logical processes running in the simulation.
bool serial
If the simulation must be run serially.
void * current_base_pointer
The current state base pointer (updated by SetState())
#define unlikely(exp)
Optimize the branch as likely not taken.