1 /* Copyright (c) 2015. The SimGrid Team.
2 * All rights reserved. */
4 /* This program is free software; you can redistribute it and/or modify it
5 * under the terms of the license (GNU LGPL) which comes with this package. */
16 #include "src/simix/smx_private.h"
18 #include "src/mc/mc_smx.h"
19 #include "src/mc/ModelChecker.hpp"
21 using simgrid::mc::remote;
23 /** HACK, Statically "upcast" a s_smx_process_t into a SimixProcessInformation
25 * This gets 'processInfo' from '&processInfo->copy'. It upcasts in the
26 * sense that we could achieve the same thing by having SimixProcessInformation
27 * inherit from s_smx_process_t but we don't really want to do that.
30 simgrid::mc::SimixProcessInformation* process_info_cast(smx_process_t p)
32 simgrid::mc::SimixProcessInformation temp;
33 std::size_t offset = (char*) temp.copy.getBuffer() - (char*)&temp;
35 simgrid::mc::SimixProcessInformation* process_info =
36 (simgrid::mc::SimixProcessInformation*) ((char*) p - offset);
40 /** Load the remote swag of processes into a vector
42 * @param process MCed process
43 * @param target Local vector (to be filled with copies of `s_smx_process_t`)
44 * @param remote_swag Address of the process SWAG in the remote list
46 static void MC_process_refresh_simix_process_list(
47 simgrid::mc::Process* process,
48 std::vector<simgrid::mc::SimixProcessInformation>& target, xbt_swag_t remote_swag)
52 // swag = REMOTE(*simix_global->process_list)
54 process->read_bytes(&swag, sizeof(swag), remote(remote_swag));
56 // Load each element of the vector from the MCed process:
58 for (smx_process_t p = (smx_process_t) swag.head; p; ++i) {
60 simgrid::mc::SimixProcessInformation info;
62 info.hostname = nullptr;
63 process->read_bytes(&info.copy, sizeof(info.copy), remote(p));
64 target.push_back(std::move(info));
66 // Lookup next process address:
67 p = (smx_process_t) xbt_swag_getNext(&info.copy, swag.offset);
69 assert(i == swag.count);
75 void Process::refresh_simix()
77 if (this->cache_flags_ & Process::cache_simix_processes)
80 // TODO, avoid to reload `&simix_global`, `simix_global`, `*simix_global`
82 // simix_global_p = REMOTE(simix_global);
83 smx_global_t simix_global_p;
84 this->read_variable("simix_global", &simix_global_p, sizeof(simix_global_p));
86 // simix_global = REMOTE(*simix_global)
87 s_smx_global_t simix_global;
88 this->read_bytes(&simix_global, sizeof(simix_global),
89 remote(simix_global_p));
91 MC_process_refresh_simix_process_list(
92 this, this->smx_process_infos, simix_global.process_list);
93 MC_process_refresh_simix_process_list(
94 this, this->smx_old_process_infos, simix_global.process_to_destroy);
96 this->cache_flags_ |= Process::cache_simix_processes;
102 /** Get the issuer of a simcall (`req->issuer`)
104 * In split-process mode, it does the black magic necessary to get an address
105 * of a (shallow) copy of the data structure the issuer SIMIX process in the local
108 * @param process the MCed process
109 * @param req the simcall (copied in the local process)
111 smx_process_t MC_smx_simcall_get_issuer(s_smx_simcall_t const* req)
113 xbt_assert(mc_model_checker != nullptr);
115 // This is the address of the smx_process in the MCed process:
116 auto address = simgrid::mc::remote(req->issuer);
118 // Lookup by address:
119 for (auto& p : mc_model_checker->process().simix_processes())
120 if (p.address == address)
121 return p.copy.getBuffer();
122 for (auto& p : mc_model_checker->process().old_simix_processes())
123 if (p.address == address)
124 return p.copy.getBuffer();
126 xbt_die("Issuer not found");
129 const char* MC_smx_process_get_host_name(smx_process_t p)
131 if (mc_model_checker == nullptr)
132 return sg_host_get_name(p->host);
134 simgrid::mc::Process* process = &mc_model_checker->process();
136 /* HACK, Horrible hack to find the offset of the id in the simgrid::s4u::Host.
138 Offsetof is not supported for non-POD types but this should
139 work in practice for the targets currently supported by the MC
140 as long as we do not add funny features to the Host class
141 (such as virtual base).
143 We are using a (C++11) unrestricted union in order to avoid
144 any construction/destruction of the simgrid::s4u::Host.
147 simgrid::s4u::Host host;
152 const size_t offset = (char*) &foo.host.name() - (char*) &foo.host;
154 // Read the simgrid::xbt::string in the MCed process:
155 simgrid::mc::SimixProcessInformation* info = process_info_cast(p);
156 auto remote_string_address = remote(
157 (simgrid::xbt::string_data*) ((char*) p->host + offset));
158 simgrid::xbt::string_data remote_string = process->read(remote_string_address);
159 char hostname[remote_string.len];
160 process->read_bytes(hostname, remote_string.len + 1, remote(remote_string.data));
161 info->hostname = mc_model_checker->get_host_name(hostname);
162 return info->hostname;
165 const char* MC_smx_process_get_name(smx_process_t p)
167 simgrid::mc::Process* process = &mc_model_checker->process();
168 if (mc_model_checker == nullptr)
169 return p->name.c_str();
171 simgrid::mc::SimixProcessInformation* info = process_info_cast(p);
172 if (info->name.empty()) {
173 simgrid::xbt::string_data string_data = (simgrid::xbt::string_data&)p->name;
174 info->name = process->read_string(remote(string_data.data), string_data.len);
176 return info->name.c_str();
180 int MC_smpi_process_count(void)
182 if (mc_model_checker == nullptr)
183 return smpi_process_count();
185 mc_model_checker->process().read_variable("process_count",
191 unsigned long MC_smx_get_maxpid(void)
193 unsigned long maxpid;
194 mc_model_checker->process().read_variable("simix_process_maxpid",
195 &maxpid, sizeof(maxpid));