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 : // We sequentially assign lids, and use the current gid
94 : lp->lid.to_int = lid++;
95 : lp->gid = gid;
96 :
97 : // Initialize memory map
98 : initialize_memory_map(lp);
99 :
100 : // Allocate memory for the outgoing buffer
101 : lp->outgoing_buffer.max_size = INIT_OUTGOING_MSG;
102 : lp->outgoing_buffer.outgoing_msgs =
103 : rsalloc(sizeof(msg_t *) * INIT_OUTGOING_MSG);
104 :
105 : // Initialize bottom halves msg channel
106 : lp->bottom_halves = init_channel();
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 : }
|