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/mc_smx.h"
9 #include "src/mc/ModelChecker.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::Process* 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::Process* 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 = (smx_actor_t*)malloc(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));
86 void Process::refresh_simix()
88 if (this->cache_flags_ & Process::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 // simix_global_p = REMOTE(simix_global.get());
101 RemotePtr<simgrid::simix::Global> simix_global_p =
102 this->read_variable<simgrid::simix::Global*>("simix_global");
104 // simix_global = REMOTE(*simix_global)
105 Remote<simgrid::simix::Global> simix_global =
106 this->read<simgrid::simix::Global>(simix_global_p);
108 MC_process_refresh_simix_actor_dynar(this, this->smx_actors_infos, remote(simix_global.getBuffer()->actors_vector));
109 MC_process_refresh_simix_process_list(this, this->smx_dead_actors_infos,
110 remote(simix_global.getBuffer()->process_to_destroy));
112 this->cache_flags_ |= Process::cache_simix_processes;
118 /** Get the issuer of a simcall (`req->issuer`)
120 * In split-process mode, it does the black magic necessary to get an address
121 * of a (shallow) copy of the data structure the issuer SIMIX actor in the local
124 * @param process the MCed process
125 * @param req the simcall (copied in the local process)
127 smx_actor_t MC_smx_simcall_get_issuer(s_smx_simcall_t const* req)
129 xbt_assert(mc_model_checker != nullptr);
131 // This is the address of the smx_actor in the MCed process:
132 auto address = simgrid::mc::remote(req->issuer);
134 // Lookup by address:
135 for (auto& actor : mc_model_checker->process().actors())
136 if (actor.address == address)
137 return actor.copy.getBuffer();
138 for (auto& actor : mc_model_checker->process().dead_actors())
139 if (actor.address == address)
140 return actor.copy.getBuffer();
142 xbt_die("Issuer not found");
145 const char* MC_smx_actor_get_host_name(smx_actor_t actor)
147 if (mc_model_checker == nullptr)
148 return actor->host->cname();
150 simgrid::mc::Process* process = &mc_model_checker->process();
152 /* HACK, Horrible hack to find the offset of the id in the simgrid::s4u::Host.
154 Offsetof is not supported for non-POD types but this should
155 work in practice for the targets currently supported by the MC
156 as long as we do not add funny features to the Host class
157 (such as virtual base).
159 We are using a (C++11) unrestricted union in order to avoid
160 any construction/destruction of the simgrid::s4u::Host.
163 simgrid::s4u::Host host;
168 const size_t offset = (char*) &foo.host.name() - (char*) &foo.host;
170 // Read the simgrid::xbt::string in the MCed process:
171 simgrid::mc::ActorInformation* info = actor_info_cast(actor);
172 auto remote_string_address = remote((simgrid::xbt::string_data*)((char*)actor->host + offset));
173 simgrid::xbt::string_data remote_string = process->read(remote_string_address);
174 char hostname[remote_string.len];
175 process->read_bytes(hostname, remote_string.len + 1, remote(remote_string.data));
176 info->hostname = mc_model_checker->get_host_name(hostname).c_str();
177 return info->hostname;
180 const char* MC_smx_actor_get_name(smx_actor_t actor)
182 simgrid::mc::Process* process = &mc_model_checker->process();
183 if (mc_model_checker == nullptr)
184 return actor->name.c_str();
186 simgrid::mc::ActorInformation* info = actor_info_cast(actor);
187 if (info->name.empty()) {
188 simgrid::xbt::string_data string_data = (simgrid::xbt::string_data&)actor->name;
189 info->name = process->read_string(remote(string_data.data), string_data.len);
191 return info->name.c_str();
195 int MC_smpi_process_count()
197 if (mc_model_checker == nullptr)
198 return smpi_process_count();
200 mc_model_checker->process().read_variable("process_count",
206 unsigned long MC_smx_get_maxpid()
208 unsigned long maxpid;
209 mc_model_checker->process().read_variable("simix_process_maxpid",
210 &maxpid, sizeof(maxpid));