Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' into fix/execute_benched
[simgrid.git] / src / mc / mc_smx.cpp
1 /* Copyright (c) 2015-2017. The SimGrid Team. All rights reserved.          */
2
3 /* This program is free software; you can redistribute it and/or modify it
4  * under the terms of the license (GNU LGPL) which comes with this package. */
5
6 #include "simgrid/s4u/Host.hpp"
7
8 #include "src/mc/ModelChecker.hpp"
9 #include "src/mc/mc_smx.hpp"
10
11 using simgrid::mc::remote;
12
13 /** HACK, Statically "upcast" a s_smx_actor_t into a ActorInformation
14  *
15  *  This gets 'actorInfo' from '&actorInfo->copy'. It upcasts in the
16  *  sense that we could achieve the same thing by having ActorInformation
17  *  inherit from s_smx_actor_t but we don't really want to do that.
18  */
19 static inline simgrid::mc::ActorInformation* actor_info_cast(smx_actor_t actor)
20 {
21   simgrid::mc::ActorInformation temp;
22   std::size_t offset = (char*) temp.copy.getBuffer() - (char*)&temp;
23
24   simgrid::mc::ActorInformation* process_info = (simgrid::mc::ActorInformation*)((char*)actor - offset);
25   return process_info;
26 }
27
28 /** Load the remote swag of processes into a vector
29  *
30  *  @param process     MCed process
31  *  @param target      Local vector (to be filled with copies of `s_smx_actor_t`)
32  *  @param remote_swag Address of the process SWAG in the remote list
33  */
34 static void MC_process_refresh_simix_process_list(simgrid::mc::RemoteClient* process,
35                                                   std::vector<simgrid::mc::ActorInformation>& target,
36                                                   simgrid::mc::RemotePtr<s_xbt_swag_t> remote_swag)
37 {
38   target.clear();
39
40   // swag = REMOTE(*simix_global->process_list)
41   s_xbt_swag_t swag;
42   process->read_bytes(&swag, sizeof(swag), remote_swag);
43
44   // Load each element of the vector from the MCed process:
45   int i = 0;
46   for (smx_actor_t p = (smx_actor_t) swag.head; p; ++i) {
47
48     simgrid::mc::ActorInformation info;
49     info.address = p;
50     info.hostname = nullptr;
51     process->read_bytes(&info.copy, sizeof(info.copy), remote(p));
52     target.push_back(std::move(info));
53
54     // Lookup next process address:
55     p = (smx_actor_t) xbt_swag_getNext(&info.copy, swag.offset);
56   }
57   assert(i == swag.count);
58 }
59
60 static void MC_process_refresh_simix_actor_dynar(simgrid::mc::RemoteClient* process,
61                                                  std::vector<simgrid::mc::ActorInformation>& target,
62                                                  simgrid::mc::RemotePtr<s_xbt_dynar_t> remote_dynar)
63 {
64   target.clear();
65
66   s_xbt_dynar_t dynar;
67   process->read_bytes(&dynar, sizeof(dynar), remote_dynar);
68
69   smx_actor_t* data = static_cast<smx_actor_t*>(::operator new(dynar.elmsize * dynar.used));
70   process->read_bytes(data, dynar.elmsize * dynar.used, dynar.data);
71
72   // Load each element of the vector from the MCed process:
73   for (unsigned int i = 0; i < dynar.used; ++i) {
74
75     simgrid::mc::ActorInformation info;
76     info.address  = data[i];
77     info.hostname = nullptr;
78     process->read_bytes(&info.copy, sizeof(info.copy), remote(data[i]));
79     target.push_back(std::move(info));
80   }
81   ::operator delete(data);
82 }
83 namespace simgrid {
84 namespace mc {
85
86 void RemoteClient::refresh_simix()
87 {
88   if (this->cache_flags_ & RemoteClient::cache_simix_processes)
89     return;
90
91   // TODO, avoid to reload `&simix_global`, `simix_global`, `*simix_global`
92
93   static_assert(std::is_same<
94       std::unique_ptr<simgrid::simix::Global>,
95       decltype(simix_global)
96     >::value, "Unexpected type for simix_global");
97   static_assert(sizeof(simix_global) == sizeof(simgrid::simix::Global*),
98     "Bad size for simix_global");
99
100   RemotePtr<simgrid::simix::Global> simix_global_p =
101     this->read_variable<simgrid::simix::Global*>("simix_global");
102
103   // simix_global = REMOTE(*simix_global)
104   Remote<simgrid::simix::Global> simix_global =
105     this->read<simgrid::simix::Global>(simix_global_p);
106
107   MC_process_refresh_simix_actor_dynar(this, this->smx_actors_infos, remote(simix_global.getBuffer()->actors_vector));
108   MC_process_refresh_simix_process_list(this, this->smx_dead_actors_infos,
109                                         remote(simix_global.getBuffer()->process_to_destroy));
110
111   this->cache_flags_ |= RemoteClient::cache_simix_processes;
112 }
113
114 }
115 }
116
117 /** Get the issuer of a simcall (`req->issuer`)
118  *
119  *  In split-process mode, it does the black magic necessary to get an address
120  *  of a (shallow) copy of the data structure the issuer SIMIX actor in the local
121  *  address space.
122  *
123  *  @param process the MCed process
124  *  @param req     the simcall (copied in the local process)
125  */
126 smx_actor_t MC_smx_simcall_get_issuer(s_smx_simcall_t const* req)
127 {
128   xbt_assert(mc_model_checker != nullptr);
129
130   // This is the address of the smx_actor in the MCed process:
131   auto address = simgrid::mc::remote(req->issuer);
132
133   // Lookup by address:
134   for (auto& actor : mc_model_checker->process().actors())
135     if (actor.address == address)
136       return actor.copy.getBuffer();
137   for (auto& actor : mc_model_checker->process().dead_actors())
138     if (actor.address == address)
139       return actor.copy.getBuffer();
140
141   xbt_die("Issuer not found");
142 }
143
144 const char* MC_smx_actor_get_host_name(smx_actor_t actor)
145 {
146   if (mc_model_checker == nullptr)
147     return actor->host->getCname();
148
149   simgrid::mc::RemoteClient* process = &mc_model_checker->process();
150
151   /* HACK, Horrible hack to find the offset of the id in the simgrid::s4u::Host.
152
153      Offsetof is not supported for non-POD types but this should
154      work in practice for the targets currently supported by the MC
155      as long as we do not add funny features to the Host class
156      (such as virtual base).
157
158      We are using a (C++11) unrestricted union in order to avoid
159      any construction/destruction of the simgrid::s4u::Host.
160   */
161   union fake_host {
162     simgrid::s4u::Host host;
163     fake_host() { /* Nothing to do*/}
164     ~fake_host() { /* Nothing to do*/}
165   };
166   fake_host foo;
167   const size_t offset = (char*)&foo.host.getName() - (char*)&foo.host;
168
169   // Read the simgrid::xbt::string in the MCed process:
170   simgrid::mc::ActorInformation* info     = actor_info_cast(actor);
171   auto remote_string_address              = remote((simgrid::xbt::string_data*)((char*)actor->host + offset));
172   simgrid::xbt::string_data remote_string = process->read(remote_string_address);
173   char hostname[remote_string.len];
174   process->read_bytes(hostname, remote_string.len + 1, remote(remote_string.data));
175   info->hostname = mc_model_checker->get_host_name(hostname).c_str();
176   return info->hostname;
177 }
178
179 const char* MC_smx_actor_get_name(smx_actor_t actor)
180 {
181   simgrid::mc::RemoteClient* process = &mc_model_checker->process();
182   if (mc_model_checker == nullptr)
183     return actor->name.c_str();
184
185   simgrid::mc::ActorInformation* info = actor_info_cast(actor);
186   if (info->name.empty()) {
187     simgrid::xbt::string_data string_data = simgrid::xbt::string::to_string_data(actor->name);
188     info->name = process->read_string(remote(string_data.data), string_data.len);
189   }
190   return info->name.c_str();
191 }
192
193 #if HAVE_SMPI
194 int MC_smpi_process_count()
195 {
196   if (mc_model_checker == nullptr)
197     return smpi_process_count();
198   int res;
199   mc_model_checker->process().read_variable("process_count",
200     &res, sizeof(res));
201   return res;
202 }
203 #endif
204
205 unsigned long MC_smx_get_maxpid()
206 {
207   unsigned long maxpid;
208   mc_model_checker->process().read_variable("simix_process_maxpid",
209     &maxpid, sizeof(maxpid));
210   return maxpid;
211 }