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. */
16 #include "src/simix/smx_private.h"
18 #include "src/mc/mc_smx.h"
19 #include "src/mc/ModelChecker.hpp"
21 using simgrid::mc::remote;
26 bool is_in_vector(smx_process_t p, std::vector<simgrid::mc::SimixProcessInformation>& ps)
28 return (uintptr_t) p >= (uintptr_t) &ps[0]
29 && (uintptr_t) p < (uintptr_t) &ps[ps.size()];
33 simgrid::mc::SimixProcessInformation* MC_smx_process_get_info(smx_process_t p)
35 assert(is_in_vector(p, mc_model_checker->process().smx_process_infos)
36 || is_in_vector(p, mc_model_checker->process().smx_old_process_infos));
37 simgrid::mc::SimixProcessInformation* process_info =
38 (simgrid::mc::SimixProcessInformation*)
39 ((char*) p - offsetof(simgrid::mc::SimixProcessInformation, copy));
43 /** Load the remote swag of processes into a dynar
45 * @param process MCed process
46 * @param target Local dynar (to be filled with copies of `s_smx_process_t`)
47 * @param remote_swag Address of the process SWAG in the remote list
49 static void MC_process_refresh_simix_process_list(
50 simgrid::mc::Process* process,
51 std::vector<simgrid::mc::SimixProcessInformation>& target, xbt_swag_t remote_swag)
55 // swag = REMOTE(*simix_global->process_list)
57 process->read_bytes(&swag, sizeof(swag), remote(remote_swag));
59 // Load each element of the dynar from the MCed process:
61 for (smx_process_t p = (smx_process_t) swag.head; p; ++i) {
63 simgrid::mc::SimixProcessInformation info;
65 info.hostname = nullptr;
66 process->read_bytes(&info.copy, sizeof(info.copy), remote(p));
67 target.push_back(std::move(info));
69 // Lookup next process address:
70 p = (smx_process_t) xbt_swag_getNext(&info.copy, swag.offset);
72 assert(i == swag.count);
78 void Process::refresh_simix()
80 if (this->cache_flags_ & Process::cache_simix_processes)
83 // TODO, avoid to reload `&simix_global`, `simix_global`, `*simix_global`
85 // simix_global_p = REMOTE(simix_global);
86 smx_global_t simix_global_p;
87 this->read_variable("simix_global", &simix_global_p, sizeof(simix_global_p));
89 // simix_global = REMOTE(*simix_global)
90 s_smx_global_t simix_global;
91 this->read_bytes(&simix_global, sizeof(simix_global),
92 remote(simix_global_p));
94 MC_process_refresh_simix_process_list(
95 this, this->smx_process_infos, simix_global.process_list);
96 MC_process_refresh_simix_process_list(
97 this, this->smx_old_process_infos, simix_global.process_to_destroy);
99 this->cache_flags_ |= Process::cache_simix_processes;
105 /** Get the issuer of a simcall (`req->issuer`)
107 * In split-process mode, it does the black magic necessary to get an address
108 * of a (shallow) copy of the data structure the issuer SIMIX process in the local
111 * @param process the MCed process
112 * @param req the simcall (copied in the local process)
114 smx_process_t MC_smx_simcall_get_issuer(smx_simcall_t req)
116 if (mc_mode == MC_MODE_CLIENT)
119 // This is the address of the smx_process in the MCed process:
120 void* address = req->issuer;
122 // Lookup by address:
123 for (auto& p : mc_model_checker->process().simix_processes())
124 if (p.address == address)
126 for (auto& p : mc_model_checker->process().old_simix_processes())
127 if (p.address == address)
130 xbt_die("Issuer not found");
133 smx_process_t MC_smx_resolve_process(smx_process_t process_remote_address)
135 if (!process_remote_address)
137 if (mc_mode == MC_MODE_CLIENT)
138 return process_remote_address;
140 simgrid::mc::SimixProcessInformation* process_info = MC_smx_resolve_process_info(process_remote_address);
142 return &process_info->copy;
147 simgrid::mc::SimixProcessInformation* MC_smx_resolve_process_info(smx_process_t process_remote_address)
149 if (mc_mode == MC_MODE_CLIENT)
150 xbt_die("No process_info for local process is not enabled.");
151 for (auto& process_info : mc_model_checker->process().smx_process_infos)
152 if (process_info.address == process_remote_address)
153 return &process_info;
154 for (auto& process_info : mc_model_checker->process().smx_old_process_infos)
155 if (process_info.address == process_remote_address)
156 return &process_info;
157 xbt_die("Process info not found");
160 const char* MC_smx_process_get_host_name(smx_process_t p)
162 if (mc_mode == MC_MODE_CLIENT)
163 return sg_host_get_name(p->host);
165 simgrid::mc::Process* process = &mc_model_checker->process();
167 /* Horrible hack to find the offset of the id in the simgrid::s4u::Host.
169 Offsetof is not supported for non-POD types but this should
170 work in pratice for the targets currently supported by the MC
171 as long as we do not add funny features to the Host class
172 (such as virtual base).
174 We are using a (C++11) unrestricted union in order to avoid
175 any construction/destruction of the simgrid::s4u::Host.
178 simgrid::s4u::Host host;
183 const size_t offset = (char*) &foo.host.name() - (char*) &foo.host;
185 // Read the simgrid::xbt::string in the MCed process:
186 simgrid::mc::SimixProcessInformation* info = MC_smx_process_get_info(p);
187 simgrid::xbt::string_data remote_string;
188 auto remote_string_address = remote(
189 (simgrid::xbt::string_data*) ((char*) p->host + offset));
190 process->read_bytes(&remote_string, sizeof(remote_string), remote_string_address);
191 char hostname[remote_string.len];
192 process->read_bytes(hostname, remote_string.len + 1, remote(remote_string.data));
193 info->hostname = mc_model_checker->get_host_name(hostname);
194 return info->hostname;
197 const char* MC_smx_process_get_name(smx_process_t p)
199 simgrid::mc::Process* process = &mc_model_checker->process();
200 if (mc_mode == MC_MODE_CLIENT)
205 simgrid::mc::SimixProcessInformation* info = MC_smx_process_get_info(p);
206 if (info->name.empty()) {
207 char* name = process->read_string(p->name);
211 return info->name.c_str();
215 int MC_smpi_process_count(void)
217 if (mc_mode == MC_MODE_CLIENT)
218 return smpi_process_count();
220 mc_model_checker->process().read_variable("process_count",
226 unsigned long MC_smx_get_maxpid(void)
228 unsigned long maxpid;
229 mc_model_checker->process().read_variable("simix_process_maxpid",
230 &maxpid, sizeof(maxpid));