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. */
6 #include "simgrid/s4u/Host.hpp"
8 #include "src/mc/ModelChecker.hpp"
9 #include "src/mc/mc_smx.hpp"
11 using simgrid::mc::remote;
13 /** HACK, Statically "upcast" a s_smx_actor_t into a ActorInformation
15 * This gets 'actorInfo' from '&actorInfo->copy'. It upcasts in the
16 * sense that we could achieve the same thing by having ActorInformation
17 * inherit from s_smx_actor_t but we don't really want to do that.
19 static inline simgrid::mc::ActorInformation* actor_info_cast(smx_actor_t actor)
21 simgrid::mc::ActorInformation temp;
22 std::size_t offset = (char*) temp.copy.getBuffer() - (char*)&temp;
24 simgrid::mc::ActorInformation* process_info = (simgrid::mc::ActorInformation*)((char*)actor - offset);
28 /** Load the remote swag of processes into a vector
30 * @param process MCed process
31 * @param target Local vector (to be filled with copies of `s_smx_actor_t`)
32 * @param remote_swag Address of the process SWAG in the remote list
34 static void MC_process_refresh_simix_process_list(simgrid::mc::RemoteClient* process,
35 std::vector<simgrid::mc::ActorInformation>& target,
36 simgrid::mc::RemotePtr<s_xbt_swag_t> remote_swag)
40 // swag = REMOTE(*simix_global->process_list)
42 process->read_bytes(&swag, sizeof(swag), remote_swag);
44 // Load each element of the vector from the MCed process:
46 for (smx_actor_t p = (smx_actor_t) swag.head; p; ++i) {
48 simgrid::mc::ActorInformation info;
50 info.hostname = nullptr;
51 process->read_bytes(&info.copy, sizeof(info.copy), remote(p));
52 target.push_back(std::move(info));
54 // Lookup next process address:
55 p = (smx_actor_t) xbt_swag_getNext(&info.copy, swag.offset);
57 assert(i == swag.count);
60 static void MC_process_refresh_simix_actor_dynar(simgrid::mc::RemoteClient* process,
61 std::vector<simgrid::mc::ActorInformation>& target,
62 simgrid::mc::RemotePtr<s_xbt_dynar_t> remote_dynar)
67 process->read_bytes(&dynar, sizeof(dynar), remote_dynar);
69 smx_actor_t* data = static_cast<smx_actor_t*>(::operator new(dynar.elmsize * dynar.used));
70 process->read_bytes(data, dynar.elmsize * dynar.used, dynar.data);
72 // Load each element of the vector from the MCed process:
73 for (unsigned int i = 0; i < dynar.used; ++i) {
75 simgrid::mc::ActorInformation info;
76 info.address = data[i];
77 info.hostname = nullptr;
78 process->read_bytes(&info.copy, sizeof(info.copy), remote(data[i]));
79 target.push_back(std::move(info));
81 ::operator delete(data);
86 void RemoteClient::refresh_simix()
88 if (this->cache_flags_ & RemoteClient::cache_simix_processes)
91 // TODO, avoid to reload `&simix_global`, `simix_global`, `*simix_global`
93 static_assert(std::is_same<
94 std::unique_ptr<simgrid::simix::Global>,
95 decltype(simix_global)
96 >::value, "Unexpected type for simix_global");
97 static_assert(sizeof(simix_global) == sizeof(simgrid::simix::Global*),
98 "Bad size for simix_global");
100 RemotePtr<simgrid::simix::Global> simix_global_p =
101 this->read_variable<simgrid::simix::Global*>("simix_global");
103 // simix_global = REMOTE(*simix_global)
104 Remote<simgrid::simix::Global> simix_global =
105 this->read<simgrid::simix::Global>(simix_global_p);
107 MC_process_refresh_simix_actor_dynar(this, this->smx_actors_infos, remote(simix_global.getBuffer()->actors_vector));
108 MC_process_refresh_simix_process_list(this, this->smx_dead_actors_infos,
109 remote(simix_global.getBuffer()->process_to_destroy));
111 this->cache_flags_ |= RemoteClient::cache_simix_processes;
117 /** Get the issuer of a simcall (`req->issuer`)
119 * In split-process mode, it does the black magic necessary to get an address
120 * of a (shallow) copy of the data structure the issuer SIMIX actor in the local
123 * @param process the MCed process
124 * @param req the simcall (copied in the local process)
126 smx_actor_t MC_smx_simcall_get_issuer(s_smx_simcall_t const* req)
128 xbt_assert(mc_model_checker != nullptr);
130 // This is the address of the smx_actor in the MCed process:
131 auto address = simgrid::mc::remote(req->issuer);
133 // Lookup by address:
134 for (auto& actor : mc_model_checker->process().actors())
135 if (actor.address == address)
136 return actor.copy.getBuffer();
137 for (auto& actor : mc_model_checker->process().dead_actors())
138 if (actor.address == address)
139 return actor.copy.getBuffer();
141 xbt_die("Issuer not found");
144 const char* MC_smx_actor_get_host_name(smx_actor_t actor)
146 if (mc_model_checker == nullptr)
147 return actor->host->getCname();
149 simgrid::mc::RemoteClient* process = &mc_model_checker->process();
151 /* HACK, Horrible hack to find the offset of the id in the simgrid::s4u::Host.
153 Offsetof is not supported for non-POD types but this should
154 work in practice for the targets currently supported by the MC
155 as long as we do not add funny features to the Host class
156 (such as virtual base).
158 We are using a (C++11) unrestricted union in order to avoid
159 any construction/destruction of the simgrid::s4u::Host.
162 simgrid::s4u::Host host;
163 fake_host() { /* Nothing to do*/}
164 ~fake_host() { /* Nothing to do*/}
167 const size_t offset = (char*)&foo.host.getName() - (char*)&foo.host;
169 // Read the simgrid::xbt::string in the MCed process:
170 simgrid::mc::ActorInformation* info = actor_info_cast(actor);
171 auto remote_string_address = remote((simgrid::xbt::string_data*)((char*)actor->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_actor_get_name(smx_actor_t actor)
181 simgrid::mc::RemoteClient* process = &mc_model_checker->process();
182 if (mc_model_checker == nullptr)
183 return actor->name.c_str();
185 simgrid::mc::ActorInformation* info = actor_info_cast(actor);
186 if (info->name.empty()) {
187 simgrid::xbt::string_data string_data = simgrid::xbt::string::to_string_data(actor->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()
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()
207 unsigned long maxpid;
208 mc_model_checker->process().read_variable("simix_process_maxpid",
209 &maxpid, sizeof(maxpid));