The ROme OpTimistic Simulator  2.0.0
A General-Purpose Multithreaded Parallel/Distributed Simulation Platform
core.c
Go to the documentation of this file.
1 
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <stdarg.h>
36 #include <limits.h>
37 #include <signal.h>
38 
39 #include <arch/thread.h>
40 #include <core/core.h>
41 #include <core/init.h>
42 #include <scheduler/process.h>
43 #include <scheduler/scheduler.h>
44 #include <statistics/statistics.h>
45 #include <gvt/gvt.h>
46 #include <mm/mm.h>
47 
50 
52 unsigned int *kernel;
53 
55 unsigned int kid;
56 
58 unsigned int n_ker;
59 
61 unsigned int n_cores;
62 
64 unsigned int n_prc_tot;
65 
67 unsigned int n_prc;
68 
71 
73 static bool sim_error = false;
74 
77 
79 static bool init_complete = false;
80 
81 bool user_exit_flag = false;
82 
92 {
93 
94  if (likely(!init_complete))
95  return;
96 
99 
100  printf("Warning: exit() has been called from the model.\n"
101  "The simulation will now halt, but its unlikely what you really wanted...\n"
102  "You should use OnGVT() instead. See the manpages for an explanation.\n");
103 
104  simulation_shutdown(EXIT_FAILURE);
105  }
106 }
107 
108 inline bool user_requested_exit(void)
109 {
110  return user_exit_flag;
111 }
112 
113 static void handle_signal(int signum)
114 {
115  if (signum == SIGINT) {
116  user_exit_flag = true;
117  }
118 }
119 
129 void base_init(void)
130 {
131  struct sigaction new_act = { 0 };
132 
133  barrier_init(&all_thread_barrier, n_cores);
134 
135  // complete the sigaction struct init
136  new_act.sa_handler = handle_signal;
137  // we set the signal action so that it auto disarms itself after the first invocation
138  new_act.sa_flags = SA_RESETHAND;
139  // register the signal handler
140  sigaction(SIGINT, &new_act, NULL);
141  // register the exit function
143 }
144 
151 void base_fini(void)
152 {
153 }
154 
163 __attribute__((pure))
164 unsigned int find_kernel_by_gid(GID_t gid)
165 {
166  // restituisce il kernel su cui si trova il processo identificato da gid
167  return kernel[gid.to_int];
168 }
169 
178 void simulation_shutdown(int code)
179 {
180 
182 
183  statistics_stop(code);
184 
185  if (likely(rootsim_config.serial == false)) {
186 
187  thread_barrier(&all_thread_barrier);
188 
189  if (master_thread()) {
190  statistics_fini();
191  gvt_fini();
193  scheduler_fini();
194  base_fini();
195  }
196 
197  thread_barrier(&all_thread_barrier);
198  }
199 
200  exit(code);
201 }
202 
203 inline bool simulation_error(void)
204 {
205  return sim_error;
206 }
207 
220 void _rootsim_error(bool fatal, const char *msg, ...)
221 {
222  char buf[1024];
223  va_list args;
224 
225  va_start(args, msg);
226  vsnprintf(buf, 1024, msg, args);
227  va_end(args);
228 
229  fprintf(stderr, (fatal ? "[FATAL ERROR] " : "[WARNING] "));
230 
231  fprintf(stderr, "%s", buf);
232  fflush(stderr);
233 
234  if (fatal) {
235  if (rootsim_config.serial) {
236  exit(EXIT_FAILURE);
237  } else {
238 
239  if (!init_complete) {
240  exit(EXIT_FAILURE);
241  }
242 
243  // Notify all KLT to shut down the simulation
244  sim_error = true;
245 
246  // Bye bye main loop!
247  longjmp(exit_jmp, 1);
248  }
249  }
250 }
251 
259 {
260  register unsigned int i = 0;
261  unsigned int j;
262  unsigned int buf1;
263  int offset;
264  int block_leftover;
265 
266  // Sanity check on number of LPs
267  if (n_prc_tot < n_ker) {
268  rootsim_error(true, "Unable to allocate %d logical processes on %d kernels: must have at least %d LPs\n", n_prc_tot, n_ker, n_ker);
269  }
270 
271  kernel = (unsigned int *)rsalloc(sizeof(unsigned int) * n_prc_tot);
272 
273  switch (rootsim_config.lps_distribution) {
274 
276  buf1 = (n_prc_tot / n_ker);
277  block_leftover = n_prc_tot - buf1 * n_ker;
278 
279  // It is a hack to bypass the first check that set offset to 0
280  if (block_leftover > 0)
281  buf1++;
282 
283  offset = 0;
284  while (i < n_prc_tot) {
285  j = 0;
286  while (j < buf1) {
287  kernel[i] = offset;
288 
289  if (kernel[i] == kid)
290  n_prc++;
291 
292  i++;
293  j++;
294  }
295  offset++;
296  block_leftover--;
297  if (block_leftover == 0)
298  buf1--;
299  }
300  break;
301 
303  for (i = 0; i < n_prc_tot; i++) {
304  kernel[i] = i % n_ker;
305 
306  if (kernel[i] == kid)
307  n_prc++;
308  }
309  break;
310  }
311 }
312 
317 {
318  init_complete = true;
319 }
void scheduler_fini(void)
Definition: scheduler.c:105
void statistics_fini(void)
Definition: statistics.c:736
#define likely(exp)
Optimize the branch as likely taken.
Definition: core.h:72
Initialization routines.
void base_fini(void)
Definition: core.c:151
unsigned int * kernel
Mapping between kernel instances and logical processes.
Definition: core.c:52
static bool sim_error
Flag to notify all workers that there was an error.
Definition: core.c:73
Core ROOT-Sim functionalities.
unsigned int n_cores
Total number of cores required for simulation.
Definition: core.c:61
bool exit_silently_from_kernel
This flag tells whether we are exiting from the kernel of from userspace.
Definition: core.c:76
void initialization_complete(void)
Definition: core.c:316
Statistics module.
void base_init(void)
Definition: core.c:129
The ROOT-Sim scheduler main module header.
void _rootsim_error(bool fatal, const char *msg,...)
Definition: core.c:220
static bool init_complete
This flag is set when the initialization of the simulator is complete, with no errors.
Definition: core.c:79
Generic thread management facilities.
void exit_from_simulation_model(void)
Definition: core.c:91
void barrier_init(barrier_t *b, int t)
Definition: thread.c:180
unsigned int find_kernel_by_gid(GID_t gid)
Definition: core.c:164
jmp_buf exit_jmp
Definition: main.c:62
simulation_configuration rootsim_config
This global variable holds the configuration for the current simulation.
Definition: core.c:70
Memory Manager main header.
Configuration of the execution of the simulator.
Definition: init.h:57
bool thread_barrier(barrier_t *b)
Definition: thread.c:200
void gvt_fini(void)
Definition: gvt.c:156
LP control blocks.
barrier_t all_thread_barrier
Barrier for all worker threads.
Definition: core.c:49
#define master_thread()
This macro expands to true if the current KLT is the master thread for the local kernel.
Definition: thread.h:155
Definition of a GID.
Definition: core.h:132
unsigned int n_prc
Number of logical processes hosted by the current kernel instance.
Definition: core.c:67
Global Virtual Time.
void communication_fini(void)
Finalize the communication subsystem.
Definition: communication.c:75
void simulation_shutdown(int code)
Definition: core.c:178
int lps_distribution
Policy for the LP to Kernel mapping.
Definition: init.h:63
void statistics_stop(int exit_code)
Definition: statistics.c:442
unsigned int n_prc_tot
Total number of logical processes running in the simulation.
Definition: core.c:64
bool serial
If the simulation must be run serially.
Definition: init.h:72
unsigned int n_ker
Total number of simulation kernel instances running.
Definition: core.c:58
#define unlikely(exp)
Optimize the branch as likely not taken.
Definition: core.h:74
unsigned int kid
Identifier of the local kernel.
Definition: core.c:55
Thread barrier definition.
Definition: thread.h:102
void distribute_lps_on_kernels(void)
Definition: core.c:258