Logo AND Algorithmique Numérique Distribuée

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