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 /** 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* process_info =
33 (simgrid::mc::SimixProcessInformation*)
34 ((char*) p - offsetof(simgrid::mc::SimixProcessInformation, copy));
38 /** Load the remote swag of processes into a vector
40 * @param process MCed process
41 * @param target Local vector (to be filled with copies of `s_smx_process_t`)
42 * @param remote_swag Address of the process SWAG in the remote list
44 static void MC_process_refresh_simix_process_list(
45 simgrid::mc::Process* process,
46 std::vector<simgrid::mc::SimixProcessInformation>& target, xbt_swag_t remote_swag)
50 // swag = REMOTE(*simix_global->process_list)
52 process->read_bytes(&swag, sizeof(swag), remote(remote_swag));
54 // Load each element of the vector from the MCed process:
56 for (smx_process_t p = (smx_process_t) swag.head; p; ++i) {
58 simgrid::mc::SimixProcessInformation info;
60 info.hostname = nullptr;
61 process->read_bytes(&info.copy, sizeof(info.copy), remote(p));
62 target.push_back(std::move(info));
64 // Lookup next process address:
65 p = (smx_process_t) xbt_swag_getNext(&info.copy, swag.offset);
67 assert(i == swag.count);
73 void Process::refresh_simix()
75 if (this->cache_flags_ & Process::cache_simix_processes)
78 // TODO, avoid to reload `&simix_global`, `simix_global`, `*simix_global`
80 // simix_global_p = REMOTE(simix_global);
81 smx_global_t simix_global_p;
82 this->read_variable("simix_global", &simix_global_p, sizeof(simix_global_p));
84 // simix_global = REMOTE(*simix_global)
85 s_smx_global_t simix_global;
86 this->read_bytes(&simix_global, sizeof(simix_global),
87 remote(simix_global_p));
89 MC_process_refresh_simix_process_list(
90 this, this->smx_process_infos, simix_global.process_list);
91 MC_process_refresh_simix_process_list(
92 this, this->smx_old_process_infos, simix_global.process_to_destroy);
94 this->cache_flags_ |= Process::cache_simix_processes;
100 /** Get the issuer of a simcall (`req->issuer`)
102 * In split-process mode, it does the black magic necessary to get an address
103 * of a (shallow) copy of the data structure the issuer SIMIX process in the local
106 * @param process the MCed process
107 * @param req the simcall (copied in the local process)
109 smx_process_t MC_smx_simcall_get_issuer(s_smx_simcall_t const* req)
111 xbt_assert(mc_mode == MC_MODE_SERVER);
113 // This is the address of the smx_process in the MCed process:
114 auto address = simgrid::mc::remote(req->issuer);
116 // Lookup by address:
117 for (auto& p : mc_model_checker->process().simix_processes())
118 if (p.address == address)
120 for (auto& p : mc_model_checker->process().old_simix_processes())
121 if (p.address == address)
124 xbt_die("Issuer not found");
127 const char* MC_smx_process_get_host_name(smx_process_t p)
129 if (mc_mode == MC_MODE_CLIENT)
130 return sg_host_get_name(p->host);
132 simgrid::mc::Process* process = &mc_model_checker->process();
134 /* HACK, Horrible hack to find the offset of the id in the simgrid::s4u::Host.
136 Offsetof is not supported for non-POD types but this should
137 work in pratice for the targets currently supported by the MC
138 as long as we do not add funny features to the Host class
139 (such as virtual base).
141 We are using a (C++11) unrestricted union in order to avoid
142 any construction/destruction of the simgrid::s4u::Host.
145 simgrid::s4u::Host host;
150 const size_t offset = (char*) &foo.host.name() - (char*) &foo.host;
152 // Read the simgrid::xbt::string in the MCed process:
153 simgrid::mc::SimixProcessInformation* info = process_info_cast(p);
154 simgrid::xbt::string_data remote_string;
155 auto remote_string_address = remote(
156 (simgrid::xbt::string_data*) ((char*) p->host + offset));
157 process->read_bytes(&remote_string, sizeof(remote_string), remote_string_address);
158 char hostname[remote_string.len];
159 process->read_bytes(hostname, remote_string.len + 1, remote(remote_string.data));
160 info->hostname = mc_model_checker->get_host_name(hostname);
161 return info->hostname;
164 const char* MC_smx_process_get_name(smx_process_t p)
166 simgrid::mc::Process* process = &mc_model_checker->process();
167 if (mc_mode == MC_MODE_CLIENT)
172 simgrid::mc::SimixProcessInformation* info = process_info_cast(p);
173 if (info->name.empty())
174 info->name = process->read_string(p->name);
175 return info->name.c_str();
179 int MC_smpi_process_count(void)
181 if (mc_mode == MC_MODE_CLIENT)
182 return smpi_process_count();
184 mc_model_checker->process().read_variable("process_count",
190 unsigned long MC_smx_get_maxpid(void)
192 unsigned long maxpid;
193 mc_model_checker->process().read_variable("simix_process_maxpid",
194 &maxpid, sizeof(maxpid));