Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
0c6b8398a1270499bc4acf0df2d05f8305fad175
[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 /** HACK, Statically "upcast" a s_smx_process_t into a SimixProcessInformation
24  *
25  *  This gets 'processInfo' from '&processInfo->copy'. It upcasts in the
26  *  sense that we could achieve the same thing by having SimixProcessInformation
27  *  inherit from s_smx_process_t but we don't really want to do that.
28  */
29 static inline
30 simgrid::mc::SimixProcessInformation* process_info_cast(smx_process_t p)
31 {
32   simgrid::mc::SimixProcessInformation temp;
33   std::size_t offset = (char*) temp.copy.getBuffer() - (char*)&temp;
34
35   simgrid::mc::SimixProcessInformation* process_info =
36     (simgrid::mc::SimixProcessInformation*) ((char*) p - offset);
37   return process_info;
38 }
39
40 /** Load the remote swag of processes into a vector
41  *
42  *  @param process     MCed process
43  *  @param target      Local vector (to be filled with copies of `s_smx_process_t`)
44  *  @param remote_swag Address of the process SWAG in the remote list
45  */
46 static void MC_process_refresh_simix_process_list(
47   simgrid::mc::Process* process,
48   std::vector<simgrid::mc::SimixProcessInformation>& target,
49   simgrid::mc::RemotePtr<s_xbt_swag_t> remote_swag)
50 {
51   target.clear();
52
53   // swag = REMOTE(*simix_global->process_list)
54   s_xbt_swag_t swag;
55   process->read_bytes(&swag, sizeof(swag), remote_swag);
56
57   // Load each element of the vector from the MCed process:
58   int i = 0;
59   for (smx_process_t p = (smx_process_t) swag.head; p; ++i) {
60
61     simgrid::mc::SimixProcessInformation info;
62     info.address = p;
63     info.hostname = nullptr;
64     process->read_bytes(&info.copy, sizeof(info.copy), remote(p));
65     target.push_back(std::move(info));
66
67     // Lookup next process address:
68     p = (smx_process_t) xbt_swag_getNext(&info.copy, swag.offset);
69   }
70   assert(i == swag.count);
71 }
72
73 namespace simgrid {
74 namespace mc {
75
76 void Process::refresh_simix()
77 {
78   if (this->cache_flags_ & Process::cache_simix_processes)
79     return;
80
81   // TODO, avoid to reload `&simix_global`, `simix_global`, `*simix_global`
82
83   static_assert(std::is_same<
84       std::unique_ptr<simgrid::simix::Global>,
85       decltype(simix_global)
86     >::value, "Unexpected type for simix_global");
87   static_assert(sizeof(simix_global) == sizeof(simgrid::simix::Global*),
88     "Bad size for simix_global");
89
90   // simix_global_p = REMOTE(simix_global.get());
91   RemotePtr<simgrid::simix::Global> simix_global_p =
92     this->read_variable<simgrid::simix::Global*>("simix_global");
93
94   // simix_global = REMOTE(*simix_global)
95   Remote<simgrid::simix::Global> simix_global =
96     this->read<simgrid::simix::Global>(simix_global_p);
97
98   MC_process_refresh_simix_process_list(
99     this, this->smx_process_infos,
100     remote(simix_global.getBuffer()->process_list));
101   MC_process_refresh_simix_process_list(
102     this, this->smx_old_process_infos,
103     remote(simix_global.getBuffer()->process_to_destroy));
104
105   this->cache_flags_ |= Process::cache_simix_processes;
106 }
107
108 }
109 }
110
111 /** Get the issuer of a simcall (`req->issuer`)
112  *
113  *  In split-process mode, it does the black magic necessary to get an address
114  *  of a (shallow) copy of the data structure the issuer SIMIX process in the local
115  *  address space.
116  *
117  *  @param process the MCed process
118  *  @param req     the simcall (copied in the local process)
119  */
120 smx_process_t MC_smx_simcall_get_issuer(s_smx_simcall_t const* req)
121 {
122   xbt_assert(mc_model_checker != nullptr);
123
124   // This is the address of the smx_process in the MCed process:
125   auto address = simgrid::mc::remote(req->issuer);
126
127   // Lookup by address:
128   for (auto& p : mc_model_checker->process().simix_processes())
129     if (p.address == address)
130       return p.copy.getBuffer();
131   for (auto& p : mc_model_checker->process().old_simix_processes())
132     if (p.address == address)
133       return p.copy.getBuffer();
134
135   xbt_die("Issuer not found");
136 }
137
138 const char* MC_smx_process_get_host_name(smx_process_t p)
139 {
140   if (mc_model_checker == nullptr)
141     return sg_host_get_name(p->host);
142
143   simgrid::mc::Process* process = &mc_model_checker->process();
144
145   /* HACK, Horrible hack to find the offset of the id in the simgrid::s4u::Host.
146
147      Offsetof is not supported for non-POD types but this should
148      work in practice for the targets currently supported by the MC
149      as long as we do not add funny features to the Host class
150      (such as virtual base).
151
152      We are using a (C++11) unrestricted union in order to avoid
153      any construction/destruction of the simgrid::s4u::Host.
154   */
155   union fake_host {
156     simgrid::s4u::Host host;
157     fake_host() {}
158     ~fake_host() {}
159   };
160   fake_host foo;
161   const size_t offset = (char*) &foo.host.name() - (char*) &foo.host;
162
163   // Read the simgrid::xbt::string in the MCed process:
164   simgrid::mc::SimixProcessInformation* info = process_info_cast(p);
165   auto remote_string_address = remote(
166     (simgrid::xbt::string_data*) ((char*) p->host + offset));
167   simgrid::xbt::string_data remote_string = process->read(remote_string_address);
168   char hostname[remote_string.len];
169   process->read_bytes(hostname, remote_string.len + 1, remote(remote_string.data));
170   info->hostname = mc_model_checker->get_host_name(hostname);
171   return info->hostname;
172 }
173
174 const char* MC_smx_process_get_name(smx_process_t p)
175 {
176   simgrid::mc::Process* process = &mc_model_checker->process();
177   if (mc_model_checker == nullptr)
178     return p->name.c_str();
179
180   simgrid::mc::SimixProcessInformation* info = process_info_cast(p);
181   if (info->name.empty()) {
182     simgrid::xbt::string_data string_data = (simgrid::xbt::string_data&)p->name;
183     info->name = process->read_string(remote(string_data.data), string_data.len);
184   }
185   return info->name.c_str();
186 }
187
188 #if HAVE_SMPI
189 int MC_smpi_process_count(void)
190 {
191   if (mc_model_checker == nullptr)
192     return smpi_process_count();
193   int res;
194   mc_model_checker->process().read_variable("process_count",
195     &res, sizeof(res));
196   return res;
197 }
198 #endif
199
200 unsigned long MC_smx_get_maxpid(void)
201 {
202   unsigned long maxpid;
203   mc_model_checker->process().read_variable("simix_process_maxpid",
204     &maxpid, sizeof(maxpid));
205   return maxpid;
206 }