Logo AND Algorithmique Numérique Distribuée

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