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 vector
45 * @param process MCed process
46 * @param target Local vector (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 vector 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(s_smx_simcall_t const* req)
116 xbt_assert(mc_mode == MC_MODE_SERVER);
118 // This is the address of the smx_process in the MCed process:
119 auto address = simgrid::mc::remote(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 const char* MC_smx_process_get_host_name(smx_process_t p)
134 if (mc_mode == MC_MODE_CLIENT)
135 return sg_host_get_name(p->host);
137 simgrid::mc::Process* process = &mc_model_checker->process();
139 /* HACK, Horrible hack to find the offset of the id in the simgrid::s4u::Host.
141 Offsetof is not supported for non-POD types but this should
142 work in pratice for the targets currently supported by the MC
143 as long as we do not add funny features to the Host class
144 (such as virtual base).
146 We are using a (C++11) unrestricted union in order to avoid
147 any construction/destruction of the simgrid::s4u::Host.
150 simgrid::s4u::Host host;
155 const size_t offset = (char*) &foo.host.name() - (char*) &foo.host;
157 // Read the simgrid::xbt::string in the MCed process:
158 simgrid::mc::SimixProcessInformation* info = MC_smx_process_get_info(p);
159 simgrid::xbt::string_data remote_string;
160 auto remote_string_address = remote(
161 (simgrid::xbt::string_data*) ((char*) p->host + offset));
162 process->read_bytes(&remote_string, sizeof(remote_string), remote_string_address);
163 char hostname[remote_string.len];
164 process->read_bytes(hostname, remote_string.len + 1, remote(remote_string.data));
165 info->hostname = mc_model_checker->get_host_name(hostname);
166 return info->hostname;
169 const char* MC_smx_process_get_name(smx_process_t p)
171 simgrid::mc::Process* process = &mc_model_checker->process();
172 if (mc_mode == MC_MODE_CLIENT)
177 simgrid::mc::SimixProcessInformation* info = MC_smx_process_get_info(p);
178 if (info->name.empty())
179 info->name = process->read_string(p->name);
180 return info->name.c_str();
184 int MC_smpi_process_count(void)
186 if (mc_mode == MC_MODE_CLIENT)
187 return smpi_process_count();
189 mc_model_checker->process().read_variable("process_count",
195 unsigned long MC_smx_get_maxpid(void)
197 unsigned long maxpid;
198 mc_model_checker->process().read_variable("simix_process_maxpid",
199 &maxpid, sizeof(maxpid));