Logo AND Algorithmique Numérique Distribuée

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