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. */
11 #include <xbt/dynar.h>
15 #include "src/simix/smx_private.h"
17 #include "src/mc/mc_smx.h"
18 #include "src/mc/ModelChecker.hpp"
20 using simgrid::mc::remote;
25 void MC_smx_process_info_clear(mc_smx_process_info_t p)
27 p->hostname = nullptr;
32 xbt_dynar_t MC_smx_process_info_list_new(void)
35 sizeof(s_mc_smx_process_info_t),
36 ( void_f_pvoid_t) &MC_smx_process_info_clear);
40 bool is_in_dynar(smx_process_t p, xbt_dynar_t dynar)
42 return (uintptr_t) p >= (uintptr_t) dynar->data
43 && (uintptr_t) p < ((uintptr_t) dynar->data + dynar->used * dynar->elmsize);
47 mc_smx_process_info_t MC_smx_process_get_info(smx_process_t p)
49 assert(is_in_dynar(p, mc_model_checker->process().smx_process_infos)
50 || is_in_dynar(p, mc_model_checker->process().smx_old_process_infos));
51 mc_smx_process_info_t process_info =
52 (mc_smx_process_info_t)
53 ((char*) p - offsetof(s_mc_smx_process_info_t, copy));
57 /** Load the remote swag of processes into a dynar
59 * @param process MCed process
60 * @param target Local dynar (to be filled with copies of `s_smx_process_t`)
61 * @param remote_swag Address of the process SWAG in the remote list
63 static void MC_process_refresh_simix_process_list(
64 simgrid::mc::Process* process,
65 xbt_dynar_t target, xbt_swag_t remote_swag)
67 // swag = REMOTE(*simix_global->process_list)
69 process->read_bytes(&swag, sizeof(swag), remote(remote_swag));
72 xbt_dynar_reset(target);
74 // Load each element of the dynar from the MCed process:
76 for (p = (smx_process_t) swag.head; p; ++i) {
78 s_mc_smx_process_info_t info;
81 info.hostname = nullptr;
82 process->read_bytes(&info.copy, sizeof(info.copy), remote(p));
83 xbt_dynar_push(target, &info);
85 // Lookup next process address:
86 p = (smx_process_t) xbt_swag_getNext(&info.copy, swag.offset);
88 assert(i == swag.count);
91 void MC_process_smx_refresh(simgrid::mc::Process* process)
93 xbt_assert(mc_mode == MC_MODE_SERVER);
94 if (process->cache_flags & MC_PROCESS_CACHE_FLAG_SIMIX_PROCESSES)
97 // TODO, avoid to reload `&simix_global`, `simix_global`, `*simix_global`
99 // simix_global_p = REMOTE(simix_global);
100 smx_global_t simix_global_p;
101 process->read_variable("simix_global", &simix_global_p, sizeof(simix_global_p));
103 // simix_global = REMOTE(*simix_global)
104 s_smx_global_t simix_global;
105 process->read_bytes(&simix_global, sizeof(simix_global),
106 remote(simix_global_p));
108 MC_process_refresh_simix_process_list(
109 process, process->smx_process_infos, simix_global.process_list);
110 MC_process_refresh_simix_process_list(
111 process, process->smx_old_process_infos, simix_global.process_to_destroy);
113 process->cache_flags |= MC_PROCESS_CACHE_FLAG_SIMIX_PROCESSES;
116 /** Get the issuer of a simcall (`req->issuer`)
118 * In split-process mode, it does the black magic necessary to get an address
119 * of a (shallow) copy of the data structure the issuer SIMIX process in the local
122 * @param process the MCed process
123 * @param req the simcall (copied in the local process)
125 smx_process_t MC_smx_simcall_get_issuer(smx_simcall_t req)
127 if (mc_mode == MC_MODE_CLIENT)
130 MC_process_smx_refresh(&mc_model_checker->process());
132 // This is the address of the smx_process in the MCed process:
133 void* address = req->issuer;
136 mc_smx_process_info_t p;
138 // Lookup by address:
139 xbt_dynar_foreach_ptr(mc_model_checker->process().smx_process_infos, i, p)
140 if (p->address == address)
142 xbt_dynar_foreach_ptr(mc_model_checker->process().smx_old_process_infos, i, p)
143 if (p->address == address)
146 xbt_die("Issuer not found");
149 smx_process_t MC_smx_resolve_process(smx_process_t process_remote_address)
151 if (!process_remote_address)
153 if (mc_mode == MC_MODE_CLIENT)
154 return process_remote_address;
156 mc_smx_process_info_t process_info = MC_smx_resolve_process_info(process_remote_address);
158 return &process_info->copy;
163 mc_smx_process_info_t MC_smx_resolve_process_info(smx_process_t process_remote_address)
165 if (mc_mode == MC_MODE_CLIENT)
166 xbt_die("No process_info for local process is not enabled.");
169 mc_smx_process_info_t process_info;
170 xbt_dynar_foreach_ptr(mc_model_checker->process().smx_process_infos, index, process_info)
171 if (process_info->address == process_remote_address)
173 xbt_dynar_foreach_ptr(mc_model_checker->process().smx_old_process_infos, index, process_info)
174 if (process_info->address == process_remote_address)
176 xbt_die("Process info not found");
179 const char* MC_smx_process_get_host_name(smx_process_t p)
181 if (mc_mode == MC_MODE_CLIENT)
182 return sg_host_get_name(p->host);
184 simgrid::mc::Process* process = &mc_model_checker->process();
186 /* Horrible hack to find the offset of the id in the simgrid::s4u::Host.
188 Offsetof is not supported for non-POD types but this should
189 work in pratice for the targets currently supported by the MC
190 as long as we do not add funny features to the Host class
191 (such as virtual base).
193 We are using a (C++11) unrestricted union in order to avoid
194 any construction/destruction of the simgrid::s4u::Host.
197 simgrid::s4u::Host host;
202 const size_t offset = (char*) &foo.host.name() - (char*) &foo.host;
204 // Read the simgrid::xbt::string in the MCed process:
205 mc_smx_process_info_t info = MC_smx_process_get_info(p);
206 simgrid::xbt::string_data remote_string;
207 auto remote_string_address = remote(
208 (simgrid::xbt::string_data*) ((char*) p->host + offset));
209 process->read_bytes(&remote_string, sizeof(remote_string), remote_string_address);
210 char hostname[remote_string.len];
211 process->read_bytes(hostname, remote_string.len + 1, remote(remote_string.data));
212 info->hostname = mc_model_checker->get_host_name(hostname);
213 return info->hostname;
216 const char* MC_smx_process_get_name(smx_process_t p)
218 simgrid::mc::Process* process = &mc_model_checker->process();
219 if (mc_mode == MC_MODE_CLIENT)
224 mc_smx_process_info_t info = MC_smx_process_get_info(p);
226 info->name = process->read_string(p->name);
232 int MC_smpi_process_count(void)
234 if (mc_mode == MC_MODE_CLIENT)
235 return smpi_process_count();
238 mc_model_checker->process().read_variable("process_count",
245 unsigned long MC_smx_get_maxpid(void)
247 unsigned long maxpid;
248 mc_model_checker->process().read_variable("simix_process_maxpid",
249 &maxpid, sizeof(maxpid));