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);
77 void Process::refresh_simix()
79 if (this->cache_flags_ & Process::cache_simix_processes)
82 // TODO, avoid to reload `&simix_global`, `simix_global`, `*simix_global`
84 static_assert(std::is_same<
85 std::unique_ptr<simgrid::simix::Global>,
86 decltype(simix_global)
87 >::value, "Unexpected type for simix_global");
88 static_assert(sizeof(simix_global) == sizeof(simgrid::simix::Global*),
89 "Bad size for simix_global");
91 // simix_global_p = REMOTE(simix_global.get());
92 RemotePtr<simgrid::simix::Global> simix_global_p =
93 this->read_variable<simgrid::simix::Global*>("simix_global");
95 // simix_global = REMOTE(*simix_global)
96 Remote<simgrid::simix::Global> simix_global =
97 this->read<simgrid::simix::Global>(simix_global_p);
99 MC_process_refresh_simix_process_list(this, this->smx_actors_infos, remote(simix_global.getBuffer()->process_list));
100 MC_process_refresh_simix_process_list(this, this->smx_dead_actors_infos,
101 remote(simix_global.getBuffer()->process_to_destroy));
103 this->cache_flags_ |= Process::cache_simix_processes;
109 /** Get the issuer of a simcall (`req->issuer`)
111 * In split-process mode, it does the black magic necessary to get an address
112 * of a (shallow) copy of the data structure the issuer SIMIX actor in the local
115 * @param process the MCed process
116 * @param req the simcall (copied in the local process)
118 smx_actor_t MC_smx_simcall_get_issuer(s_smx_simcall_t const* req)
120 xbt_assert(mc_model_checker != nullptr);
122 // This is the address of the smx_actor in the MCed process:
123 auto address = simgrid::mc::remote(req->issuer);
125 // Lookup by address:
126 for (auto& actor : mc_model_checker->process().actors())
127 if (actor.address == address)
128 return actor.copy.getBuffer();
129 for (auto& actor : mc_model_checker->process().dead_actors())
130 if (actor.address == address)
131 return actor.copy.getBuffer();
133 xbt_die("Issuer not found");
136 const char* MC_smx_actor_get_host_name(smx_actor_t actor)
138 if (mc_model_checker == nullptr)
139 return actor->host->cname();
141 simgrid::mc::Process* process = &mc_model_checker->process();
143 /* HACK, Horrible hack to find the offset of the id in the simgrid::s4u::Host.
145 Offsetof is not supported for non-POD types but this should
146 work in practice for the targets currently supported by the MC
147 as long as we do not add funny features to the Host class
148 (such as virtual base).
150 We are using a (C++11) unrestricted union in order to avoid
151 any construction/destruction of the simgrid::s4u::Host.
154 simgrid::s4u::Host host;
159 const size_t offset = (char*) &foo.host.name() - (char*) &foo.host;
161 // Read the simgrid::xbt::string in the MCed process:
162 simgrid::mc::ActorInformation* info = actor_info_cast(actor);
163 auto remote_string_address = remote((simgrid::xbt::string_data*)((char*)actor->host + offset));
164 simgrid::xbt::string_data remote_string = process->read(remote_string_address);
165 char hostname[remote_string.len];
166 process->read_bytes(hostname, remote_string.len + 1, remote(remote_string.data));
167 info->hostname = mc_model_checker->get_host_name(hostname).c_str();
168 return info->hostname;
171 const char* MC_smx_actor_get_name(smx_actor_t actor)
173 simgrid::mc::Process* process = &mc_model_checker->process();
174 if (mc_model_checker == nullptr)
175 return actor->name.c_str();
177 simgrid::mc::ActorInformation* info = actor_info_cast(actor);
178 if (info->name.empty()) {
179 simgrid::xbt::string_data string_data = (simgrid::xbt::string_data&)actor->name;
180 info->name = process->read_string(remote(string_data.data), string_data.len);
182 return info->name.c_str();
186 int MC_smpi_process_count(void)
188 if (mc_model_checker == nullptr)
189 return smpi_process_count();
191 mc_model_checker->process().read_variable("process_count",
197 unsigned long MC_smx_get_maxpid(void)
199 unsigned long maxpid;
200 mc_model_checker->process().read_variable("simix_process_maxpid",
201 &maxpid, sizeof(maxpid));