Logo AND Algorithmique Numérique Distribuée

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