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. */
12 #include <type_traits>
20 #include <simgrid/s4u/host.hpp>
22 #include "src/simix/smx_private.h"
23 #include "src/mc/mc_smx.h"
24 #include "src/mc/ModelChecker.hpp"
26 using simgrid::mc::remote;
28 /** HACK, Statically "upcast" a s_smx_process_t into a SimixProcessInformation
30 * This gets 'processInfo' from '&processInfo->copy'. It upcasts in the
31 * sense that we could achieve the same thing by having SimixProcessInformation
32 * inherit from s_smx_process_t but we don't really want to do that.
35 simgrid::mc::SimixProcessInformation* process_info_cast(smx_process_t p)
37 simgrid::mc::SimixProcessInformation temp;
38 std::size_t offset = (char*) temp.copy.getBuffer() - (char*)&temp;
40 simgrid::mc::SimixProcessInformation* process_info =
41 (simgrid::mc::SimixProcessInformation*) ((char*) p - offset);
45 /** Load the remote swag of processes into a vector
47 * @param process MCed process
48 * @param target Local vector (to be filled with copies of `s_smx_process_t`)
49 * @param remote_swag Address of the process SWAG in the remote list
51 static void MC_process_refresh_simix_process_list(
52 simgrid::mc::Process* process,
53 std::vector<simgrid::mc::SimixProcessInformation>& target,
54 simgrid::mc::RemotePtr<s_xbt_swag_t> remote_swag)
58 // swag = REMOTE(*simix_global->process_list)
60 process->read_bytes(&swag, sizeof(swag), remote_swag);
62 // Load each element of the vector from the MCed process:
64 for (smx_process_t p = (smx_process_t) swag.head; p; ++i) {
66 simgrid::mc::SimixProcessInformation info;
68 info.hostname = nullptr;
69 process->read_bytes(&info.copy, sizeof(info.copy), remote(p));
70 target.push_back(std::move(info));
72 // Lookup next process address:
73 p = (smx_process_t) xbt_swag_getNext(&info.copy, swag.offset);
75 assert(i == swag.count);
81 void Process::refresh_simix()
83 if (this->cache_flags_ & Process::cache_simix_processes)
86 // TODO, avoid to reload `&simix_global`, `simix_global`, `*simix_global`
88 static_assert(std::is_same<
89 std::unique_ptr<simgrid::simix::Global>,
90 decltype(simix_global)
91 >::value, "Unexpected type for simix_global");
92 static_assert(sizeof(simix_global) == sizeof(simgrid::simix::Global*),
93 "Bad size for simix_global");
95 // simix_global_p = REMOTE(simix_global.get());
96 RemotePtr<simgrid::simix::Global> simix_global_p =
97 this->read_variable<simgrid::simix::Global*>("simix_global");
99 // simix_global = REMOTE(*simix_global)
100 Remote<simgrid::simix::Global> simix_global =
101 this->read<simgrid::simix::Global>(simix_global_p);
103 MC_process_refresh_simix_process_list(
104 this, this->smx_process_infos,
105 remote(simix_global.getBuffer()->process_list));
106 MC_process_refresh_simix_process_list(
107 this, this->smx_old_process_infos,
108 remote(simix_global.getBuffer()->process_to_destroy));
110 this->cache_flags_ |= Process::cache_simix_processes;
116 /** Get the issuer of a simcall (`req->issuer`)
118 * In split-process mode, it does the black magic necessary to get an address
119 * of a (shallow) copy of the data structure the issuer SIMIX process in the local
122 * @param process the MCed process
123 * @param req the simcall (copied in the local process)
125 smx_process_t MC_smx_simcall_get_issuer(s_smx_simcall_t const* req)
127 xbt_assert(mc_model_checker != nullptr);
129 // This is the address of the smx_process in the MCed process:
130 auto address = simgrid::mc::remote(req->issuer);
132 // Lookup by address:
133 for (auto& p : mc_model_checker->process().simix_processes())
134 if (p.address == address)
135 return p.copy.getBuffer();
136 for (auto& p : mc_model_checker->process().old_simix_processes())
137 if (p.address == address)
138 return p.copy.getBuffer();
140 xbt_die("Issuer not found");
143 const char* MC_smx_process_get_host_name(smx_process_t p)
145 if (mc_model_checker == nullptr)
146 return sg_host_get_name(p->host);
148 simgrid::mc::Process* process = &mc_model_checker->process();
150 /* HACK, Horrible hack to find the offset of the id in the simgrid::s4u::Host.
152 Offsetof is not supported for non-POD types but this should
153 work in practice for the targets currently supported by the MC
154 as long as we do not add funny features to the Host class
155 (such as virtual base).
157 We are using a (C++11) unrestricted union in order to avoid
158 any construction/destruction of the simgrid::s4u::Host.
161 simgrid::s4u::Host host;
166 const size_t offset = (char*) &foo.host.name() - (char*) &foo.host;
168 // Read the simgrid::xbt::string in the MCed process:
169 simgrid::mc::SimixProcessInformation* info = process_info_cast(p);
170 auto remote_string_address = remote(
171 (simgrid::xbt::string_data*) ((char*) p->host + offset));
172 simgrid::xbt::string_data remote_string = process->read(remote_string_address);
173 char hostname[remote_string.len];
174 process->read_bytes(hostname, remote_string.len + 1, remote(remote_string.data));
175 info->hostname = mc_model_checker->get_host_name(hostname).c_str();
176 return info->hostname;
179 const char* MC_smx_process_get_name(smx_process_t p)
181 simgrid::mc::Process* process = &mc_model_checker->process();
182 if (mc_model_checker == nullptr)
183 return p->name.c_str();
185 simgrid::mc::SimixProcessInformation* info = process_info_cast(p);
186 if (info->name.empty()) {
187 simgrid::xbt::string_data string_data = (simgrid::xbt::string_data&)p->name;
188 info->name = process->read_string(remote(string_data.data), string_data.len);
190 return info->name.c_str();
194 int MC_smpi_process_count(void)
196 if (mc_model_checker == nullptr)
197 return smpi_process_count();
199 mc_model_checker->process().read_variable("process_count",
205 unsigned long MC_smx_get_maxpid(void)
207 unsigned long maxpid;
208 mc_model_checker->process().read_variable("simix_process_maxpid",
209 &maxpid, sizeof(maxpid));