Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
codacy
[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/mc_smx.h"
9 #include "src/mc/ModelChecker.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 = (smx_actor_t*)malloc(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   free(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   // simix_global_p = REMOTE(simix_global.get());
101   RemotePtr<simgrid::simix::Global> simix_global_p =
102     this->read_variable<simgrid::simix::Global*>("simix_global");
103
104   // simix_global = REMOTE(*simix_global)
105   Remote<simgrid::simix::Global> simix_global =
106     this->read<simgrid::simix::Global>(simix_global_p);
107
108   MC_process_refresh_simix_actor_dynar(this, this->smx_actors_infos, remote(simix_global.getBuffer()->actors_vector));
109   MC_process_refresh_simix_process_list(this, this->smx_dead_actors_infos,
110                                         remote(simix_global.getBuffer()->process_to_destroy));
111
112   this->cache_flags_ |= RemoteClient::cache_simix_processes;
113 }
114
115 }
116 }
117
118 /** Get the issuer of a simcall (`req->issuer`)
119  *
120  *  In split-process mode, it does the black magic necessary to get an address
121  *  of a (shallow) copy of the data structure the issuer SIMIX actor in the local
122  *  address space.
123  *
124  *  @param process the MCed process
125  *  @param req     the simcall (copied in the local process)
126  */
127 smx_actor_t MC_smx_simcall_get_issuer(s_smx_simcall_t const* req)
128 {
129   xbt_assert(mc_model_checker != nullptr);
130
131   // This is the address of the smx_actor in the MCed process:
132   auto address = simgrid::mc::remote(req->issuer);
133
134   // Lookup by address:
135   for (auto& actor : mc_model_checker->process().actors())
136     if (actor.address == address)
137       return actor.copy.getBuffer();
138   for (auto& actor : mc_model_checker->process().dead_actors())
139     if (actor.address == address)
140       return actor.copy.getBuffer();
141
142   xbt_die("Issuer not found");
143 }
144
145 const char* MC_smx_actor_get_host_name(smx_actor_t actor)
146 {
147   if (mc_model_checker == nullptr)
148     return actor->host->getCname();
149
150   simgrid::mc::RemoteClient* process = &mc_model_checker->process();
151
152   /* HACK, Horrible hack to find the offset of the id in the simgrid::s4u::Host.
153
154      Offsetof is not supported for non-POD types but this should
155      work in practice for the targets currently supported by the MC
156      as long as we do not add funny features to the Host class
157      (such as virtual base).
158
159      We are using a (C++11) unrestricted union in order to avoid
160      any construction/destruction of the simgrid::s4u::Host.
161   */
162   union fake_host {
163     simgrid::s4u::Host host;
164     fake_host() {}
165     ~fake_host() {}
166   };
167   fake_host foo;
168   const size_t offset = (char*)&foo.host.getName() - (char*)&foo.host;
169
170   // Read the simgrid::xbt::string in the MCed process:
171   simgrid::mc::ActorInformation* info     = actor_info_cast(actor);
172   auto remote_string_address              = remote((simgrid::xbt::string_data*)((char*)actor->host + offset));
173   simgrid::xbt::string_data remote_string = process->read(remote_string_address);
174   char hostname[remote_string.len];
175   process->read_bytes(hostname, remote_string.len + 1, remote(remote_string.data));
176   info->hostname = mc_model_checker->get_host_name(hostname).c_str();
177   return info->hostname;
178 }
179
180 const char* MC_smx_actor_get_name(smx_actor_t actor)
181 {
182   simgrid::mc::RemoteClient* process = &mc_model_checker->process();
183   if (mc_model_checker == nullptr)
184     return actor->name.c_str();
185
186   simgrid::mc::ActorInformation* info = actor_info_cast(actor);
187   if (info->name.empty()) {
188     simgrid::xbt::string_data string_data = (simgrid::xbt::string_data&)actor->name;
189     info->name = process->read_string(remote(string_data.data), string_data.len);
190   }
191   return info->name.c_str();
192 }
193
194 #if HAVE_SMPI
195 int MC_smpi_process_count()
196 {
197   if (mc_model_checker == nullptr)
198     return smpi_process_count();
199   int res;
200   mc_model_checker->process().read_variable("process_count",
201     &res, sizeof(res));
202   return res;
203 }
204 #endif
205
206 unsigned long MC_smx_get_maxpid()
207 {
208   unsigned long maxpid;
209   mc_model_checker->process().read_variable("simix_process_maxpid",
210     &maxpid, sizeof(maxpid));
211   return maxpid;
212 }