1 /* Copyright (c) 2015-2018. 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, simgrid::mc::RemotePtr<void>(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 = simgrid::mc::RemotePtr<simgrid::kernel::actor::ActorImpl>(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{this->read_variable<simgrid::simix::Global*>("simix_global")};
76 // simix_global = REMOTE(*simix_global)
77 Remote<simgrid::simix::Global> simix_global =
78 this->read<simgrid::simix::Global>(simix_global_p);
80 MC_process_refresh_simix_actor_dynar(this, this->smx_actors_infos, remote(simix_global.getBuffer()->actors_vector));
81 MC_process_refresh_simix_actor_dynar(this, this->smx_dead_actors_infos,
82 remote(simix_global.getBuffer()->dead_actors_vector));
84 this->cache_flags_ |= RemoteClient::cache_simix_processes;
90 /** Get the issuer of a simcall (`req->issuer`)
92 * In split-process mode, it does the black magic necessary to get an address
93 * of a (shallow) copy of the data structure the issuer SIMIX actor in the local
96 * @param process the MCed process
97 * @param req the simcall (copied in the local process)
99 smx_actor_t MC_smx_simcall_get_issuer(s_smx_simcall const* req)
101 xbt_assert(mc_model_checker != nullptr);
103 // This is the address of the smx_actor in the MCed process:
104 auto address = simgrid::mc::remote(req->issuer);
106 // Lookup by address:
107 for (auto& actor : mc_model_checker->process().actors())
108 if (actor.address == address)
109 return actor.copy.getBuffer();
110 for (auto& actor : mc_model_checker->process().dead_actors())
111 if (actor.address == address)
112 return actor.copy.getBuffer();
114 xbt_die("Issuer not found");
117 const char* MC_smx_actor_get_host_name(smx_actor_t actor)
119 if (mc_model_checker == nullptr)
120 return actor->host->get_cname();
122 simgrid::mc::RemoteClient* process = &mc_model_checker->process();
124 /* HACK, Horrible hack to find the offset of the id in the simgrid::s4u::Host.
126 Offsetof is not supported for non-POD types but this should
127 work in practice for the targets currently supported by the MC
128 as long as we do not add funny features to the Host class
129 (such as virtual base).
131 We are using a (C++11) unrestricted union in order to avoid
132 any construction/destruction of the simgrid::s4u::Host.
135 simgrid::s4u::Host host;
136 fake_host() { /* Nothing to do*/}
137 ~fake_host() { /* Nothing to do*/}
140 const size_t offset = (char*)&foo.host.get_name() - (char*)&foo.host;
142 // Read the simgrid::xbt::string in the MCed process:
143 simgrid::mc::ActorInformation* info = actor_info_cast(actor);
144 auto remote_string_address = remote((simgrid::xbt::string_data*)((char*)actor->host + offset));
145 simgrid::xbt::string_data remote_string = process->read(remote_string_address);
146 char hostname[remote_string.len];
147 process->read_bytes(hostname, remote_string.len + 1, remote(remote_string.data));
148 info->hostname = mc_model_checker->get_host_name(hostname).c_str();
149 return info->hostname;
152 const char* MC_smx_actor_get_name(smx_actor_t actor)
154 simgrid::mc::RemoteClient* process = &mc_model_checker->process();
155 if (mc_model_checker == nullptr)
156 return actor->name.c_str();
158 simgrid::mc::ActorInformation* info = actor_info_cast(actor);
159 if (info->name.empty()) {
160 simgrid::xbt::string_data string_data = simgrid::xbt::string::to_string_data(actor->name);
161 info->name = process->read_string(remote(string_data.data), string_data.len);
163 return info->name.c_str();
167 int MC_smpi_process_count()
169 if (mc_model_checker == nullptr)
170 return smpi_process_count();
172 mc_model_checker->process().read_variable("process_count",
178 unsigned long MC_smx_get_maxpid()
180 unsigned long maxpid;
181 mc_model_checker->process().read_variable("simix_process_maxpid",
182 &maxpid, sizeof(maxpid));