Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[mc] Mark some remote pointers as such
[simgrid.git] / src / mc / mc_smx.cpp
1 /* Copyright (c) 2015. The SimGrid Team.
2  * All rights reserved.                                                     */
3
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. */
6
7 #include <cassert>
8 #include <cstdlib>
9
10 #include <vector>
11
12 #include <xbt/log.h>
13 #include <xbt/str.h>
14 #include <xbt/swag.h>
15
16 #include "src/simix/smx_private.h"
17
18 #include "src/mc/mc_smx.h"
19 #include "src/mc/ModelChecker.hpp"
20
21 using simgrid::mc::remote;
22
23 extern "C" {
24
25 static inline
26 bool is_in_vector(smx_process_t p, std::vector<simgrid::mc::SimixProcessInformation>& ps)
27 {
28   return (uintptr_t) p >= (uintptr_t) &ps[0]
29     && (uintptr_t) p < (uintptr_t) &ps[ps.size()];
30 }
31
32 static inline
33 simgrid::mc::SimixProcessInformation* MC_smx_process_get_info(smx_process_t p)
34 {
35   assert(is_in_vector(p, mc_model_checker->process().smx_process_infos)
36     || is_in_vector(p, mc_model_checker->process().smx_old_process_infos));
37   simgrid::mc::SimixProcessInformation* process_info =
38     (simgrid::mc::SimixProcessInformation*)
39       ((char*) p - offsetof(simgrid::mc::SimixProcessInformation, copy));
40   return process_info;
41 }
42
43 /** Load the remote swag of processes into a vector
44  *
45  *  @param process     MCed process
46  *  @param target      Local vector (to be filled with copies of `s_smx_process_t`)
47  *  @param remote_swag Address of the process SWAG in the remote list
48  */
49 static void MC_process_refresh_simix_process_list(
50   simgrid::mc::Process* process,
51   std::vector<simgrid::mc::SimixProcessInformation>& target, xbt_swag_t remote_swag)
52 {
53   target.clear();
54
55   // swag = REMOTE(*simix_global->process_list)
56   s_xbt_swag_t swag;
57   process->read_bytes(&swag, sizeof(swag), remote(remote_swag));
58
59   // Load each element of the vector from the MCed process:
60   int i = 0;
61   for (smx_process_t p = (smx_process_t) swag.head; p; ++i) {
62
63     simgrid::mc::SimixProcessInformation info;
64     info.address = p;
65     info.hostname = nullptr;
66     process->read_bytes(&info.copy, sizeof(info.copy), remote(p));
67     target.push_back(std::move(info));
68
69     // Lookup next process address:
70     p = (smx_process_t) xbt_swag_getNext(&info.copy, swag.offset);
71   }
72   assert(i == swag.count);
73 }
74
75 namespace simgrid {
76 namespace mc {
77
78 void Process::refresh_simix()
79 {
80   if (this->cache_flags_ & Process::cache_simix_processes)
81     return;
82
83   // TODO, avoid to reload `&simix_global`, `simix_global`, `*simix_global`
84
85   // simix_global_p = REMOTE(simix_global);
86   smx_global_t simix_global_p;
87   this->read_variable("simix_global", &simix_global_p, sizeof(simix_global_p));
88
89   // simix_global = REMOTE(*simix_global)
90   s_smx_global_t simix_global;
91   this->read_bytes(&simix_global, sizeof(simix_global),
92     remote(simix_global_p));
93
94   MC_process_refresh_simix_process_list(
95     this, this->smx_process_infos, simix_global.process_list);
96   MC_process_refresh_simix_process_list(
97     this, this->smx_old_process_infos, simix_global.process_to_destroy);
98
99   this->cache_flags_ |= Process::cache_simix_processes;
100 }
101
102 }
103 }
104
105 /** Get the issuer of a simcall (`req->issuer`)
106  *
107  *  In split-process mode, it does the black magic necessary to get an address
108  *  of a (shallow) copy of the data structure the issuer SIMIX process in the local
109  *  address space.
110  *
111  *  @param process the MCed process
112  *  @param req     the simcall (copied in the local process)
113  */
114 smx_process_t MC_smx_simcall_get_issuer(s_smx_simcall_t const* req)
115 {
116   if (mc_mode == MC_MODE_CLIENT)
117     return req->issuer;
118
119   // This is the address of the smx_process in the MCed process:
120   auto address = simgrid::mc::remote(req->issuer);
121
122   // Lookup by address:
123   for (auto& p : mc_model_checker->process().simix_processes())
124     if (p.address == address)
125       return &p.copy;
126   for (auto& p : mc_model_checker->process().old_simix_processes())
127     if (p.address == address)
128       return &p.copy;
129
130   xbt_die("Issuer not found");
131 }
132
133 smx_process_t MC_smx_resolve_process(
134   simgrid::mc::RemotePtr<s_smx_process_t> process_remote_address)
135 {
136   if (!process_remote_address)
137     return nullptr;
138   if (mc_mode == MC_MODE_CLIENT)
139     return process_remote_address.local();
140
141   simgrid::mc::SimixProcessInformation* process_info =
142     MC_smx_resolve_process_info(process_remote_address);
143   if (process_info)
144     return &process_info->copy;
145   else
146     return nullptr;
147 }
148
149 simgrid::mc::SimixProcessInformation* MC_smx_resolve_process_info(
150   simgrid::mc::RemotePtr<s_smx_process_t> process_remote_address)
151 {
152   if (mc_mode == MC_MODE_CLIENT)
153     xbt_die("No process_info for local process is not enabled.");
154   for (auto& process_info : mc_model_checker->process().smx_process_infos)
155     if (process_info.address == process_remote_address)
156       return &process_info;
157   for (auto& process_info : mc_model_checker->process().smx_old_process_infos)
158     if (process_info.address == process_remote_address)
159       return &process_info;
160   xbt_die("Process info not found");
161 }
162
163 const char* MC_smx_process_get_host_name(smx_process_t p)
164 {
165   if (mc_mode == MC_MODE_CLIENT)
166     return sg_host_get_name(p->host);
167
168   simgrid::mc::Process* process = &mc_model_checker->process();
169
170   /* HACK, Horrible hack to find the offset of the id in the simgrid::s4u::Host.
171
172      Offsetof is not supported for non-POD types but this should
173      work in pratice for the targets currently supported by the MC
174      as long as we do not add funny features to the Host class
175      (such as virtual base).
176
177      We are using a (C++11) unrestricted union in order to avoid
178      any construction/destruction of the simgrid::s4u::Host.
179   */
180   union fake_host {
181     simgrid::s4u::Host host;
182     fake_host() {}
183     ~fake_host() {}
184   };
185   fake_host foo;
186   const size_t offset = (char*) &foo.host.name() - (char*) &foo.host;
187
188   // Read the simgrid::xbt::string in the MCed process:
189   simgrid::mc::SimixProcessInformation* info = MC_smx_process_get_info(p);
190   simgrid::xbt::string_data remote_string;
191   auto remote_string_address = remote(
192     (simgrid::xbt::string_data*) ((char*) p->host + offset));
193   process->read_bytes(&remote_string, sizeof(remote_string), remote_string_address);
194   char hostname[remote_string.len];
195   process->read_bytes(hostname, remote_string.len + 1, remote(remote_string.data));
196   info->hostname = mc_model_checker->get_host_name(hostname);
197   return info->hostname;
198 }
199
200 const char* MC_smx_process_get_name(smx_process_t p)
201 {
202   simgrid::mc::Process* process = &mc_model_checker->process();
203   if (mc_mode == MC_MODE_CLIENT)
204     return p->name;
205   if (!p->name)
206     return nullptr;
207
208   simgrid::mc::SimixProcessInformation* info = MC_smx_process_get_info(p);
209   if (info->name.empty())
210     info->name = process->read_string(p->name);
211   return info->name.c_str();
212 }
213
214 #if HAVE_SMPI
215 int MC_smpi_process_count(void)
216 {
217   if (mc_mode == MC_MODE_CLIENT)
218     return smpi_process_count();
219   int res;
220   mc_model_checker->process().read_variable("process_count",
221     &res, sizeof(res));
222   return res;
223 }
224 #endif
225
226 unsigned long MC_smx_get_maxpid(void)
227 {
228   unsigned long maxpid;
229   mc_model_checker->process().read_variable("simix_process_maxpid",
230     &maxpid, sizeof(maxpid));
231   return maxpid;
232 }
233
234 }