Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
move surf::As to s4u::As
[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
25 void MC_smx_process_info_clear(mc_smx_process_info_t p)
26 {
27   p->hostname = nullptr;
28   std::free(p->name);
29   p->name = nullptr;
30 }
31
32 xbt_dynar_t MC_smx_process_info_list_new(void)
33 {
34   return xbt_dynar_new(
35     sizeof(s_mc_smx_process_info_t),
36     ( void_f_pvoid_t) &MC_smx_process_info_clear);
37 }
38
39 static inline
40 bool is_in_dynar(smx_process_t p, xbt_dynar_t dynar)
41 {
42   return (uintptr_t) p >= (uintptr_t) dynar->data
43     && (uintptr_t) p < ((uintptr_t) dynar->data + dynar->used * dynar->elmsize);
44 }
45
46 static inline
47 mc_smx_process_info_t MC_smx_process_get_info(smx_process_t p)
48 {
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));
54   return process_info;
55 }
56
57 /** Load the remote swag of processes into a dynar
58  *
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
62  */
63 static void MC_process_refresh_simix_process_list(
64   simgrid::mc::Process* process,
65   xbt_dynar_t target, xbt_swag_t remote_swag)
66 {
67   // swag = REMOTE(*simix_global->process_list)
68   s_xbt_swag_t swag;
69   process->read_bytes(&swag, sizeof(swag), remote(remote_swag));
70
71   smx_process_t p;
72   xbt_dynar_reset(target);
73
74   // Load each element of the dynar from the MCed process:
75   int i = 0;
76   for (p = (smx_process_t) swag.head; p; ++i) {
77
78     s_mc_smx_process_info_t info;
79     info.address = p;
80     info.name = nullptr;
81     info.hostname = nullptr;
82     process->read_bytes(&info.copy, sizeof(info.copy), remote(p));
83     xbt_dynar_push(target, &info);
84
85     // Lookup next process address:
86     p = (smx_process_t) xbt_swag_getNext(&info.copy, swag.offset);
87   }
88   assert(i == swag.count);
89 }
90
91 void MC_process_smx_refresh(simgrid::mc::Process* process)
92 {
93   xbt_assert(mc_mode == MC_MODE_SERVER);
94   if (process->cache_flags & MC_PROCESS_CACHE_FLAG_SIMIX_PROCESSES)
95     return;
96
97   // TODO, avoid to reload `&simix_global`, `simix_global`, `*simix_global`
98
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));
102
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));
107
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);
112
113   process->cache_flags |= MC_PROCESS_CACHE_FLAG_SIMIX_PROCESSES;
114 }
115
116 /** Get the issuer of a simcall (`req->issuer`)
117  *
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
120  *  address space.
121  *
122  *  @param process the MCed process
123  *  @param req     the simcall (copied in the local process)
124  */
125 smx_process_t MC_smx_simcall_get_issuer(smx_simcall_t req)
126 {
127   if (mc_mode == MC_MODE_CLIENT)
128     return req->issuer;
129
130   MC_process_smx_refresh(&mc_model_checker->process());
131
132   // This is the address of the smx_process in the MCed process:
133   void* address = req->issuer;
134
135   unsigned i;
136   mc_smx_process_info_t p;
137
138   // Lookup by address:
139   xbt_dynar_foreach_ptr(mc_model_checker->process().smx_process_infos, i, p)
140     if (p->address == address)
141       return &p->copy;
142   xbt_dynar_foreach_ptr(mc_model_checker->process().smx_old_process_infos, i, p)
143     if (p->address == address)
144       return &p->copy;
145
146   xbt_die("Issuer not found");
147 }
148
149 smx_process_t MC_smx_resolve_process(smx_process_t process_remote_address)
150 {
151   if (!process_remote_address)
152     return nullptr;
153   if (mc_mode == MC_MODE_CLIENT)
154     return process_remote_address;
155
156   mc_smx_process_info_t process_info = MC_smx_resolve_process_info(process_remote_address);
157   if (process_info)
158     return &process_info->copy;
159   else
160     return nullptr;
161 }
162
163 mc_smx_process_info_t MC_smx_resolve_process_info(smx_process_t process_remote_address)
164 {
165   if (mc_mode == MC_MODE_CLIENT)
166     xbt_die("No process_info for local process is not enabled.");
167
168   unsigned index;
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)
172       return process_info;
173   xbt_dynar_foreach_ptr(mc_model_checker->process().smx_old_process_infos, index, process_info)
174     if (process_info->address == process_remote_address)
175       return process_info;
176   xbt_die("Process info not found");
177 }
178
179 const char* MC_smx_process_get_host_name(smx_process_t p)
180 {
181   if (mc_mode == MC_MODE_CLIENT)
182     return sg_host_get_name(p->host);
183
184   simgrid::mc::Process* process = &mc_model_checker->process();
185
186   /* Horrible hack to find the offset of the id in the simgrid::s4u::Host.
187
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).
192
193      We are using a (C++11) unrestricted union in order to avoid
194      any construction/destruction of the simgrid::s4u::Host.
195   */
196   union fake_host {
197     simgrid::s4u::Host host;
198     fake_host() {}
199     ~fake_host() {}
200   };
201   fake_host foo;
202   const size_t offset = (char*) &foo.host.name() - (char*) &foo.host;
203
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;
214 }
215
216 const char* MC_smx_process_get_name(smx_process_t p)
217 {
218   simgrid::mc::Process* process = &mc_model_checker->process();
219   if (mc_mode == MC_MODE_CLIENT)
220     return p->name;
221   if (!p->name)
222     return nullptr;
223
224   mc_smx_process_info_t info = MC_smx_process_get_info(p);
225   if (!info->name) {
226     info->name = process->read_string(p->name);
227   }
228   return info->name;
229 }
230
231 #ifdef HAVE_SMPI
232 int MC_smpi_process_count(void)
233 {
234   if (mc_mode == MC_MODE_CLIENT)
235     return smpi_process_count();
236   else {
237     int res;
238     mc_model_checker->process().read_variable("process_count",
239       &res, sizeof(res));
240     return res;
241   }
242 }
243 #endif
244
245 unsigned long MC_smx_get_maxpid(void)
246 {
247   unsigned long maxpid;
248   mc_model_checker->process().read_variable("simix_process_maxpid",
249     &maxpid, sizeof(maxpid));
250   return maxpid;
251 }
252
253 }