LCOV - code coverage report
Current view: top level - ROOT-Sim/src/core - core.c Hit Total Coverage
Test: doc-coverage.info Lines: 20 24 83.3 %
Date: 2020-02-28 13:00:44

          Line data    Source code
       1           1 : /**
       2             : * @file core/core.c
       3             : *
       4             : * @brief Core ROOT-Sim functionalities
       5             : *
       6             : * Core ROOT-Sim functionalities
       7             : *
       8             : * @copyright
       9             : * Copyright (C) 2008-2019 HPDCS Group
      10             : * https://hpdcs.github.io
      11             : *
      12             : * This file is part of ROOT-Sim (ROme OpTimistic Simulator).
      13             : *
      14             : * ROOT-Sim is free software; you can redistribute it and/or modify it under the
      15             : * terms of the GNU General Public License as published by the Free Software
      16             : * Foundation; only version 3 of the License applies.
      17             : *
      18             : * ROOT-Sim is distributed in the hope that it will be useful, but WITHOUT ANY
      19             : * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
      20             : * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
      21             : *
      22             : * You should have received a copy of the GNU General Public License along with
      23             : * ROOT-Sim; if not, write to the Free Software Foundation, Inc.,
      24             : * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
      25             : *
      26             : * @author Francesco Quaglia
      27             : * @author Alessandro Pellegrini
      28             : * @author Roberto Vitali
      29             : *
      30             : * @date 3/18/2011
      31             : */
      32             : 
      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             : 
      48             : /// Barrier for all worker threads
      49           1 : barrier_t all_thread_barrier;
      50             : 
      51             : /// Mapping between kernel instances and logical processes
      52           1 : unsigned int *kernel;
      53             : 
      54             : /// Identifier of the local kernel
      55           1 : unsigned int kid;
      56             : 
      57             : /// Total number of simulation kernel instances running
      58           1 : unsigned int n_ker;
      59             : 
      60             : /// Total number of cores required for simulation
      61           1 : unsigned int n_cores;
      62             : 
      63             : /// Total number of logical processes running in the simulation
      64           1 : unsigned int n_prc_tot;
      65             : 
      66             : /// Number of logical processes hosted by the current kernel instance
      67           1 : unsigned int n_prc;
      68             : 
      69             : /// This global variable holds the configuration for the current simulation
      70           1 : simulation_configuration rootsim_config;
      71             : 
      72             : /// Flag to notify all workers that there was an error
      73           1 : static bool sim_error = false;
      74             : 
      75             : /// This flag tells whether we are exiting from the kernel of from userspace
      76           1 : bool exit_silently_from_kernel = false;
      77             : 
      78             : /// This flag is set when the initialization of the simulator is complete, with no errors
      79           1 : static bool init_complete = false;
      80             : 
      81           0 : bool user_exit_flag = false;
      82             : 
      83             : /**
      84             :  * This function is used to terminate with not much pain the simulation
      85             :  * if the user model inadvertently calls exit(). It displays a warning
      86             :  * message, and then tries to silently shutdown.
      87             :  * The software enters this function using the standard atexit() API.
      88             :  *
      89             :  * @author Alessandro Pellegrini
      90             :  */
      91           1 : void exit_from_simulation_model(void)
      92             : {
      93             : 
      94             :         if (likely(!init_complete))
      95             :                 return;
      96             : 
      97             :         if (unlikely(!exit_silently_from_kernel)) {
      98             :                 exit_silently_from_kernel = true;
      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           0 : inline bool user_requested_exit(void)
     109             : {
     110             :         return user_exit_flag;
     111             : }
     112             : 
     113           0 : static void handle_signal(int signum)
     114             : {
     115             :         if (signum == SIGINT) {
     116             :                 user_exit_flag = true;
     117             :         }
     118             : }
     119             : 
     120             : /**
     121             : * This function initilizes basic functionalities within ROOT-Sim. In particular, it
     122             : * creates a mapping between logical processes and kernel instances.
     123             : *
     124             : * @author Francesco Quaglia
     125             : * @author Roberto Vitali
     126             : * @author Alessandro Pellegrini
     127             : *
     128             : */
     129           1 : 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
     142             :         atexit(exit_from_simulation_model);
     143             : }
     144             : 
     145             : /**
     146             : * This function finalizes the core structures of ROOT-Sim, just before terminating a simulation
     147             : *
     148             : * @author Roberto Vitali
     149             : *
     150             : */
     151           1 : void base_fini(void)
     152             : {
     153             : }
     154             : 
     155             : /**
     156             : * Creates a mapping between logical processes and kernel instances
     157             : *
     158             : * @author Francesco Quaglia
     159             : *
     160             : * @param gid The logical process' global identifier
     161             : * @return The id of the kernel currently hosting the logical process
     162             : */
     163             : __attribute__((pure))
     164           1 : 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             : 
     170             : /**
     171             : * This function calls all the finalization functions exposed by subsystems and then
     172             : * exits.
     173             : *
     174             : * @author Alessandro Pellegrini
     175             : *
     176             : * @param code The exit code to be returned by the process
     177             : */
     178           1 : void simulation_shutdown(int code)
     179             : {
     180             : 
     181             :         exit_silently_from_kernel = true;
     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();
     192             :                         communication_fini();
     193             :                         scheduler_fini();
     194             :                         base_fini();
     195             :                 }
     196             : 
     197             :                 thread_barrier(&all_thread_barrier);
     198             :         }
     199             : 
     200             :         exit(code);
     201             : }
     202             : 
     203           0 : inline bool simulation_error(void)
     204             : {
     205             :         return sim_error;
     206             : }
     207             : 
     208             : /**
     209             : * A variadic function which prints out error messages. If the errors are marked as fatal,
     210             : * the simulation is correctly shut down.
     211             : *
     212             : * @author Alessandro Pellegrini
     213             : *
     214             : * @param fatal This flag marks an error as fatal (true) or not (false)
     215             : * @param msg The error message to be printed out. This can be specified as in the printf()
     216             : *        format message, thus a matching number of extra parameters can be passed.
     217             : *
     218             : * @todo If a fatal error is received, write it on the log file as well!
     219             : */
     220           1 : 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             : 
     252             : /**
     253             : * This function maps logical processes onto kernel instances
     254             : *
     255             : * @author Francesco Quaglia
     256             : * @author Alessandro Pellegrini
     257             : */
     258           1 : void distribute_lps_on_kernels(void)
     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             : 
     275             :         case LP_DISTRIBUTION_BLOCK:
     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             : 
     302             :         case LP_DISTRIBUTION_CIRCULAR:
     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             : 
     313             : /**
     314             :  * This function records that the initialization is complete.
     315             :  */
     316           1 : void initialization_complete(void)
     317             : {
     318             :         init_complete = true;
     319             : }

Generated by: LCOV version 1.12