1 /* Copyright (c) 2015-2017. The SimGrid Team. All rights reserved. */
3 /* This program is free software; you can redistribute it and/or modify it
4 * under the terms of the license (GNU LGPL) which comes with this package. */
11 #include <type_traits>
19 #include <simgrid/s4u/host.hpp>
21 #include "src/simix/smx_private.h"
22 #include "src/mc/mc_smx.h"
23 #include "src/mc/ModelChecker.hpp"
25 using simgrid::mc::remote;
27 /** HACK, Statically "upcast" a s_smx_actor_t into a ActorInformation
29 * This gets 'actorInfo' from '&actorInfo->copy'. It upcasts in the
30 * sense that we could achieve the same thing by having ActorInformation
31 * inherit from s_smx_actor_t but we don't really want to do that.
33 static inline simgrid::mc::ActorInformation* actor_info_cast(smx_actor_t actor)
35 simgrid::mc::ActorInformation temp;
36 std::size_t offset = (char*) temp.copy.getBuffer() - (char*)&temp;
38 simgrid::mc::ActorInformation* process_info = (simgrid::mc::ActorInformation*)((char*)actor - offset);
42 /** Load the remote swag of processes into a vector
44 * @param process MCed process
45 * @param target Local vector (to be filled with copies of `s_smx_actor_t`)
46 * @param remote_swag Address of the process SWAG in the remote list
48 static void MC_process_refresh_simix_process_list(simgrid::mc::Process* process,
49 std::vector<simgrid::mc::ActorInformation>& target,
50 simgrid::mc::RemotePtr<s_xbt_swag_t> remote_swag)
54 // swag = REMOTE(*simix_global->process_list)
56 process->read_bytes(&swag, sizeof(swag), remote_swag);
58 // Load each element of the vector from the MCed process:
60 for (smx_actor_t p = (smx_actor_t) swag.head; p; ++i) {
62 simgrid::mc::ActorInformation 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_actor_t) xbt_swag_getNext(&info.copy, swag.offset);
71 assert(i == swag.count);
74 static void MC_process_refresh_simix_actor_dynar(simgrid::mc::Process* process,
75 std::vector<simgrid::mc::ActorInformation>& target,
76 simgrid::mc::RemotePtr<s_xbt_dynar_t> remote_dynar)
81 process->read_bytes(&dynar, sizeof(dynar), remote_dynar);
83 smx_actor_t* data = (smx_actor_t*)malloc(dynar.elmsize * dynar.used);
84 process->read_bytes(data, dynar.elmsize * dynar.used, dynar.data);
86 // Load each element of the vector from the MCed process:
87 for (unsigned int i = 0; i < dynar.used; ++i) {
89 simgrid::mc::ActorInformation info;
90 info.address = data[i];
91 info.hostname = nullptr;
92 process->read_bytes(&info.copy, sizeof(info.copy), remote(data[i]));
93 target.push_back(std::move(info));
100 void Process::refresh_simix()
102 if (this->cache_flags_ & Process::cache_simix_processes)
105 // TODO, avoid to reload `&simix_global`, `simix_global`, `*simix_global`
107 static_assert(std::is_same<
108 std::unique_ptr<simgrid::simix::Global>,
109 decltype(simix_global)
110 >::value, "Unexpected type for simix_global");
111 static_assert(sizeof(simix_global) == sizeof(simgrid::simix::Global*),
112 "Bad size for simix_global");
114 // simix_global_p = REMOTE(simix_global.get());
115 RemotePtr<simgrid::simix::Global> simix_global_p =
116 this->read_variable<simgrid::simix::Global*>("simix_global");
118 // simix_global = REMOTE(*simix_global)
119 Remote<simgrid::simix::Global> simix_global =
120 this->read<simgrid::simix::Global>(simix_global_p);
122 MC_process_refresh_simix_actor_dynar(this, this->smx_actors_infos, remote(simix_global.getBuffer()->actors_vector));
123 MC_process_refresh_simix_process_list(this, this->smx_dead_actors_infos,
124 remote(simix_global.getBuffer()->process_to_destroy));
126 this->cache_flags_ |= Process::cache_simix_processes;
132 /** Get the issuer of a simcall (`req->issuer`)
134 * In split-process mode, it does the black magic necessary to get an address
135 * of a (shallow) copy of the data structure the issuer SIMIX actor in the local
138 * @param process the MCed process
139 * @param req the simcall (copied in the local process)
141 smx_actor_t MC_smx_simcall_get_issuer(s_smx_simcall_t const* req)
143 xbt_assert(mc_model_checker != nullptr);
145 // This is the address of the smx_actor in the MCed process:
146 auto address = simgrid::mc::remote(req->issuer);
148 // Lookup by address:
149 for (auto& actor : mc_model_checker->process().actors())
150 if (actor.address == address)
151 return actor.copy.getBuffer();
152 for (auto& actor : mc_model_checker->process().dead_actors())
153 if (actor.address == address)
154 return actor.copy.getBuffer();
156 xbt_die("Issuer not found");
159 const char* MC_smx_actor_get_host_name(smx_actor_t actor)
161 if (mc_model_checker == nullptr)
162 return actor->host->cname();
164 simgrid::mc::Process* process = &mc_model_checker->process();
166 /* HACK, 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 practice 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::ActorInformation* info = actor_info_cast(actor);
186 auto remote_string_address = remote((simgrid::xbt::string_data*)((char*)actor->host + offset));
187 simgrid::xbt::string_data remote_string = process->read(remote_string_address);
188 char hostname[remote_string.len];
189 process->read_bytes(hostname, remote_string.len + 1, remote(remote_string.data));
190 info->hostname = mc_model_checker->get_host_name(hostname).c_str();
191 return info->hostname;
194 const char* MC_smx_actor_get_name(smx_actor_t actor)
196 simgrid::mc::Process* process = &mc_model_checker->process();
197 if (mc_model_checker == nullptr)
198 return actor->name.c_str();
200 simgrid::mc::ActorInformation* info = actor_info_cast(actor);
201 if (info->name.empty()) {
202 simgrid::xbt::string_data string_data = (simgrid::xbt::string_data&)actor->name;
203 info->name = process->read_string(remote(string_data.data), string_data.len);
205 return info->name.c_str();
209 int MC_smpi_process_count(void)
211 if (mc_model_checker == nullptr)
212 return smpi_process_count();
214 mc_model_checker->process().read_variable("process_count",
220 unsigned long MC_smx_get_maxpid(void)
222 unsigned long maxpid;
223 mc_model_checker->process().read_variable("simix_process_maxpid",
224 &maxpid, sizeof(maxpid));