Logo AND Algorithmique Numérique Distribuée

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