Logo AND Algorithmique Numérique Distribuée

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