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;
23 /** HACK, Statically "upcast" a s_smx_process_t into a SimixProcessInformation
25 * This gets 'processInfo' from '&processInfo->copy'. It upcasts in the
26 * sense that we could achieve the same thing by having SimixProcessInformation
27 * inherit from s_smx_process_t but we don't really want to do that.
30 simgrid::mc::SimixProcessInformation* process_info_cast(smx_process_t p)
32 simgrid::mc::SimixProcessInformation temp;
33 std::size_t offset = (char*) temp.copy.getBuffer() - (char*)&temp;
35 simgrid::mc::SimixProcessInformation* process_info =
36 (simgrid::mc::SimixProcessInformation*) ((char*) p - offset);
40 /** Load the remote swag of processes into a vector
42 * @param process MCed process
43 * @param target Local vector (to be filled with copies of `s_smx_process_t`)
44 * @param remote_swag Address of the process SWAG in the remote list
46 static void MC_process_refresh_simix_process_list(
47 simgrid::mc::Process* process,
48 std::vector<simgrid::mc::SimixProcessInformation>& target,
49 simgrid::mc::RemotePtr<s_xbt_swag_t> remote_swag)
53 // swag = REMOTE(*simix_global->process_list)
55 process->read_bytes(&swag, sizeof(swag), remote_swag);
57 // Load each element of the vector from the MCed process:
59 for (smx_process_t p = (smx_process_t) swag.head; p; ++i) {
61 simgrid::mc::SimixProcessInformation info;
63 info.hostname = nullptr;
64 process->read_bytes(&info.copy, sizeof(info.copy), remote(p));
65 target.push_back(std::move(info));
67 // Lookup next process address:
68 p = (smx_process_t) xbt_swag_getNext(&info.copy, swag.offset);
70 assert(i == swag.count);
76 void Process::refresh_simix()
78 if (this->cache_flags_ & Process::cache_simix_processes)
81 // TODO, avoid to reload `&simix_global`, `simix_global`, `*simix_global`
83 static_assert(std::is_same<
84 std::unique_ptr<simgrid::simix::Global>,
85 decltype(simix_global)
86 >::value, "Unexpected type for simix_global");
87 static_assert(sizeof(simix_global) == sizeof(simgrid::simix::Global*),
88 "Bad size for simix_global");
90 // simix_global_p = REMOTE(simix_global.get());
91 RemotePtr<simgrid::simix::Global> simix_global_p =
92 this->read_variable<simgrid::simix::Global*>("simix_global");
94 // simix_global = REMOTE(*simix_global)
95 Remote<simgrid::simix::Global> simix_global =
96 this->read<simgrid::simix::Global>(simix_global_p);
98 MC_process_refresh_simix_process_list(
99 this, this->smx_process_infos,
100 remote(simix_global.getBuffer()->process_list));
101 MC_process_refresh_simix_process_list(
102 this, this->smx_old_process_infos,
103 remote(simix_global.getBuffer()->process_to_destroy));
105 this->cache_flags_ |= Process::cache_simix_processes;
111 /** Get the issuer of a simcall (`req->issuer`)
113 * In split-process mode, it does the black magic necessary to get an address
114 * of a (shallow) copy of the data structure the issuer SIMIX process in the local
117 * @param process the MCed process
118 * @param req the simcall (copied in the local process)
120 smx_process_t MC_smx_simcall_get_issuer(s_smx_simcall_t const* req)
122 xbt_assert(mc_model_checker != nullptr);
124 // This is the address of the smx_process in the MCed process:
125 auto address = simgrid::mc::remote(req->issuer);
127 // Lookup by address:
128 for (auto& p : mc_model_checker->process().simix_processes())
129 if (p.address == address)
130 return p.copy.getBuffer();
131 for (auto& p : mc_model_checker->process().old_simix_processes())
132 if (p.address == address)
133 return p.copy.getBuffer();
135 xbt_die("Issuer not found");
138 const char* MC_smx_process_get_host_name(smx_process_t p)
140 if (mc_model_checker == nullptr)
141 return sg_host_get_name(p->host);
143 simgrid::mc::Process* process = &mc_model_checker->process();
145 /* HACK, Horrible hack to find the offset of the id in the simgrid::s4u::Host.
147 Offsetof is not supported for non-POD types but this should
148 work in practice for the targets currently supported by the MC
149 as long as we do not add funny features to the Host class
150 (such as virtual base).
152 We are using a (C++11) unrestricted union in order to avoid
153 any construction/destruction of the simgrid::s4u::Host.
156 simgrid::s4u::Host host;
161 const size_t offset = (char*) &foo.host.name() - (char*) &foo.host;
163 // Read the simgrid::xbt::string in the MCed process:
164 simgrid::mc::SimixProcessInformation* info = process_info_cast(p);
165 auto remote_string_address = remote(
166 (simgrid::xbt::string_data*) ((char*) p->host + offset));
167 simgrid::xbt::string_data remote_string = process->read(remote_string_address);
168 char hostname[remote_string.len];
169 process->read_bytes(hostname, remote_string.len + 1, remote(remote_string.data));
170 info->hostname = mc_model_checker->get_host_name(hostname);
171 return info->hostname;
174 const char* MC_smx_process_get_name(smx_process_t p)
176 simgrid::mc::Process* process = &mc_model_checker->process();
177 if (mc_model_checker == nullptr)
178 return p->name.c_str();
180 simgrid::mc::SimixProcessInformation* info = process_info_cast(p);
181 if (info->name.empty()) {
182 simgrid::xbt::string_data string_data = (simgrid::xbt::string_data&)p->name;
183 info->name = process->read_string(remote(string_data.data), string_data.len);
185 return info->name.c_str();
189 int MC_smpi_process_count(void)
191 if (mc_model_checker == nullptr)
192 return smpi_process_count();
194 mc_model_checker->process().read_variable("process_count",
200 unsigned long MC_smx_get_maxpid(void)
202 unsigned long maxpid;
203 mc_model_checker->process().read_variable("simix_process_maxpid",
204 &maxpid, sizeof(maxpid));