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);
77 void Process::refresh_simix()
79 if (this->cache_flags_ & Process::cache_simix_processes)
82 // TODO, avoid to reload `&simix_global`, `simix_global`, `*simix_global`
84 // simix_global_p = REMOTE(simix_global);
85 smx_global_t simix_global_p;
86 this->read_variable("simix_global", &simix_global_p, sizeof(simix_global_p));
88 // simix_global = REMOTE(*simix_global)
89 s_smx_global_t simix_global;
90 this->read_bytes(&simix_global, sizeof(simix_global),
91 remote(simix_global_p));
93 MC_process_refresh_simix_process_list(
94 this, this->smx_process_infos, simix_global.process_list);
95 MC_process_refresh_simix_process_list(
96 this, this->smx_old_process_infos, simix_global.process_to_destroy);
98 this->cache_flags_ |= Process::cache_simix_processes;
104 /** Get the issuer of a simcall (`req->issuer`)
106 * In split-process mode, it does the black magic necessary to get an address
107 * of a (shallow) copy of the data structure the issuer SIMIX process in the local
110 * @param process the MCed process
111 * @param req the simcall (copied in the local process)
113 smx_process_t MC_smx_simcall_get_issuer(smx_simcall_t req)
115 if (mc_mode == MC_MODE_CLIENT)
118 // This is the address of the smx_process in the MCed process:
119 void* address = req->issuer;
121 // Lookup by address:
122 for (auto& p : mc_model_checker->process().simix_processes())
123 if (p.address == address)
125 for (auto& p : mc_model_checker->process().old_simix_processes())
126 if (p.address == address)
129 xbt_die("Issuer not found");
132 smx_process_t MC_smx_resolve_process(smx_process_t process_remote_address)
134 if (!process_remote_address)
136 if (mc_mode == MC_MODE_CLIENT)
137 return process_remote_address;
139 simgrid::mc::SimixProcessInformation* process_info = MC_smx_resolve_process_info(process_remote_address);
141 return &process_info->copy;
146 simgrid::mc::SimixProcessInformation* MC_smx_resolve_process_info(smx_process_t process_remote_address)
148 if (mc_mode == MC_MODE_CLIENT)
149 xbt_die("No process_info for local process is not enabled.");
150 for (auto& process_info : mc_model_checker->process().smx_process_infos)
151 if (process_info.address == process_remote_address)
152 return &process_info;
153 for (auto& process_info : mc_model_checker->process().smx_old_process_infos)
154 if (process_info.address == process_remote_address)
155 return &process_info;
156 xbt_die("Process info not found");
159 const char* MC_smx_process_get_host_name(smx_process_t p)
161 if (mc_mode == MC_MODE_CLIENT)
162 return sg_host_get_name(p->host);
164 simgrid::mc::Process* process = &mc_model_checker->process();
166 /* Horrible hack to find the offset of the id in the simgrid::s4u::Host.
168 Offsetof is not supported for non-POD types but this should
169 work in pratice for the targets currently supported by the MC
170 as long as we do not add funny features to the Host class
171 (such as virtual base).
173 We are using a (C++11) unrestricted union in order to avoid
174 any construction/destruction of the simgrid::s4u::Host.
177 simgrid::s4u::Host host;
182 const size_t offset = (char*) &foo.host.name() - (char*) &foo.host;
184 // Read the simgrid::xbt::string in the MCed process:
185 simgrid::mc::SimixProcessInformation* info = MC_smx_process_get_info(p);
186 simgrid::xbt::string_data remote_string;
187 auto remote_string_address = remote(
188 (simgrid::xbt::string_data*) ((char*) p->host + offset));
189 process->read_bytes(&remote_string, sizeof(remote_string), remote_string_address);
190 char hostname[remote_string.len];
191 process->read_bytes(hostname, remote_string.len + 1, remote(remote_string.data));
192 info->hostname = mc_model_checker->get_host_name(hostname);
193 return info->hostname;
196 const char* MC_smx_process_get_name(smx_process_t p)
198 simgrid::mc::Process* process = &mc_model_checker->process();
199 if (mc_mode == MC_MODE_CLIENT)
204 simgrid::mc::SimixProcessInformation* info = MC_smx_process_get_info(p);
205 if (info->name.empty()) {
206 char* name = process->read_string(p->name);
210 return info->name.c_str();
214 int MC_smpi_process_count(void)
216 if (mc_mode == MC_MODE_CLIENT)
217 return smpi_process_count();
219 mc_model_checker->process().read_variable("process_count",
225 unsigned long MC_smx_get_maxpid(void)
227 unsigned long maxpid;
228 mc_model_checker->process().read_variable("simix_process_maxpid",
229 &maxpid, sizeof(maxpid));