The ROme OpTimistic Simulator  2.0.0
A General-Purpose Multithreaded Parallel/Distributed Simulation Platform
init.c
Go to the documentation of this file.
1 
32 #include <unistd.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <sys/types.h>
37 #include <limits.h>
38 #include <sysexits.h>
39 #include <argp.h>
40 #include <errno.h>
41 
42 #include <ROOT-Sim.h>
43 #include <arch/thread.h>
45 #include <core/core.h>
46 #include <core/init.h>
47 #include <datatypes/bitmap.h>
48 #include <scheduler/process.h>
49 #include <gvt/gvt.h>
50 #include <gvt/ccgs.h>
51 #include <scheduler/scheduler.h>
52 #include <mm/state.h>
53 #include <mm/ecs.h>
54 #include <mm/mm.h>
55 #include <statistics/statistics.h>
56 #include <lib/numerical.h>
57 #include <lib/topology.h>
58 #include <lib/abm_layer.h>
59 #include <serial/serial.h>
60 #ifdef HAVE_MPI
61 #include <communication/mpi.h>
62 #endif
63 
64 
67  OPT_FIRST = 128,
69  // make sure these ones are mapped correctly to the external enum param_codes,
70  OPT_SCHEDULER = OPT_FIRST + PARAM_SCHEDULER,
71  OPT_CKTRM_MODE = OPT_FIRST + PARAM_CKTRM_MODE,
72  OPT_LPS_DISTRIBUTION = OPT_FIRST + PARAM_LPS_DISTRIBUTION,
73  OPT_VERBOSE = OPT_FIRST + PARAM_VERBOSE,
74  OPT_STATS = OPT_FIRST + PARAM_STATS,
75  OPT_STATE_SAVING = OPT_FIRST + PARAM_STATE_SAVING,
76  OPT_SNAPSHOT = OPT_FIRST + PARAM_SNAPSHOT,
77 
78  OPT_NP,
79  OPT_NPRC,
80  OPT_OUTPUT_DIR,
81  OPT_NPWD,
82  OPT_P,
83  OPT_FULL,
84  OPT_INC,
85  OPT_A,
86  OPT_GVT,
87  OPT_SIMULATION_TIME,
88  OPT_DETERMINISTIC_SEED,
89  OPT_SEED,
90  OPT_SERIAL,
91  OPT_NO_CORE_BINDING,
92  OPT_PREEMPTION,
93  OPT_SILENT,
94  OPT_LAST
95 };
96 
97 // XXX we offset the first level with OPT_FIRST so remember about it when you index it!
98 const char * const param_to_text[][5] = {
99  [OPT_SCHEDULER - OPT_FIRST] = {
100  [SCHEDULER_INVALID] = "invalid scheduler",
101  [SCHEDULER_STF] = "stf",
102  },
103  [OPT_CKTRM_MODE - OPT_FIRST] = {
104  [CKTRM_INVALID] = "invalid termination checking",
105  [CKTRM_NORMAL] = "normal",
106  [CKTRM_INCREMENTAL] = "incremental",
107  [CKTRM_ACCURATE] = "accurate"
108  },
109  [OPT_LPS_DISTRIBUTION - OPT_FIRST] = {
110  [LP_DISTRIBUTION_INVALID] = "invalid LPs distribution",
111  [LP_DISTRIBUTION_BLOCK] = "block",
112  [LP_DISTRIBUTION_CIRCULAR] = "circular"
113  },
114  [OPT_VERBOSE - OPT_FIRST] = {
115  [VERBOSE_INVALID] = "invalid verbose specification",
116  [VERBOSE_INFO] = "info",
117  [VERBOSE_DEBUG] = "debug",
118  [VERBOSE_NO] = "no"
119  },
120  [OPT_STATS - OPT_FIRST] = {
121  [STATS_INVALID] = "invalid statistics specification",
122  [STATS_GLOBAL] = "global",
123  [STATS_PERF] = "performance",
124  [STATS_LP] = "lp",
125  [STATS_ALL] = "all"
126  },
127  [OPT_STATE_SAVING - OPT_FIRST] = {
128  [STATE_SAVING_INVALID] = "invalid checkpointing specification",
129  [STATE_SAVING_COPY] = "copy",
130  [STATE_SAVING_PERIODIC] = "periodic",
131  },
132  [OPT_SNAPSHOT - OPT_FIRST] = {
133  [SNAPSHOT_INVALID] = "invalid snapshot specification",
134  [SNAPSHOT_FULL] = "full",
135  }
136 };
137 
138 const char *argp_program_version = PACKAGE_STRING "\nCopyright (C) 2008-2019 HPDCS Group";
139 const char *argp_program_bug_address = PACKAGE_BUGREPORT;
140 
141 // Directly from argp documentation:
142 // If non-zero, a string containing extra text to be printed before and after the options in a long help message,
143 // with the two sections separated by a vertical tab ('\v', '\013') character.
144 // By convention, the documentation before the options is just a short string explaining what the program does.
145 // Documentation printed after the options describe behavior in more detail.
146 static char doc[] = "ROOT-Sim - a fast distributed multithreaded Parallel Discrete Event Simulator \v For more information check the official wiki at https://github.com/HPDCS/ROOT-Sim/wiki";
147 
148 // this isn't needed (we haven't got non option arguments to document)
149 static char args_doc[] = "";
150 // the options recognized by argp
151 static const struct argp_option argp_options[] = {
152  {"wt", OPT_NP, "VALUE", 0, "Number of total cores being used by the simulation", 0},
153  {"lp", OPT_NPRC, "VALUE", 0, "Total number of Logical Processes being launched at simulation startup", 0},
154  {"output-dir", OPT_OUTPUT_DIR, "PATH", 0, "Path to a folder where execution statistics are stored. If not present, it is created", 0},
155  {"scheduler", OPT_SCHEDULER, "TYPE", 0, "LP Scheduling algorithm. Supported values are: stf", 0},
156  {"npwd", OPT_NPWD, 0, 0, "Non Piece-Wise-Deterministic simulation model. See manpage for accurate description", 0},
157  {"p", OPT_P, "VALUE", 0, "Checkpointing interval", 0},
158  {"full", OPT_FULL, 0, 0, "Take only full logs", 0},
159  {"inc", OPT_INC, 0, 0, "Take only incremental logs (still to be released)", 0},
160  {"A", OPT_A, 0, 0, "Autonomic subsystem: set checkpointing interval and log mode automatically at runtime (still to be released)", 0},
161  {"gvt", OPT_GVT, "VALUE", 0, "Time between two GVT reductions (in milliseconds)", 0},
162  {"cktrm-mode", OPT_CKTRM_MODE, "TYPE", 0, "Termination Detection mode. Supported values: normal, incremental, accurate", 0},
163  {"simulation-time", OPT_SIMULATION_TIME, "VALUE", 0, "Halt the simulation when all LPs reach this logical time. 0 means infinite", 0},
164  {"lps-distribution", OPT_LPS_DISTRIBUTION, "TYPE", 0, "LPs distributions over simulation kernels policies. Supported values: block, circular", 0},
165  {"deterministic-seed", OPT_DETERMINISTIC_SEED, 0, 0, "Do not change the initial random seed for LPs. Enforces different deterministic simulation runs", 0},
166  {"verbose", OPT_VERBOSE, "TYPE", 0, "Verbose execution", 0},
167  {"stats", OPT_STATS, "TYPE", 0, "Level of detail in the output statistics", 0},
168  {"seed", OPT_SEED, "VALUE", 0, "Manually specify the initial random seed", 0},
169  {"serial", OPT_SERIAL, 0, 0, "Run a serial simulation (using Calendar Queues)", 0},
170  {"sequential", OPT_SERIAL, 0, OPTION_ALIAS, NULL, 0},
171  {"no-core-binding", OPT_NO_CORE_BINDING, 0, 0, "Disable the binding of threads to specific physical processing cores", 0},
172  {"silent-output", OPT_SILENT, 0, 0, "Disable any output generated by printf() calls (also from models)", 0},
173  {"no-preemption", OPT_PREEMPTION, 0, 0, "Disable Preemptive Time Warp", 0},
174  {0}
175 };
176 
177 #define malformed_option_failure() argp_error(state, "invalid value \"%s\" in %s option.\nAborting!", arg, state->argv[state->next -1 -(arg != NULL)])
178 
179 #define conflicting_option_failure(msg) argp_error(state, "the requested option %s with value \"%s\" is conflicting: " msg "\nAborting!", state->argv[state->next -1 -(arg != NULL)], arg)
180 
181 // this parses an string option leveraging the 2d array of strings specified earlier
182 // the weird iteration style skips the element 0, which we know is associated with an invalid value description
183 #define handle_string_option(label, var) \
184  case label: \
185  ({ \
186  unsigned __i = 1; \
187  while(1) { \
188  if(strcmp(arg, param_to_text[key - OPT_FIRST][__i]) == 0) { \
189  var = __i; \
190  break; \
191  } \
192  if(!param_to_text[key - OPT_FIRST][++__i]) \
193  malformed_option_failure(); \
194  } \
195  }); \
196  break
197 
198 
199 // the compound expression equivalent to __value >= low is needed in order to suppress a warning when low == 0
200 #define parse_ullong_limits(low, high) \
201  ({ \
202  unsigned long long int __value; \
203  char *__endptr; \
204  __value = strtoull(arg, &__endptr, 10); \
205  if(!(*arg != '\0' && *__endptr == '\0' && (__value > low || __value == low) && __value <= high)) { \
206  malformed_option_failure(); \
207  } \
208  __value; \
209  })
210 
211 static error_t parse_opt (int key, char *arg, struct argp_state *state)
212 {
213  // this is used in order to ensure that the user doesn't use duplicate options
214  static rootsim_bitmap scanned[bitmap_required_size(OPT_LAST - OPT_FIRST)];
215 
216  if(key >= OPT_FIRST && key < OPT_LAST){
217  if(bitmap_check(scanned, key - OPT_FIRST))
218  conflicting_option_failure("this option has already been specified");
219 
220  bitmap_set(scanned, key - OPT_FIRST);
221  }
222 
223  switch (key) {
224  case OPT_NP:
225  if(strcmp(arg, "auto") == 0) {
226  n_cores = get_cores();
227  } else {
228  n_cores = parse_ullong_limits(1, UINT_MAX);
229  }
230  break;
231 
232  case OPT_NPRC:
233  n_prc_tot = parse_ullong_limits(1, UINT_MAX);
234  break;
235 
236  case OPT_OUTPUT_DIR:
238  break;
239 
240  handle_string_option(OPT_SCHEDULER, rootsim_config.scheduler);
241  handle_string_option(OPT_FULL, rootsim_config.snapshot);
242  handle_string_option(OPT_CKTRM_MODE, rootsim_config.check_termination_mode);
243  handle_string_option(OPT_VERBOSE, rootsim_config.verbose);
244  handle_string_option(OPT_STATS, rootsim_config.stats);
245  handle_string_option(OPT_LPS_DISTRIBUTION, rootsim_config.lps_distribution);
246 
247  case OPT_NPWD:
248  if (bitmap_check(scanned, OPT_P-OPT_FIRST)) {
249  conflicting_option_failure("I'm requested to run non piece-wise deterministically, but a checkpointing interval is set already.");
250  } else {
252  }
253  break;
254 
255  case OPT_P:
256  if(bitmap_check(scanned, OPT_NPWD-OPT_FIRST)) {
257  conflicting_option_failure("Copy State Saving is selected, but I'm requested to set a checkpointing interval.");
258  } else {
260  rootsim_config.ckpt_period = parse_ullong_limits(1, 40);
261  // This is a micro optimization that makes the LogState function to avoid checking the checkpointing interval and keeping track of the logs taken
262  if(rootsim_config.ckpt_period == 1)
264  }
265  break;
266 
267  case OPT_INC:
268  argp_failure(state, EXIT_FAILURE, ENOSYS, "incremental state saving is not supported in stable version yet...\nAborting");
269  break;
270 
271  case OPT_A:
272  argp_failure(state, EXIT_FAILURE, ENOSYS, "autonomic state saving is not supported in stable version yet...\nAborting");
273  break;
274 
275  case OPT_GVT:
276  rootsim_config.gvt_time_period = parse_ullong_limits(1, 10000);
277  break;
278 
279  case OPT_SIMULATION_TIME:
280  rootsim_config.simulation_time = parse_ullong_limits(0, INT_MAX);
281  break;
282 
283  case OPT_DETERMINISTIC_SEED:
285  break;
286 
287  case OPT_SEED:
288  rootsim_config.set_seed = parse_ullong_limits(0, UINT64_MAX);
289  break;
290 
291  case OPT_SERIAL:
292  rootsim_config.serial = true;
293  break;
294 
295  case OPT_NO_CORE_BINDING:
297  break;
298 
299  case OPT_PREEMPTION:
301  break;
302 
303  case OPT_SILENT:
305  break;
306 
307  case ARGP_KEY_INIT:
308 
309  memset(&rootsim_config, 0, sizeof(rootsim_config));
310  memset(scanned, 0, sizeof(scanned));
311  // Store the predefined values, before reading any overriding one
318  rootsim_config.snapshot = SNAPSHOT_FULL; // TODO: in the future, default to AUTONOMIC_
325  rootsim_config.serial = false;
329  break;
330 
331  case ARGP_KEY_SUCCESS:
332 
333  // sanity checks
334  if(!rootsim_config.serial && !bitmap_check(scanned, OPT_NP - OPT_FIRST))
335  rootsim_error(true, "Number of cores was not provided \"--wt\"\n");
336 
337  if(!bitmap_check(scanned, OPT_NPRC - OPT_FIRST))
338  rootsim_error(true, "Number of LPs was not provided \"--lp\"\n");
339 
340  if(n_cores > get_cores())
341  rootsim_error(true, "Demanding %u cores, which are more than available (%d)\n", n_cores, get_cores());
342 
344  rootsim_error(true, "Too many threads, maximum supported number is %u\n", MAX_THREADS_PER_KERNEL);
345 
346  if(n_prc_tot > MAX_LPs)
347  rootsim_error(true, "Too many LPs, maximum supported number is %u\n", MAX_LPs);
348 
350  rootsim_error(true, "Requested a simulation run with %u LPs and %u worker threads: the mapping is not possible\n", n_prc_tot, n_cores);
351 
352  print_config();
353 
354  break;
355 
356  /* these functionalities are not needed
357  case ARGP_KEY_ARGS:
358  case ARGP_KEY_NO_ARGS:
359  case ARGP_KEY_SUCCESS:
360  case ARGP_KEY_END:
361  case ARGP_KEY_ARG:
362  case ARGP_KEY_ERROR:
363  */
364  default:
365  return ARGP_ERR_UNKNOWN;
366  }
367  return 0;
368 }
369 
370 #undef parse_ullong_limits
371 #undef handle_string_option
372 #undef conflicting_option_failure
373 #undef malformed_option_failure
374 
375 static struct argp_child argp_child[2] = {
376  {0, 0, "Model specific options", 0},
377  {0}
378 };
379 
380 static struct argp argp = { argp_options, parse_opt, args_doc, doc, argp_child, 0, 0 };
381 
382 
392 void SystemInit(int argc, char **argv)
393 {
394 #ifdef HAVE_MPI
395  mpi_init(&argc, &argv);
396 
397  if(n_ker > MAX_KERNELS){
398  rootsim_error(true, "Too many kernels, maximum supported number is %u\n", MAX_KERNELS);
399  }
400 #else
401  n_ker = 1;
402 #endif
403 
404  // Early initialization of ECS subsystem if needed
405 #ifdef HAVE_CROSS_STATE
406  ecs_init();
407 #endif
408 
409  // this retrieves the model's argp parser if declared by the developer
410  argp_child[0].argp = &model_argp;
411 
412  argp_parse (&argp, argc, argv, 0, NULL, NULL);
413 
414  // If we're going to run a serial simulation, configure the simulation to support it
415  if(rootsim_config.serial) {
416  ScheduleNewEvent = SerialScheduleNewEvent;
417  initialize_lps();
418  numerical_init();
419  statistics_init();
420  serial_init();
421  topology_init();
422  abm_layer_init();
423  return;
424  } else {
426  }
427 
428  // Initialize ROOT-Sim subsystems.
429  // All init routines are executed serially (there is no notion of threads in there)
430  // and the order of invocation can matter!
431  base_init();
432  segment_init();
433  initialize_lps();
434  remote_memory_init();
435  statistics_init();
436  scheduler_init();
438  gvt_init();
439  numerical_init();
440  topology_init();
441  abm_layer_init();
442 
443  // This call tells the simulation engine that the sequential initial simulation is complete
445 }
446 
447 
461 bool CapabilityAvailable(enum capability_t which, struct capability_info_t *info)
462 {
463 
464  // Early evaluate things that don't have any information to provide
465  switch(which) {
466  case CAP_NPWD:
468  case CAP_FULL:
469  return true;
470  case CAP_INC:
471  return false; // not implemented
472  case CAP_A:
473  return false; // not implemented
474  case CAP_DETERMINISTIC_SEED:
476  case CAP_SERIAL:
477  return rootsim_config.serial;
478  case CAP_CORE_BINDING:
480  case CAP_PREEMPTION:
482  case CAP_ECS:
483  return false; // not implemented
484  case CAP_LINUX_MODULES:
485  return false; // not implemented
486  case CAP_LP_REBINDING:
487  #ifdef HAVE_LP_REBINDING
488  return true;
489  #else
490  return false;
491  #endif
492  case CAP_MPI:
493  #ifdef HAVE_MPI
494  return true;
495  #else
496  return false;
497  #endif
498  case CAP_SILENT:
500  default:
501  break; // Just to silence compiler's warnings [-Wswitch]: other values are evaluated later
502  }
503 
504 
505  // With respect to the above, evaluate here in case no information is requested
506  if(info == NULL) {
507  switch(which) {
508  case CAP_SCHEDULER ... CAP_VERBOSE:
509  return true;
510  case CAP_SIMULATION_TIME:
511  return rootsim_config.simulation_time > 0;
512  default:
513  rootsim_error(false, "Requesting information for an unknown capability\n");
514  return false;
515  }
516  }
517 
518  // Here we do the most work
519  info->capability = which;
520 
521  switch(which) {
522  case CAP_SCHEDULER:
524  return true;
525  case CAP_CKTRM_MODE:
527  return true;
528  case CAP_LPS_DISTRIBUTION:
530  return true;
531  case CAP_STATS:
532  info->stats = rootsim_config.stats;
533  return true;
534  case CAP_STATE_SAVING:
536  return true;
537  case CAP_THREADS:
538  info->lps = n_cores;
539  return true;
540  case CAP_LPS:
541  info->lps = n_prc_tot;
542  return true;
543  case CAP_OUTPUT_DIR:
545  return true;
546  case CAP_P:
548  return true;
549  case CAP_GVT:
551  return true;
552  case CAP_SEED:
553  info->seed = rootsim_config.set_seed;
554  return true;
555  case CAP_VERBOSE:
557  return true;
558  case CAP_SIMULATION_TIME:
560  return rootsim_config.simulation_time > 0;
561  default:
562  rootsim_error(false, "Requesting information for an unknown capability\n");
563  return false;
564  }
565 }
uint64_t seed
The master seed to be used in this run.
Definition: ROOT-Sim.h:294
Communication Routines.
void abm_layer_init(void)
Definition: abm_layer.c:235
Initialization routines.
#define bitmap_set(bitmap, bit_index)
This sets the bit with index bit_index of the bitmap bitmap.
Definition: bitmap.h:116
int lps
Number of active logical processes.
Definition: ROOT-Sim.h:293
seed_type set_seed
The master seed to be used in this run.
Definition: init.h:72
int check_termination_mode
Check termination strategy: standard or incremental.
Definition: init.h:67
char * output_dir
Destination Directory of output files.
Definition: init.h:58
int verbose
Kernel verbose.
Definition: init.h:69
Core ROOT-Sim functionalities.
void gvt_init(void)
Definition: gvt.c:132
void statistics_init(void)
Definition: statistics.c:660
ROOT-Sim header for model development.
unsigned int n_cores
Total number of cores required for simulation.
Definition: core.c:61
#define bitmap_required_size(requested_bits)
Computes the required size of a bitmap with requested_bits entries.
Definition: bitmap.h:92
int verbose
Kernel verbose.
Definition: ROOT-Sim.h:291
int ckpt_period
Number of events to execute before taking a snapshot in PSS (ignored otherwise)
Definition: init.h:65
Definition: init.c:67
void initialization_complete(void)
Definition: core.c:316
int checkpointing
Type of checkpointing scheme (e.g., PSS, CSS, ...)
Definition: init.h:64
#define MAX_THREADS_PER_KERNEL
Definition: thread.h:137
void ParallelScheduleNewEvent(unsigned int gid_receiver, simtime_t timestamp, unsigned int event_type, void *event_content, unsigned int event_size)
Schedule a new message to some LP.
bool deterministic_seed
Does not change the seed value config file that will be read during the next runs.
Definition: init.h:68
int ckpt_period
Number of events to execute before taking a snapshot in PSS (ignored otherwise)
Definition: ROOT-Sim.h:289
#define DEFAULT_OUTPUT_DIR
This macro specified the default output directory, if nothing is passed as an option.
Definition: statistics.h:59
_opt_codes
This is the list of mnemonics for arguments.
Definition: init.c:66
int scheduler
Which scheduler to be used.
Definition: ROOT-Sim.h:283
Statistics module.
void base_init(void)
Definition: core.c:129
The ROOT-Sim scheduler main module header.
int simulation_time
Wall-clock-time based termination predicate.
Definition: ROOT-Sim.h:285
Generic thread management facilities.
Consistent and Committed Global State.
int stats
Produce performance statistic file (default STATS_ALL)
Definition: ROOT-Sim.h:292
int gvt_time_period
Wall-Clock time to wait before executiong GVT operations.
Definition: ROOT-Sim.h:284
Numerical Library.
int lps_distribution
Policy for the LP to Kernel mapping.
Definition: ROOT-Sim.h:286
int scheduler
Which scheduler to be used.
Definition: init.h:59
simulation_configuration rootsim_config
This global variable holds the configuration for the current simulation.
Definition: core.c:70
void SystemInit(int argc, char **argv)
Definition: init.c:392
Memory Manager main header.
int ckpt_mode
Type of checkpointing mode (Synchronous, Semi-Asyncronous, ...)
Definition: init.h:63
Serial scheduler.
capability_t
Capability enumeration.
Definition: ROOT-Sim.h:245
bool silent_output
Disable any output generated by printf() calls.
Definition: init.h:75
int simulation_time
Wall-clock-time based termination predicate.
Definition: init.h:61
LP control blocks.
bool CapabilityAvailable(enum capability_t which, struct capability_info_t *info)
Query runtime capabilities while executing the model.
Definition: init.c:461
void mpi_init(int *argc, char ***argv)
Initialize MPI subsystem.
Definition: mpi.c:516
void(* ScheduleNewEvent)(unsigned int gid_receiver, simtime_t timestamp, unsigned int event_type, void *event_content, unsigned int event_size)
This is the function pointer to correctly set ScheduleNewEvent API version, depending if we&#39;re runnin...
Definition: communication.c:50
#define get_cores()
Macro to get the core count on the hosting machine.
Definition: thread.h:48
MPI Support Module.
LP state management.
#define bitmap_check(bitmap, bit_index)
This checks if the bit with index bit_index of the bitmap bitmap is set or unset. ...
Definition: bitmap.h:135
Bitmap data type.
#define MAX_KERNELS
Definition: thread.h:129
const char *const param_to_text[][5]
Definition: init.c:98
Global Virtual Time.
#define MAX_LPs
Maximum number of LPs the simulator will handle.
Definition: core.h:59
enum stats_levels stats
Produce performance statistic file (default STATS_ALL)
Definition: init.h:70
int lps_distribution
Policy for the LP to Kernel mapping.
Definition: init.h:62
const char * output_dir
Destination Directory of output files.
Definition: ROOT-Sim.h:282
int snapshot
Type of snapshot (e.g., full, incremental, autonomic, ...)
Definition: init.h:66
void communication_init(void)
Initialize the communication subsystem.
Definition: communication.c:59
int state_saving
Type of checkpointing mode (Synchronous, Semi-Asyncronous, ...)
Definition: ROOT-Sim.h:287
bool core_binding
Bind threads to specific core (reduce context switches and cache misses)
Definition: init.h:73
Event & Cross State Synchornization.
int termination_mode
Check termination strategy: standard or incremental.
Definition: ROOT-Sim.h:290
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
bool serial
If the simulation must be run serially.
Definition: init.h:71
unsigned char rootsim_bitmap
This defines a generic bitmap.
Definition: bitmap.h:43
bool disable_preemption
If compiled for preemptive Time Warp, it can be disabled at runtime.
Definition: init.h:74
unsigned int n_ker
Total number of simulation kernel instances running.
Definition: core.c:58