1 /* Copyright (c) 2015. The SimGrid Team.
2 * All rights reserved. */
4 /* This program is free software; you can redistribute it and/or modify it
5 * under the terms of the license (GNU LGPL) which comes with this package. */
11 #include <xbt/dynar.h>
15 #include "src/simix/smx_private.h"
17 #include "src/mc/mc_smx.h"
18 #include "src/mc/ModelChecker.hpp"
20 using simgrid::mc::remote;
25 bool is_in_vector(smx_process_t p, std::vector<simgrid::mc::SimixProcessInformation>& ps)
27 return (uintptr_t) p >= (uintptr_t) &ps[0]
28 && (uintptr_t) p < (uintptr_t) &ps[ps.size()];
32 simgrid::mc::SimixProcessInformation* MC_smx_process_get_info(smx_process_t p)
34 assert(is_in_vector(p, mc_model_checker->process().smx_process_infos)
35 || is_in_vector(p, mc_model_checker->process().smx_old_process_infos));
36 simgrid::mc::SimixProcessInformation* process_info =
37 (simgrid::mc::SimixProcessInformation*)
38 ((char*) p - offsetof(simgrid::mc::SimixProcessInformation, copy));
42 /** Load the remote swag of processes into a dynar
44 * @param process MCed process
45 * @param target Local dynar (to be filled with copies of `s_smx_process_t`)
46 * @param remote_swag Address of the process SWAG in the remote list
48 static void MC_process_refresh_simix_process_list(
49 simgrid::mc::Process* process,
50 std::vector<simgrid::mc::SimixProcessInformation>& target, xbt_swag_t remote_swag)
54 // swag = REMOTE(*simix_global->process_list)
56 process->read_bytes(&swag, sizeof(swag), remote(remote_swag));
58 // Load each element of the dynar from the MCed process:
60 for (smx_process_t p = (smx_process_t) swag.head; p; ++i) {
62 simgrid::mc::SimixProcessInformation info;
64 info.hostname = nullptr;
65 process->read_bytes(&info.copy, sizeof(info.copy), remote(p));
66 target.push_back(std::move(info));
68 // Lookup next process address:
69 p = (smx_process_t) xbt_swag_getNext(&info.copy, swag.offset);
71 assert(i == swag.count);
74 void MC_process_smx_refresh(simgrid::mc::Process* process)
76 xbt_assert(mc_mode == MC_MODE_SERVER);
77 if (process->cache_flags & MC_PROCESS_CACHE_FLAG_SIMIX_PROCESSES)
80 // TODO, avoid to reload `&simix_global`, `simix_global`, `*simix_global`
82 // simix_global_p = REMOTE(simix_global);
83 smx_global_t simix_global_p;
84 process->read_variable("simix_global", &simix_global_p, sizeof(simix_global_p));
86 // simix_global = REMOTE(*simix_global)
87 s_smx_global_t simix_global;
88 process->read_bytes(&simix_global, sizeof(simix_global),
89 remote(simix_global_p));
91 MC_process_refresh_simix_process_list(
92 process, process->smx_process_infos, simix_global.process_list);
93 MC_process_refresh_simix_process_list(
94 process, process->smx_old_process_infos, simix_global.process_to_destroy);
96 process->cache_flags |= MC_PROCESS_CACHE_FLAG_SIMIX_PROCESSES;
99 /** Get the issuer of a simcall (`req->issuer`)
101 * In split-process mode, it does the black magic necessary to get an address
102 * of a (shallow) copy of the data structure the issuer SIMIX process in the local
105 * @param process the MCed process
106 * @param req the simcall (copied in the local process)
108 smx_process_t MC_smx_simcall_get_issuer(smx_simcall_t req)
110 if (mc_mode == MC_MODE_CLIENT)
113 MC_process_smx_refresh(&mc_model_checker->process());
115 // This is the address of the smx_process in the MCed process:
116 void* address = req->issuer;
118 // Lookup by address:
119 for (auto& p : mc_model_checker->process().smx_process_infos)
120 if (p.address == address)
122 for (auto& p : mc_model_checker->process().smx_old_process_infos)
123 if (p.address == address)
126 xbt_die("Issuer not found");
129 smx_process_t MC_smx_resolve_process(smx_process_t process_remote_address)
131 if (!process_remote_address)
133 if (mc_mode == MC_MODE_CLIENT)
134 return process_remote_address;
136 simgrid::mc::SimixProcessInformation* process_info = MC_smx_resolve_process_info(process_remote_address);
138 return &process_info->copy;
143 simgrid::mc::SimixProcessInformation* MC_smx_resolve_process_info(smx_process_t process_remote_address)
145 if (mc_mode == MC_MODE_CLIENT)
146 xbt_die("No process_info for local process is not enabled.");
147 for (auto& process_info : mc_model_checker->process().smx_process_infos)
148 if (process_info.address == process_remote_address)
149 return &process_info;
150 for (auto& process_info : mc_model_checker->process().smx_old_process_infos)
151 if (process_info.address == process_remote_address)
152 return &process_info;
153 xbt_die("Process info not found");
156 const char* MC_smx_process_get_host_name(smx_process_t p)
158 if (mc_mode == MC_MODE_CLIENT)
159 return sg_host_get_name(p->host);
161 simgrid::mc::Process* process = &mc_model_checker->process();
163 /* Horrible hack to find the offset of the id in the simgrid::s4u::Host.
165 Offsetof is not supported for non-POD types but this should
166 work in pratice for the targets currently supported by the MC
167 as long as we do not add funny features to the Host class
168 (such as virtual base).
170 We are using a (C++11) unrestricted union in order to avoid
171 any construction/destruction of the simgrid::s4u::Host.
174 simgrid::s4u::Host host;
179 const size_t offset = (char*) &foo.host.name() - (char*) &foo.host;
181 // Read the simgrid::xbt::string in the MCed process:
182 simgrid::mc::SimixProcessInformation* info = MC_smx_process_get_info(p);
183 simgrid::xbt::string_data remote_string;
184 auto remote_string_address = remote(
185 (simgrid::xbt::string_data*) ((char*) p->host + offset));
186 process->read_bytes(&remote_string, sizeof(remote_string), remote_string_address);
187 char hostname[remote_string.len];
188 process->read_bytes(hostname, remote_string.len + 1, remote(remote_string.data));
189 info->hostname = mc_model_checker->get_host_name(hostname);
190 return info->hostname;
193 const char* MC_smx_process_get_name(smx_process_t p)
195 simgrid::mc::Process* process = &mc_model_checker->process();
196 if (mc_mode == MC_MODE_CLIENT)
201 simgrid::mc::SimixProcessInformation* info = MC_smx_process_get_info(p);
202 if (info->name.empty()) {
203 char* name = process->read_string(p->name);
207 return info->name.c_str();
211 int MC_smpi_process_count(void)
213 if (mc_mode == MC_MODE_CLIENT)
214 return smpi_process_count();
216 mc_model_checker->process().read_variable("process_count",
222 unsigned long MC_smx_get_maxpid(void)
224 unsigned long maxpid;
225 mc_model_checker->process().read_variable("simix_process_maxpid",
226 &maxpid, sizeof(maxpid));