Line data Source code
1 1 : /** 2 : * @file scheduler/process.c 3 : * 4 : * @brief Generic LP management functions 5 : * 6 : * Generic LP management functions 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 Alessandro Pellegrini 27 : * @author Francesco Quaglia 28 : * 29 : * @date December 14, 2017 30 : */ 31 : 32 : #include <limits.h> 33 : 34 : #include <core/core.h> 35 : #include <core/init.h> 36 : #include <scheduler/process.h> 37 : #include <scheduler/scheduler.h> 38 : 39 : // TODO: see issue #121 to see how to make this ugly hack disappear 40 0 : __thread unsigned int __lp_counter = 0; 41 0 : __thread unsigned int __lp_bound_counter = 0; 42 : 43 : /// Maintain LPs' simulation and execution states 44 1 : struct lp_struct **lps_blocks = NULL; 45 : 46 : /** Each KLT has a binding towards some LPs. This is the structure used 47 : * to keep track of LPs currently being handled 48 : */ 49 1 : __thread struct lp_struct **lps_bound_blocks = NULL; 50 : 51 0 : void initialize_binding_blocks(void) 52 : { 53 : lps_bound_blocks = 54 : (struct lp_struct **)rsalloc(n_prc * sizeof(struct lp_struct *)); 55 : bzero(lps_bound_blocks, sizeof(struct lp_struct *) * n_prc); 56 : } 57 : 58 0 : void initialize_lps(void) 59 : { 60 : unsigned int i, j; 61 : unsigned int lid = 0; 62 : struct lp_struct *lp; 63 : unsigned int local = 0; 64 : GID_t gid; 65 : 66 : // First of all, determine what LPs should be locally hosted. 67 : // Only for them, we are creating struct lp_structs here. 68 : distribute_lps_on_kernels(); 69 : 70 : // We now know how many LPs should be locally hosted. Prepare 71 : // the place for their control blocks. 72 : lps_blocks = 73 : (struct lp_struct **)rsalloc(n_prc * sizeof(struct lp_struct *)); 74 : 75 : // We now iterate over all LP Gids. Everytime that we find an LP 76 : // which should be locally hosted, we create the local lp_struct 77 : // process control block. 78 : for (i = 0; i < n_prc_tot; i++) { 79 : set_gid(gid, i); 80 : if (find_kernel_by_gid(gid) != kid) 81 : continue; 82 : 83 : // Initialize the control block for the current lp 84 : lp = (struct lp_struct *)rsalloc(sizeof(struct lp_struct)); 85 : bzero(lp, sizeof(struct lp_struct)); 86 : lps_blocks[local++] = lp; 87 : 88 : if (local > n_prc) { 89 : printf("reached local %d\n", local); 90 : fflush(stdout); 91 : abort(); 92 : } 93 : // Initialize memory map 94 : initialize_memory_map(lp); 95 : 96 : // Allocate memory for the outgoing buffer 97 : lp->outgoing_buffer.max_size = INIT_OUTGOING_MSG; 98 : lp->outgoing_buffer.outgoing_msgs = 99 : rsalloc(sizeof(msg_t *) * INIT_OUTGOING_MSG); 100 : 101 : // Initialize bottom halves msg channel 102 : lp->bottom_halves = init_channel(); 103 : 104 : // We sequentially assign lids, and use the current gid 105 : lp->lid.to_int = lid++; 106 : lp->gid = gid; 107 : 108 : // Which version of OnGVT and ProcessEvent should we use? 109 : if (rootsim_config.snapshot == SNAPSHOT_FULL) { 110 : lp->OnGVT = &OnGVT_light; 111 : lp->ProcessEvent = &ProcessEvent_light; 112 : } // TODO: add here an else for ISS 113 : 114 : // Allocate LP stack 115 : lp->stack = get_ult_stack(LP_STACK_SIZE); 116 : 117 : // Set the initial checkpointing period for this LP. 118 : // If the checkpointing period is fixed, this will not change during the 119 : // execution. Otherwise, new calls to this function will (locally) update 120 : // this. 121 : set_checkpoint_period(lp, rootsim_config.ckpt_period); 122 : 123 : // Initially, every LP is ready 124 : lp->state = LP_STATE_READY; 125 : 126 : // There is no current state layout at the beginning 127 : lp->current_base_pointer = NULL; 128 : 129 : // Initialize the queues 130 : lp->queue_in = new_list(msg_t); 131 : lp->queue_out = new_list(msg_hdr_t); 132 : lp->queue_states = new_list(state_t); 133 : lp->rendezvous_queue = new_list(msg_t); 134 : 135 : // No event has been processed so far 136 : lp->bound = NULL; 137 : 138 : // We have no information about messages still to be delivered to this LP 139 : lp->outgoing_buffer.min_in_transit = rsalloc(sizeof(simtime_t) * n_cores); 140 : for (j = 0; j < n_cores; j++) { 141 : lp->outgoing_buffer.min_in_transit[j] = INFTY; 142 : } 143 : 144 : #ifdef HAVE_CROSS_STATE 145 : // No read/write dependencies open so far for the LP. The current lp is always opened 146 : lp->ECS_index = 0; 147 : lp->ECS_synch_table[0] = LidToGid(lp); // LidToGid for distributed ECS 148 : #endif 149 : 150 : // Create User-Level Thread 151 : context_create(&lp->context, LP_main_loop, NULL, lp->stack, 152 : LP_STACK_SIZE); 153 : } 154 : } 155 : 156 : // This works only for locally-hosted LPs! 157 0 : struct lp_struct *find_lp_by_gid(GID_t gid) 158 : { 159 : foreach_lp(lp) { 160 : if (lp->gid.to_int == gid.to_int) 161 : return lp; 162 : } 163 : return NULL; 164 : }