The ROme OpTimistic Simulator  2.0.0
A General-Purpose Multithreaded Parallel/Distributed Simulation Platform
serial.c
Go to the documentation of this file.
1 
32 #include <stdio.h>
33 #include <sys/time.h>
34 #include <stdlib.h>
35 #include <stdbool.h>
36 
37 #include <ROOT-Sim.h>
38 #include <serial/serial.h>
39 #include <scheduler/scheduler.h>
40 #include <core/core.h>
41 #include <core/init.h>
42 #include <core/timer.h>
43 #include <gvt/ccgs.h>
44 #include <mm/mm.h>
45 #include <datatypes/calqueue.h>
46 #include <statistics/statistics.h>
47 
48 #ifdef EXTRA_CHECKS
49 #include <queues/xxhash.h>
50 #endif
51 
52 static bool serial_simulation_complete = false;
53 static bool *serial_completed_simulation;
54 
55 void SerialScheduleNewEvent(unsigned int rcv, simtime_t stamp,
56  unsigned int event_type, void *event_content,
57  unsigned int event_size)
58 {
59  GID_t receiver;
60  msg_t *event;
61 
62  // Sanity checks
63  if (unlikely(stamp < lvt(current))) {
64  rootsim_error(true, "LP %d is trying to send events in the past. Current time: %f, scheduled time: %f\n",
65  current->gid.to_int, lvt(current), stamp);
66  }
67  // Populate the message data structure
68  set_gid(receiver, rcv);
69  size_t size = sizeof(msg_t) + event_size;
70  event = rsalloc(size);
71  bzero(event, sizeof(msg_t));
72  event->sender = current->gid;
73  event->receiver = receiver;
74  event->timestamp = stamp;
75  event->send_time = lvt(current);
76  event->type = event_type;
77  event->size = event_size;
78  memcpy(event->event_content, event_content, event_size);
79 
80  // Put the event in the Calenda Queue
81  calqueue_put(stamp, event);
82 }
83 
84 void serial_init(void)
85 {
86  // Sanity check on the number of LPs
87  if (unlikely(n_prc_tot == 0)) {
88  rootsim_error(true, "You must specify the total number of Logical Processes\n");
89  }
90  // Initialize the calendar queue
91  calqueue_init();
92 
93  // Initialize the per LP variables
94  serial_completed_simulation = rsalloc(sizeof(bool) * n_prc_tot);
95  bzero(serial_completed_simulation, sizeof(bool) * n_prc_tot);
96 
97  // Generate the INIT events for all the LPs
98  foreach_lp(lp) {
99  current = lp;
100  SerialScheduleNewEvent(current->gid.to_int, 0.0, INIT, NULL, 0);
101  }
102 
103  // No LP is scheduled now
104  current = NULL;
105 }
106 
107 void serial_simulation(void)
108 {
109  timer serial_event_execution;
110  timer serial_gvt_timer;
111  msg_t *event;
112  bool new_termination_decision;
113  unsigned int completed = 0;
114 
115 #ifdef EXTRA_CHECKS
116  unsigned long long hash1, hash2;
117  hash1 = hash2 = 0;
118 #endif
119 
120  timer_start(serial_gvt_timer);
121 
123 
124  while (!serial_simulation_complete) {
125 
126  // Pick an event from the calendar queue and use the
127  // receiver as the current lp
128  event = (msg_t *) calqueue_get();
129  if (unlikely(event == NULL)) {
130  rootsim_error(true, "No events to process!\n");
131  }
132 
133  current = find_lp_by_gid(event->receiver);
134  current->bound = event;
135  current_evt = event;
136 
137 #ifdef EXTRA_CHECKS
138  if (event->size > 0) {
139  hash1 = XXH64(event->event_content, event->size, current);
140  }
141 #endif
142 
143  timer_start(serial_event_execution);
144  if(&abm_settings){
145  ProcessEventABM();
146  }else if (&topology_settings){
147  ProcessEventTopology();
148  }else{
149  ProcessEvent_light(current->gid.to_int, event->timestamp,
150  event->type, event->event_content,
152  }
153 
154  statistics_post_data_serial(STAT_EVENT, 1.0);
155  statistics_post_data_serial(STAT_EVENT_TIME, timer_value_seconds(serial_event_execution));
156 
157 #ifdef EXTRA_CHECKS
158  if (event->size > 0) {
159  hash2 = XXH64(event->event_content, event->size, current);
160  }
161 
162  if (hash1 != hash2) {
163  printf("hash1 = %llu, hash2= %llu\n", hash1, hash2);
164  rootsim_error(true, "Error, LP %d has modified the payload of event %d during its processing. Aborting...\n",
165  current->gid, event->type);
166  }
167 #endif
168 
169  // Termination detection can happen only after the state is initialized
170  if (likely(current->current_base_pointer != NULL)) {
171 
172  // We have just executed a new event at some LP. Depending on the type of requested termination detection,
173  // we call or skip the termination detection for the current LP.
175  // In incremental termination detection we are dealing with stable termination
176  // predicates. We can suppose that after that an LP decided to terminate the
177  // simulation, it will never change its mind.
178  if (!serial_completed_simulation[event->receiver.to_int] && current->OnGVT(event->receiver.to_int, current->current_base_pointer)) {
179  completed++;
180  serial_completed_simulation[event->receiver.to_int] = true;
181  if (unlikely(completed == n_prc_tot)) {
182  serial_simulation_complete = true;
183  }
184  }
185  } else {
186  // Normal and accurate termination detection policies are the same in sequential simulation.
187  // We have to be sure that, at the current time, all the LPs are agreeing on termination.
188  // We therefore keep track of past per-LP decisions and increment/decrement the termination counter depending
189  // on changed decision.
190  new_termination_decision = current->OnGVT(event->receiver.to_int, current->current_base_pointer);
191 
192  if(serial_completed_simulation[event->receiver.to_int] != new_termination_decision) {
193  if(new_termination_decision) {
194  // Changed from false to true
195  completed++;
196  } else {
197  // Changed from true to false
198  completed--;
199  }
200  }
201 
202  serial_completed_simulation[event->receiver.to_int] = new_termination_decision;
203 
204  if (unlikely(completed == n_prc_tot)) {
205  serial_simulation_complete = true;
206  }
207  }
208  }
209 
210  // Termination detection on reached LVT value
211  if (rootsim_config.simulation_time > 0 && event->timestamp >= rootsim_config.simulation_time) {
212  serial_simulation_complete = true;
213  }
214 
215  // Print the time advancement periodically
216  if (timer_value_milli(serial_gvt_timer) > (int)rootsim_config.gvt_time_period) {
217  timer_restart(serial_gvt_timer);
218  printf("TIME BARRIER: %f\n", lvt(current));
219  statistics_on_gvt_serial(lvt(current));
220  }
221 
222  current = NULL;
223 
224  rsfree(event);
225  }
226 
227  simulation_shutdown(EXIT_SUCCESS);
228 }
#define lvt(lp)
Definition: process.h:168
msg_t * bound
Pointer to the last correctly processed event.
Definition: process.h:106
#define likely(exp)
Optimize the branch as likely taken.
Definition: core.h:72
void statistics_start(void)
Definition: statistics.c:286
Initialization routines.
void ProcessEventABM(void)
Definition: abm_layer.c:461
int check_termination_mode
Check termination strategy: standard or incremental.
Definition: init.h:68
Core ROOT-Sim functionalities.
ROOT-Sim header for model development.
unsigned int to_int
The GID numerical value.
Definition: core.h:133
Timers.
Statistics module.
The ROOT-Sim scheduler main module header.
__thread struct lp_struct * current
This is a per-thread variable pointing to the block state of the LP currently scheduled.
Definition: scheduler.c:72
Consistent and Committed Global State.
struct _msg_t msg_t
Message Type definition.
double simtime_t
This defines the type with whom timestamps are represented.
Definition: ROOT-Sim.h:55
simulation_configuration rootsim_config
This global variable holds the configuration for the current simulation.
Definition: core.c:70
__thread msg_t * current_evt
Definition: scheduler.c:83
Memory Manager main header.
Message Type definition.
Definition: core.h:164
bool(* OnGVT)(unsigned int me, void *snapshot)
Definition: process.h:130
unsigned int size
Unique identifier of the message, used for rendez-vous events.
Definition: core.h:189
Serial scheduler.
int simulation_time
Wall-clock-time based termination predicate.
Definition: init.h:62
Calendar Queue Implementation.
Definition of a GID.
Definition: core.h:132
GID_t gid
Global ID of the LP.
Definition: process.h:82
void simulation_shutdown(int code)
Definition: core.c:178
Fast Hash Algorithm.
#define INIT
This is the message code which is sent by the simulation kernel upon startup.
Definition: ROOT-Sim.h:52
unsigned int n_prc_tot
Total number of logical processes running in the simulation.
Definition: core.c:64
int gvt_time_period
Wall-Clock time to wait before executiong GVT operations.
Definition: init.h:60
void * current_base_pointer
The current state base pointer (updated by SetState())
Definition: process.h:100
#define unlikely(exp)
Optimize the branch as likely not taken.
Definition: core.h:74