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 list 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_dynar Address of the process dynar in the remote list
34 static void MC_process_refresh_simix_actor_dynar(simgrid::mc::RemoteClient* process,
35 std::vector<simgrid::mc::ActorInformation>& target,
36 simgrid::mc::RemotePtr<s_xbt_dynar_t> remote_dynar)
41 process->read_bytes(&dynar, sizeof(dynar), remote_dynar);
43 smx_actor_t* data = static_cast<smx_actor_t*>(::operator new(dynar.elmsize * dynar.used));
44 process->read_bytes(data, dynar.elmsize * dynar.used, dynar.data);
46 // Load each element of the vector from the MCed process:
47 for (unsigned int i = 0; i < dynar.used; ++i) {
49 simgrid::mc::ActorInformation info;
50 info.address = data[i];
51 info.hostname = nullptr;
52 process->read_bytes(&info.copy, sizeof(info.copy), remote(data[i]));
53 target.push_back(std::move(info));
55 ::operator delete(data);
60 void RemoteClient::refresh_simix()
62 if (this->cache_flags_ & RemoteClient::cache_simix_processes)
65 // TODO, avoid to reload `&simix_global`, `simix_global`, `*simix_global`
67 static_assert(std::is_same<
68 std::unique_ptr<simgrid::simix::Global>,
69 decltype(simix_global)
70 >::value, "Unexpected type for simix_global");
71 static_assert(sizeof(simix_global) == sizeof(simgrid::simix::Global*),
72 "Bad size for simix_global");
74 RemotePtr<simgrid::simix::Global> simix_global_p =
75 this->read_variable<simgrid::simix::Global*>("simix_global");
77 // simix_global = REMOTE(*simix_global)
78 Remote<simgrid::simix::Global> simix_global =
79 this->read<simgrid::simix::Global>(simix_global_p);
81 MC_process_refresh_simix_actor_dynar(this, this->smx_actors_infos, remote(simix_global.getBuffer()->actors_vector));
82 MC_process_refresh_simix_actor_dynar(this, this->smx_dead_actors_infos,
83 remote(simix_global.getBuffer()->dead_actors_vector));
85 this->cache_flags_ |= RemoteClient::cache_simix_processes;
91 /** Get the issuer of a simcall (`req->issuer`)
93 * In split-process mode, it does the black magic necessary to get an address
94 * of a (shallow) copy of the data structure the issuer SIMIX actor in the local
97 * @param process the MCed process
98 * @param req the simcall (copied in the local process)
100 smx_actor_t MC_smx_simcall_get_issuer(s_smx_simcall_t const* req)
102 xbt_assert(mc_model_checker != nullptr);
104 // This is the address of the smx_actor in the MCed process:
105 auto address = simgrid::mc::remote(req->issuer);
107 // Lookup by address:
108 for (auto& actor : mc_model_checker->process().actors())
109 if (actor.address == address)
110 return actor.copy.getBuffer();
111 for (auto& actor : mc_model_checker->process().dead_actors())
112 if (actor.address == address)
113 return actor.copy.getBuffer();
115 xbt_die("Issuer not found");
118 const char* MC_smx_actor_get_host_name(smx_actor_t actor)
120 if (mc_model_checker == nullptr)
121 return actor->host->getCname();
123 simgrid::mc::RemoteClient* process = &mc_model_checker->process();
125 /* HACK, Horrible hack to find the offset of the id in the simgrid::s4u::Host.
127 Offsetof is not supported for non-POD types but this should
128 work in practice for the targets currently supported by the MC
129 as long as we do not add funny features to the Host class
130 (such as virtual base).
132 We are using a (C++11) unrestricted union in order to avoid
133 any construction/destruction of the simgrid::s4u::Host.
136 simgrid::s4u::Host host;
137 fake_host() { /* Nothing to do*/}
138 ~fake_host() { /* Nothing to do*/}
141 const size_t offset = (char*)&foo.host.getName() - (char*)&foo.host;
143 // Read the simgrid::xbt::string in the MCed process:
144 simgrid::mc::ActorInformation* info = actor_info_cast(actor);
145 auto remote_string_address = remote((simgrid::xbt::string_data*)((char*)actor->host + offset));
146 simgrid::xbt::string_data remote_string = process->read(remote_string_address);
147 char hostname[remote_string.len];
148 process->read_bytes(hostname, remote_string.len + 1, remote(remote_string.data));
149 info->hostname = mc_model_checker->get_host_name(hostname).c_str();
150 return info->hostname;
153 const char* MC_smx_actor_get_name(smx_actor_t actor)
155 simgrid::mc::RemoteClient* process = &mc_model_checker->process();
156 if (mc_model_checker == nullptr)
157 return actor->name.c_str();
159 simgrid::mc::ActorInformation* info = actor_info_cast(actor);
160 if (info->name.empty()) {
161 simgrid::xbt::string_data string_data = simgrid::xbt::string::to_string_data(actor->name);
162 info->name = process->read_string(remote(string_data.data), string_data.len);
164 return info->name.c_str();
168 int MC_smpi_process_count()
170 if (mc_model_checker == nullptr)
171 return smpi_process_count();
173 mc_model_checker->process().read_variable("process_count",
179 unsigned long MC_smx_get_maxpid()
181 unsigned long maxpid;
182 mc_model_checker->process().read_variable("simix_process_maxpid",
183 &maxpid, sizeof(maxpid));