Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
bcdec8bd9ba8920fa40ce827a99ce62d155a088c
[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 list 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_dynar Address of the process dynar in the remote list
33  */
34 static void MC_process_refresh_simix_actor_dynar(simgrid::mc::RemoteClient* process,
35                                                  std::vector<simgrid::mc::ActorInformation>& target,
36                                                  simgrid::mc::RemotePtr<s_xbt_dynar_t> remote_dynar)
37 {
38   target.clear();
39
40   s_xbt_dynar_t dynar;
41   process->read_bytes(&dynar, sizeof(dynar), remote_dynar);
42
43   smx_actor_t* data = static_cast<smx_actor_t*>(::operator new(dynar.elmsize * dynar.used));
44   process->read_bytes(data, dynar.elmsize * dynar.used, dynar.data);
45
46   // Load each element of the vector from the MCed process:
47   for (unsigned int i = 0; i < dynar.used; ++i) {
48
49     simgrid::mc::ActorInformation info;
50     info.address  = data[i];
51     info.hostname = nullptr;
52     process->read_bytes(&info.copy, sizeof(info.copy), remote(data[i]));
53     target.push_back(std::move(info));
54   }
55   ::operator delete(data);
56 }
57 namespace simgrid {
58 namespace mc {
59
60 void RemoteClient::refresh_simix()
61 {
62   if (this->cache_flags_ & RemoteClient::cache_simix_processes)
63     return;
64
65   // TODO, avoid to reload `&simix_global`, `simix_global`, `*simix_global`
66
67   static_assert(std::is_same<
68       std::unique_ptr<simgrid::simix::Global>,
69       decltype(simix_global)
70     >::value, "Unexpected type for simix_global");
71   static_assert(sizeof(simix_global) == sizeof(simgrid::simix::Global*),
72     "Bad size for simix_global");
73
74   RemotePtr<simgrid::simix::Global> simix_global_p =
75     this->read_variable<simgrid::simix::Global*>("simix_global");
76
77   // simix_global = REMOTE(*simix_global)
78   Remote<simgrid::simix::Global> simix_global =
79     this->read<simgrid::simix::Global>(simix_global_p);
80
81   MC_process_refresh_simix_actor_dynar(this, this->smx_actors_infos, remote(simix_global.getBuffer()->actors_vector));
82   MC_process_refresh_simix_actor_dynar(this, this->smx_dead_actors_infos,
83                                        remote(simix_global.getBuffer()->dead_actors_vector));
84
85   this->cache_flags_ |= RemoteClient::cache_simix_processes;
86 }
87
88 }
89 }
90
91 /** Get the issuer of a simcall (`req->issuer`)
92  *
93  *  In split-process mode, it does the black magic necessary to get an address
94  *  of a (shallow) copy of the data structure the issuer SIMIX actor in the local
95  *  address space.
96  *
97  *  @param process the MCed process
98  *  @param req     the simcall (copied in the local process)
99  */
100 smx_actor_t MC_smx_simcall_get_issuer(s_smx_simcall_t const* req)
101 {
102   xbt_assert(mc_model_checker != nullptr);
103
104   // This is the address of the smx_actor in the MCed process:
105   auto address = simgrid::mc::remote(req->issuer);
106
107   // Lookup by address:
108   for (auto& actor : mc_model_checker->process().actors())
109     if (actor.address == address)
110       return actor.copy.getBuffer();
111   for (auto& actor : mc_model_checker->process().dead_actors())
112     if (actor.address == address)
113       return actor.copy.getBuffer();
114
115   xbt_die("Issuer not found");
116 }
117
118 const char* MC_smx_actor_get_host_name(smx_actor_t actor)
119 {
120   if (mc_model_checker == nullptr)
121     return actor->host->getCname();
122
123   simgrid::mc::RemoteClient* process = &mc_model_checker->process();
124
125   /* HACK, Horrible hack to find the offset of the id in the simgrid::s4u::Host.
126
127      Offsetof is not supported for non-POD types but this should
128      work in practice for the targets currently supported by the MC
129      as long as we do not add funny features to the Host class
130      (such as virtual base).
131
132      We are using a (C++11) unrestricted union in order to avoid
133      any construction/destruction of the simgrid::s4u::Host.
134   */
135   union fake_host {
136     simgrid::s4u::Host host;
137     fake_host() { /* Nothing to do*/}
138     ~fake_host() { /* Nothing to do*/}
139   };
140   fake_host foo;
141   const size_t offset = (char*)&foo.host.getName() - (char*)&foo.host;
142
143   // Read the simgrid::xbt::string in the MCed process:
144   simgrid::mc::ActorInformation* info     = actor_info_cast(actor);
145   auto remote_string_address              = remote((simgrid::xbt::string_data*)((char*)actor->host + offset));
146   simgrid::xbt::string_data remote_string = process->read(remote_string_address);
147   char hostname[remote_string.len];
148   process->read_bytes(hostname, remote_string.len + 1, remote(remote_string.data));
149   info->hostname = mc_model_checker->get_host_name(hostname).c_str();
150   return info->hostname;
151 }
152
153 const char* MC_smx_actor_get_name(smx_actor_t actor)
154 {
155   simgrid::mc::RemoteClient* process = &mc_model_checker->process();
156   if (mc_model_checker == nullptr)
157     return actor->name.c_str();
158
159   simgrid::mc::ActorInformation* info = actor_info_cast(actor);
160   if (info->name.empty()) {
161     simgrid::xbt::string_data string_data = simgrid::xbt::string::to_string_data(actor->name);
162     info->name = process->read_string(remote(string_data.data), string_data.len);
163   }
164   return info->name.c_str();
165 }
166
167 #if HAVE_SMPI
168 int MC_smpi_process_count()
169 {
170   if (mc_model_checker == nullptr)
171     return smpi_process_count();
172   int res;
173   mc_model_checker->process().read_variable("process_count",
174     &res, sizeof(res));
175   return res;
176 }
177 #endif
178
179 unsigned long MC_smx_get_maxpid()
180 {
181   unsigned long maxpid;
182   mc_model_checker->process().read_variable("simix_process_maxpid",
183     &maxpid, sizeof(maxpid));
184   return maxpid;
185 }