assign(s, s == nullptr ? 0 : std::strlen(s));
return *this;
}
- string& operator=(string& s)
+ string& operator=(string const& s)
{
assign(s.c_str(), s.size());
return *this;
}
- string& operator=(std::string& s)
+ string& operator=(std::string const& s)
{
assign(s.c_str(), s.size());
return *this;
string_data::data = (char*) &NUL;
}
- // Compare
- int compare(string const& that) const
+ bool equals(const char* data, std::size_t len) const
{
- size_t n = std::min(this->size(), that.size());
- int res = memcmp(this->c_str(), that.c_str(), n);
- if (res != 0)
- return res;
- else if (this->size() == that.size())
- return 0;
- else if (this->size() < that.size())
- return -1;
- else
- return 1;
+ return this->size() == len
+ && std::memcmp(this->c_str(), data, len) == 0;
}
+
bool operator==(string const& that) const
{
- return this->size() == that.size()
- && std::memcmp(this->c_str(), that.c_str(), this->size()) == 0;
+ return this->equals(that.c_str(), that.size());
}
- bool operator!=(string const& that) const
+ bool operator==(std::string const& that) const
{
- return !(*this == that);
+ return this->equals(that.c_str(), that.size());
}
- bool operator<(string const& that) const
+ bool operator==(const char* that) const
{
- return compare(that) < 0;
+ return this->equals(that, std::strlen(that));
}
- bool operator<=(string const& that) const
+
+ template<class X>
+ bool operator!=(X const& that) const
{
- return compare(that) <= 0;
+ return !((*this) == that);
}
- bool operator>(string const& that) const
+
+ // Compare:
+ int compare(const char* data, std::size_t len) const
{
- return compare(that) > 0;
+ size_t n = std::min(this->size(), len);
+ int res = memcmp(this->c_str(), data, n);
+ if (res != 0)
+ return res;
+ else if (this->size() == len)
+ return 0;
+ else if (this->size() < len)
+ return -1;
+ else
+ return 1;
}
- bool operator>=(string const& that) const
+ int compare(string const& that) const
{
- return compare(that) >= 0;
+ return this->compare(that.c_str(), that.size());
}
-
- // Compare with std::string
- bool operator==(std::string const& that) const
+ int compare(std::string const& that) const
{
- return this->size() == that.size()
- && std::memcmp(this->c_str(), that.c_str(), this->size()) == 0;
+ return this->compare(that.c_str(), that.size());
}
- bool operator!=(std::string const& that) const
+ int compare(const char* that) const
{
- return !(*this == that);
+ return this->compare(that, std::strlen(that));
}
- bool operator<(std::string const& that) const
+
+ // Define < <= >= > in term of compare():
+ template<class X>
+ bool operator<(X const& that) const
{
- return compare(that) < 0;
+ return this->compare(that) < 0;
}
- bool operator<=(std::string const& that) const
+ template<class X>
+ bool operator<=(X const& that) const
{
- return compare(that) <= 0;
+ return this->compare(that) <= 0;
}
- bool operator>(std::string const& that) const
+ template<class X>
+ bool operator>(X const& that) const
{
- return compare(that) > 0;
+ return this->compare(that) > 0;
}
- bool operator>=(std::string const& that) const
+ template<class X>
+ bool operator>=(X const& that) const
{
- return compare(that) >= 0;
+ return this->compare(that) >= 0;
}
};
#include <cstring>
#include <type_traits>
+#include <string>
+#include <vector>
+
#include "src/mc/mc_forward.hpp"
#include "src/mc/RemotePtr.hpp"
static constexpr ReadOptions lazy() { return ReadOptions(1); }
};
-/** A value from another process
+/** HACK, A value from another process
*
* This represents a value from another process:
*
* cross-architecture (such as 32-bit/64-bit access).
*/
template<class T>
-class Remote {
+union Remote {
private:
- // If we use a union, it won't work with abstract types:
- char buffer[sizeof(T)];
+ T buffer;
public:
- // HACK, some code currently cast this to T* which is **not** legal.
- void* data() { return buffer; }
- const void* data() const { return buffer; }
- constexpr std::size_t size() const { return sizeof(T); }
- operator T() const {
- static_assert(std::is_trivial<T>::value, "Cannot convert non trivial type");
- T res;
- std::memcpy(&res, buffer, sizeof(T));
- return res;
- }
Remote() {}
- Remote(T const& x)
+ ~Remote() {}
+ Remote(Remote const& that)
{
- std::memcpy(&x, buffer, sizeof(T));
+ std::memcpy(&buffer, &that.buffer, sizeof(buffer));
}
- Remote& operator=(T const& x)
+ Remote& operator=(Remote const& that)
{
- std::memcpy(&x, buffer, sizeof(T));
+ std::memcpy(&buffer, &that.buffer, sizeof(buffer));
+ return *this;
+ }
+ T* getBuffer() { return &buffer; }
+ const T* getBuffer() const { return &buffer; }
+ std::size_t getBufferSize() const { return sizeof(T); }
+ operator T() const {
+ static_assert(std::is_trivial<T>::value, "Cannot convert non trivial type");
+ return buffer;
+ }
+ void clear()
+ {
+ std::memset(static_cast<void*>(&buffer), 0, sizeof(T));
}
};
/** Read a given data structure from the address space */
template<class T> inline
- void read(T *buffer, RemotePtr<T> ptr, int process_index = ProcessIndexAny)
+ void read(T *buffer, RemotePtr<T> ptr, int process_index = ProcessIndexAny) const
{
this->read_bytes(buffer, sizeof(T), ptr, process_index);
}
template<class T> inline
- void read(Remote<T>& buffer, RemotePtr<T> ptr, int process_index = ProcessIndexAny)
+ void read(Remote<T>& buffer, RemotePtr<T> ptr, int process_index = ProcessIndexAny) const
{
- this->read_bytes(buffer.data(), sizeof(T), ptr, process_index);
+ this->read_bytes(buffer.getBuffer(), sizeof(T), ptr, process_index);
}
/** Read a given data structure from the address space */
template<class T> inline
- Remote<T> read(RemotePtr<T> ptr, int process_index = ProcessIndexMissing)
+ Remote<T> read(RemotePtr<T> ptr, int process_index = ProcessIndexMissing) const
{
Remote<T> res;
this->read_bytes(&res, sizeof(T), ptr, process_index);
return res;
}
+
+ std::string read_string(RemotePtr<char> address, std::size_t len) const
+ {
+ // TODO, use std::vector with .data() in C++17 to avoid useless copies
+ std::vector<char> buffer(len);
+ buffer[len] = '\0';
+ this->read_bytes(buffer.data(), len, address);
+ return std::string(buffer.data(), buffer.size());
+ }
+
};
}
simgrid::mc::Remote<simgrid::simix::Comm> temp_comm;
mc_model_checker->process().read(temp_comm, comm_addr);
simgrid::simix::Comm* comm =
- static_cast<simgrid::simix::Comm*>(temp_comm.data());
+ static_cast<simgrid::simix::Comm*>(temp_comm.getBuffer());
smx_process_t src_proc = mc_model_checker->process().resolveProcess(
simgrid::mc::remote(comm->src_proc));
mc_model_checker->process().read(temp_synchro, remote(
static_cast<simgrid::simix::Comm*>(pattern->comm_addr)));
simgrid::simix::Comm* synchro =
- static_cast<simgrid::simix::Comm*>(temp_synchro.data());
+ static_cast<simgrid::simix::Comm*>(temp_synchro.getBuffer());
char* remote_name = mc_model_checker->process().read<char*>(
(std::uint64_t)(synchro->mbox ? &synchro->mbox->name : &synchro->mbox_cpy->name));
simgrid::mc::Remote<simgrid::simix::Comm> temp_comm;
mc_model_checker->process().read(temp_comm, remote(
static_cast<simgrid::simix::Comm*>(pattern->comm_addr)));
- simgrid::simix::Comm* comm =
- static_cast<simgrid::simix::Comm*>(temp_comm.data());
+ simgrid::simix::Comm* comm = temp_comm.getBuffer();
char* remote_name;
mc_model_checker->process().read(&remote_name,
/* Get an enabled process and insert it in the interleave set of the initial state */
for (auto& p : mc_model_checker->process().simix_processes())
- if (simgrid::mc::process_is_enabled(&p.copy))
- initial_state->interleave(&p.copy);
+ if (simgrid::mc::process_is_enabled(p.copy.getBuffer()))
+ initial_state->interleave(p.copy.getBuffer());
stack_.push_back(std::move(initial_state));
}
/* Get enabled processes and insert them in the interleave set of the next state */
for (auto& p : mc_model_checker->process().simix_processes())
- if (simgrid::mc::process_is_enabled(&p.copy))
- next_state->interleave(&p.copy);
+ if (simgrid::mc::process_is_enabled(p.copy.getBuffer()))
+ next_state->interleave(p.copy.getBuffer());
if (dot_output != nullptr)
fprintf(dot_output, "\"%d\" -> \"%d\" [%s];\n",
next_pair->depth = 1;
/* Get enabled processes and insert them in the interleave set of the next graph_state */
for (auto& p : mc_model_checker->process().simix_processes())
- if (simgrid::mc::process_is_enabled(&p.copy))
- next_pair->graph_state->interleave(&p.copy);
+ if (simgrid::mc::process_is_enabled(p.copy.getBuffer()))
+ next_pair->graph_state->interleave(p.copy.getBuffer());
next_pair->requests = next_pair->graph_state->interleaveSize();
/* FIXME : get search_cycle value for each acceptant state */
if (next_pair->automaton_state->type == 1 ||
this->read_bytes(target, size, remote(var->address));
}
-std::string Process::read_string(RemotePtr<void> address) const
+std::string Process::read_string(RemotePtr<char> address) const
{
if (!address)
return {};
+ // TODO, use std::vector with .data() in C++17 to avoid useless copies
std::vector<char> res(128);
off_t off = 0;
class SimixProcessInformation {
public:
/** MCed address of the process */
- RemotePtr<s_smx_process_t> address = nullptr;
- union {
- /** (Flat) Copy of the process data structure */
- struct s_smx_process copy;
- };
+ RemotePtr<simgrid::simix::Process> address = nullptr;
+ Remote<simgrid::simix::Process> copy;
+
/** Hostname (owned by `mc_modelchecker->hostnames`) */
const char* hostname = nullptr;
std::string name;
read_variable(name, &res, sizeof(T));
return res;
}
- std::string read_string(RemotePtr<void> address) const;
+ std::string read_string(RemotePtr<char> address) const;
+ std::string read_string(RemotePtr<char> address, std::size_t len) const
+ {
+ return AddressSpace::read_string(address, len);
+ }
// Write memory:
void write_bytes(const void* buffer, size_t len, RemotePtr<void> address);
/** Get a local description of a remote SIMIX process */
simgrid::mc::SimixProcessInformation* resolveProcessInfo(
- simgrid::mc::RemotePtr<s_smx_process_t> process)
+ simgrid::mc::RemotePtr<simgrid::simix::Process> process)
{
xbt_assert(mc_model_checker != nullptr);
if (!process)
}
/** Get a local copy of the SIMIX process structure */
- smx_process_t resolveProcess(simgrid::mc::RemotePtr<s_smx_process_t> process)
+ simgrid::simix::Process* resolveProcess(simgrid::mc::RemotePtr<simgrid::simix::Process> process)
{
simgrid::mc::SimixProcessInformation* process_info =
this->resolveProcessInfo(process);
if (process_info)
- return &process_info->copy;
+ return process_info->copy.getBuffer();
else
return nullptr;
}
/* Get an enabled process and insert it in the interleave set of the next state */
for (auto& p : mc_model_checker->process().simix_processes())
- if (simgrid::mc::process_is_enabled(&p.copy)) {
- next_state->interleave(&p.copy);
+ if (simgrid::mc::process_is_enabled(p.copy.getBuffer())) {
+ next_state->interleave(p.copy.getBuffer());
if (reductionMode_ != simgrid::mc::ReductionMode::none)
break;
}
/* Get an enabled process and insert it in the interleave set of the initial state */
for (auto& p : mc_model_checker->process().simix_processes())
- if (simgrid::mc::process_is_enabled(&p.copy)) {
- initial_state->interleave(&p.copy);
+ if (simgrid::mc::process_is_enabled(p.copy.getBuffer())) {
+ initial_state->interleave(p.copy.getBuffer());
if (reductionMode_ != simgrid::mc::ReductionMode::none)
break;
}
simgrid::mc::Remote<simgrid::simix::Comm> temp_comm;
if (mc_model_checker != nullptr) {
mc_model_checker->process().read(temp_comm, remote(act));
- act = static_cast<simgrid::simix::Comm*>(temp_comm.data());
+ act = static_cast<simgrid::simix::Comm*>(temp_comm.getBuffer());
}
#endif
if (mc_model_checker != nullptr) {
memcpy(&act, buffer + comms->elmsize * index, sizeof(act));
mc_model_checker->process().read(temp_comm, remote(act));
- act = static_cast<simgrid::simix::Comm*>(temp_comm.data());
+ act = static_cast<simgrid::simix::Comm*>(temp_comm.getBuffer());
}
else
#endif
snapshot->num_state = num_state;
for (auto& p : mc_model_checker->process().simix_processes())
- snapshot->enabled_processes.insert(p.copy.pid);
+ snapshot->enabled_processes.insert(p.copy.getBuffer()->pid);
snapshot_handle_ignore(snapshot.get());
simgrid::mc::UnwindContext context;
unw_context_t raw_context =
- mc_model_checker->process().read<unw_context_t>(
+ (unw_context_t) mc_model_checker->process().read<unw_context_t>(
simgrid::mc::remote((unw_context_t *)stack.context));
context.initialize(&mc_model_checker->process(), &raw_context);
if (use_remote_comm) {
mc_model_checker->process().read(temp_synchro, remote(
static_cast<simgrid::simix::Comm*>(remote_act)));
- act = static_cast<simgrid::simix::Comm*>(temp_synchro.data());
+ act = temp_synchro.getBuffer();
} else
act = remote_act;
if (use_remote_comm) {
mc_model_checker->process().read(temp_synchro, remote(
static_cast<simgrid::simix::Comm*>(remote_act)));
- act = static_cast<simgrid::simix::Comm*>(temp_synchro.data());
+ act = temp_synchro.getBuffer();
} else
act = remote_act;
simgrid::mc::Remote<simgrid::simix::Comm> temp_comm;
mc_model_checker->process().read(temp_comm, remote(
static_cast<simgrid::simix::Comm*>(remote_act)));
- simgrid::simix::Comm* comm = static_cast<simgrid::simix::Comm*>(temp_comm.data());
+ simgrid::simix::Comm* comm = temp_comm.getBuffer();
return comm->src_proc && comm->dst_proc;
}
simgrid::mc::Remote<simgrid::simix::Comm> temp_comm;
mc_model_checker->process().read(temp_comm, remote(
static_cast<simgrid::simix::Comm*>(remote_act)));
- simgrid::simix::Comm* comm = static_cast<simgrid::simix::Comm*>(temp_comm.data());
+ simgrid::simix::Comm* comm = temp_comm.getBuffer();
smx_process_t src_proc = mc_model_checker->process().resolveProcess(
simgrid::mc::remote(comm->src_proc));
simgrid::mc::Remote<simgrid::simix::Comm> temp_comm;
mc_model_checker->process().read(temp_comm, remote(
static_cast<simgrid::simix::Comm*>(remote_act)));
- simgrid::simix::Comm* comm = static_cast<simgrid::simix::Comm*>(temp_comm.data());
+ simgrid::simix::Comm* comm = temp_comm.getBuffer();
if (comm->src_proc == nullptr || comm->dst_proc == nullptr) {
if (issuer->host)
label = simgrid::xbt::string_printf("[(%lu)%s] Test FALSE",
using simgrid::mc::remote;
-/** Statically "upcast" a s_smx_process_t into a SimixProcessInformation
+/** HACK, Statically "upcast" a s_smx_process_t into a SimixProcessInformation
*
* This gets 'processInfo' from '&processInfo->copy'. It upcasts in the
* sense that we could achieve the same thing by having SimixProcessInformation
static inline
simgrid::mc::SimixProcessInformation* process_info_cast(smx_process_t p)
{
+ simgrid::mc::SimixProcessInformation temp;
+ std::size_t offset = (char*) temp.copy.getBuffer() - (char*)&temp;
+
simgrid::mc::SimixProcessInformation* process_info =
- (simgrid::mc::SimixProcessInformation*)
- ((char*) p - offsetof(simgrid::mc::SimixProcessInformation, copy));
+ (simgrid::mc::SimixProcessInformation*) ((char*) p - offset);
return process_info;
}
// Lookup by address:
for (auto& p : mc_model_checker->process().simix_processes())
if (p.address == address)
- return &p.copy;
+ return p.copy.getBuffer();
for (auto& p : mc_model_checker->process().old_simix_processes())
if (p.address == address)
- return &p.copy;
+ return p.copy.getBuffer();
xbt_die("Issuer not found");
}
// Read the simgrid::xbt::string in the MCed process:
simgrid::mc::SimixProcessInformation* info = process_info_cast(p);
- simgrid::xbt::string_data remote_string;
auto remote_string_address = remote(
(simgrid::xbt::string_data*) ((char*) p->host + offset));
- process->read_bytes(&remote_string, sizeof(remote_string), remote_string_address);
+ simgrid::xbt::string_data remote_string = process->read(remote_string_address);
char hostname[remote_string.len];
process->read_bytes(hostname, remote_string.len + 1, remote(remote_string.data));
info->hostname = mc_model_checker->get_host_name(hostname);
{
simgrid::mc::Process* process = &mc_model_checker->process();
if (mc_model_checker == nullptr)
- return p->name;
- if (!p->name)
- return nullptr;
+ return p->name.c_str();
simgrid::mc::SimixProcessInformation* info = process_info_cast(p);
- if (info->name.empty())
- info->name = process->read_string(p->name);
+ if (info->name.empty()) {
+ simgrid::xbt::string_data string_data = (simgrid::xbt::string_data&)p->name;
+ info->name = process->read_string(remote(string_data.data), string_data.len);
+ }
return info->name.c_str();
}
State::State()
{
- std::memset(this->internal_comm.data(), 0, this->internal_comm.size());
+ this->internal_comm.clear();
std::memset(&this->internal_req, 0, sizeof(this->internal_req));
std::memset(&this->executed_req, 0, sizeof(this->executed_req));
}
static_cast<simgrid::simix::Comm*>(simcall_comm_wait__get__comm(&process->simcall)));
simgrid::mc::Remote<simgrid::simix::Comm> temp_act;
mc_model_checker->process().read(temp_act, remote_act);
- simgrid::simix::Comm* act = static_cast<simgrid::simix::Comm*>(temp_act.data());
+ simgrid::simix::Comm* act = temp_act.getBuffer();
if (act->src_proc && act->dst_proc)
state->transition.argument = 0;
else if (act->src_proc == nullptr && act->type == SIMIX_COMM_READY
smx_simcall_t MC_state_get_request(simgrid::mc::State* state)
{
for (auto& p : mc_model_checker->process().simix_processes()) {
- smx_simcall_t res = MC_state_get_request_for_process(state, &p.copy);
+ smx_simcall_t res = MC_state_get_request_for_process(state, p.copy.getBuffer());
if (res)
return res;
}
xbt_assert(code && host != NULL, "Invalid parameters");
/* Process data */
process->pid = simix_process_maxpid++;
- process->name = std::string(name);
+ process->name = simgrid::xbt::string(name);
process->host = host;
process->data = data;
process->comms = xbt_fifo_new();
#include <string>
#include <xbt/base.h>
+#include <xbt/string.hpp>
#include <simgrid/simix.hpp>
#include "simgrid/simix.h"
unsigned long pid = 0;
unsigned long ppid = 0;
- std::string name;
+ simgrid::xbt::string name;
sg_host_t host = nullptr; /* the host on which the process is running */
smx_context_t context = nullptr; /* the context (uctx/raw/thread) that executes the user function */
xbt_running_ctx_t *running_ctx = nullptr;