Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
900e372c547ffc5b9612d4b21cfac8adcd06eef5
[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 mc_smx_process_info_t 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   mc_smx_process_info_t process_info =
37     (mc_smx_process_info_t)
38       ((char*) p - offsetof(s_mc_smx_process_info_t, 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 void MC_process_smx_refresh(simgrid::mc::Process* process)
75 {
76   xbt_assert(mc_mode == MC_MODE_SERVER);
77   if (process->cache_flags & MC_PROCESS_CACHE_FLAG_SIMIX_PROCESSES)
78     return;
79
80   // TODO, avoid to reload `&simix_global`, `simix_global`, `*simix_global`
81
82   // simix_global_p = REMOTE(simix_global);
83   smx_global_t simix_global_p;
84   process->read_variable("simix_global", &simix_global_p, sizeof(simix_global_p));
85
86   // simix_global = REMOTE(*simix_global)
87   s_smx_global_t simix_global;
88   process->read_bytes(&simix_global, sizeof(simix_global),
89     remote(simix_global_p));
90
91   MC_process_refresh_simix_process_list(
92     process, process->smx_process_infos, simix_global.process_list);
93   MC_process_refresh_simix_process_list(
94     process, process->smx_old_process_infos, simix_global.process_to_destroy);
95
96   process->cache_flags |= MC_PROCESS_CACHE_FLAG_SIMIX_PROCESSES;
97 }
98
99 /** Get the issuer of a simcall (`req->issuer`)
100  *
101  *  In split-process mode, it does the black magic necessary to get an address
102  *  of a (shallow) copy of the data structure the issuer SIMIX process in the local
103  *  address space.
104  *
105  *  @param process the MCed process
106  *  @param req     the simcall (copied in the local process)
107  */
108 smx_process_t MC_smx_simcall_get_issuer(smx_simcall_t req)
109 {
110   if (mc_mode == MC_MODE_CLIENT)
111     return req->issuer;
112
113   MC_process_smx_refresh(&mc_model_checker->process());
114
115   // This is the address of the smx_process in the MCed process:
116   void* address = req->issuer;
117
118   // Lookup by address:
119   for (auto& p : mc_model_checker->process().smx_process_infos)
120     if (p.address == address)
121       return &p.copy;
122   for (auto& p : mc_model_checker->process().smx_old_process_infos)
123     if (p.address == address)
124       return &p.copy;
125
126   xbt_die("Issuer not found");
127 }
128
129 smx_process_t MC_smx_resolve_process(smx_process_t process_remote_address)
130 {
131   if (!process_remote_address)
132     return nullptr;
133   if (mc_mode == MC_MODE_CLIENT)
134     return process_remote_address;
135
136   mc_smx_process_info_t process_info = MC_smx_resolve_process_info(process_remote_address);
137   if (process_info)
138     return &process_info->copy;
139   else
140     return nullptr;
141 }
142
143 mc_smx_process_info_t MC_smx_resolve_process_info(smx_process_t process_remote_address)
144 {
145   if (mc_mode == MC_MODE_CLIENT)
146     xbt_die("No process_info for local process is not enabled.");
147   for (auto& process_info : mc_model_checker->process().smx_process_infos)
148     if (process_info.address == process_remote_address)
149       return &process_info;
150   for (auto& process_info : mc_model_checker->process().smx_old_process_infos)
151     if (process_info.address == process_remote_address)
152       return &process_info;
153   xbt_die("Process info not found");
154 }
155
156 const char* MC_smx_process_get_host_name(smx_process_t p)
157 {
158   if (mc_mode == MC_MODE_CLIENT)
159     return sg_host_get_name(p->host);
160
161   simgrid::mc::Process* process = &mc_model_checker->process();
162
163   /* Horrible hack to find the offset of the id in the simgrid::s4u::Host.
164
165      Offsetof is not supported for non-POD types but this should
166      work in pratice for the targets currently supported by the MC
167      as long as we do not add funny features to the Host class
168      (such as virtual base).
169
170      We are using a (C++11) unrestricted union in order to avoid
171      any construction/destruction of the simgrid::s4u::Host.
172   */
173   union fake_host {
174     simgrid::s4u::Host host;
175     fake_host() {}
176     ~fake_host() {}
177   };
178   fake_host foo;
179   const size_t offset = (char*) &foo.host.name() - (char*) &foo.host;
180
181   // Read the simgrid::xbt::string in the MCed process:
182   mc_smx_process_info_t info = MC_smx_process_get_info(p);
183   simgrid::xbt::string_data remote_string;
184   auto remote_string_address = remote(
185     (simgrid::xbt::string_data*) ((char*) p->host + offset));
186   process->read_bytes(&remote_string, sizeof(remote_string), remote_string_address);
187   char hostname[remote_string.len];
188   process->read_bytes(hostname, remote_string.len + 1, remote(remote_string.data));
189   info->hostname = mc_model_checker->get_host_name(hostname);
190   return info->hostname;
191 }
192
193 const char* MC_smx_process_get_name(smx_process_t p)
194 {
195   simgrid::mc::Process* process = &mc_model_checker->process();
196   if (mc_mode == MC_MODE_CLIENT)
197     return p->name;
198   if (!p->name)
199     return nullptr;
200
201   mc_smx_process_info_t info = MC_smx_process_get_info(p);
202   if (info->name.empty()) {
203     char* name = process->read_string(p->name);
204     info->name = name;
205     free(name);
206   }
207   return info->name.c_str();
208 }
209
210 #ifdef HAVE_SMPI
211 int MC_smpi_process_count(void)
212 {
213   if (mc_mode == MC_MODE_CLIENT)
214     return smpi_process_count();
215   else {
216     int res;
217     mc_model_checker->process().read_variable("process_count",
218       &res, sizeof(res));
219     return res;
220   }
221 }
222 #endif
223
224 unsigned long MC_smx_get_maxpid(void)
225 {
226   unsigned long maxpid;
227   mc_model_checker->process().read_variable("simix_process_maxpid",
228     &maxpid, sizeof(maxpid));
229   return maxpid;
230 }
231
232 }