From: Gabriel Corona Date: Tue, 15 Dec 2015 14:46:58 +0000 (+0100) Subject: [mc] Fix the MC wrt the simgrid::Host modification X-Git-Tag: v3_13~1438 X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/commitdiff_plain/ad0cb80ebff7603232ec1621d9b6cfa1ea3471f6 [mc] Fix the MC wrt the simgrid::Host modification --- diff --git a/include/simgrid/Host.hpp b/include/simgrid/Host.hpp index d61aefabfa..e1d2999faa 100644 --- a/include/simgrid/Host.hpp +++ b/include/simgrid/Host.hpp @@ -7,22 +7,24 @@ #ifndef SIMGRID_HOST_HPP #define SIMGRID_HOST_HPP +#include #include #include #include #include #include +#include namespace simgrid { XBT_PUBLIC_CLASS Host : public simgrid::xbt::Facetable { private: - std::string id_; + simgrid::xbt::string id_; public: - Host(std::string id); + Host(std::string const& id); ~Host(); - std::string const& id() const { return id_; } + simgrid::xbt::string const& id() const { return id_; } static Host* by_name_or_null(const char* name); static Host* by_name_or_create(const char* name); }; diff --git a/include/xbt/string.hpp b/include/xbt/string.hpp new file mode 100644 index 0000000000..30d6737a70 --- /dev/null +++ b/include/xbt/string.hpp @@ -0,0 +1,288 @@ +/* Copyright (c) 2015. The SimGrid Team. + * All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + +#ifndef SIMGRIC_XBT_STRING_HPP +#define SIMGRIC_XBT_STRING_HPP + +#ifdef HAVE_MC + +#include +#include +#include +#include +#include +#include + +#include + +namespace simgrid { +namespace xbt { + +/** POD structure representation of a string + */ +struct string_data { + char* data; + std::size_t len; +}; + +/** A std::string with well-known representation + * + * This is a (incomplete) drop-in replacement for std::string. + * + * This is used for cross-process access to strings + * (when the MC is enabled). + */ +XBT_PUBLIC_CLASS string : private string_data { + static const char NUL; +public: + + // Types + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef char& reference; + typedef const char& const_reference; + typedef char* pointer; + typedef const char* const_pointer; + typedef char* iterator; + typedef const char* const_iterator; + + // Dtor + ~string() + { + if (string_data::data != &NUL) + std::free(string_data::data); + } + + // Ctors + string(const char* s, size_t size) + { + if (size == 0) { + string_data::len = 0; + string_data::data = const_cast(&NUL); + } else { + string_data::len = size; + string_data::data = static_cast(std::malloc(string_data::len + 1)); + memcpy(string_data::data, s, string_data::len); + string_data::data[string_data::len] = '\0'; + } + } + string() : string (nullptr, 0) {} + string(const char* s) + : string(s, s == nullptr ? 0 : strlen(s)) + {} + string(string const& s) : string(s.c_str(), s.size()) {} + string(string&& s) + { + string_data::len = s.string_data::len; + string_data::data = s.string_data::data; + s.string_data::len = 0; + s.string_data::data = const_cast(&NUL); + } + string(std::string const& s) : string(s.c_str(), s.size()) {} + + // Assign + void assign(const char* s, size_t size) + { + if (string_data::data != &NUL) + std::free(string_data::data); + if (size == 0) { + string_data::len = 0; + string_data::data = nullptr; + } else { + string_data::len = size; + string_data::data = (char*) std::malloc(string_data::len + 1); + memcpy(string_data::data, s, string_data::len); + string_data::data[string_data::len] = '\0'; + } + } + + // Copy + string& operator=(const char* s) + { + assign(s, s == nullptr ? 0 : std::strlen(s)); + return *this; + } + string& operator=(string& s) + { + assign(s.c_str(), s.size()); + return *this; + } + string& operator=(std::string& s) + { + assign(s.c_str(), s.size()); + return *this; + } + + // Capacity + size_t size() const { return len; } + size_t length() const { return len; } + bool empty() const { return len != 0; } + void shrink_to_fit() {} + + // Alement access + char* data() { return string_data::data; } + const char* data() const { return string_data::data; } + char* c_str() { return string_data::data; } + const char* c_str() const { return string_data::data; }; + reference at(size_type i) + { + if (i >= size()) + throw std::out_of_range("Out of range"); + return data()[i]; + } + const_reference at(size_type i) const + { + if (i >= size()) + throw std::out_of_range("Out of range"); + return data()[i]; + } + reference operator[](size_type i) + { + return data()[i]; + } + const_reference operator[](size_type i) const + { + return data()[i]; + } + // Conversion + operator std::string() const + { + return std::string(this->c_str(), this->size()); + } + + // Iterators + iterator begin() { return data(); } + iterator end() { return data() + size(); } + const_iterator begin() const { return data(); } + const_iterator end() const { return data() + size(); } + const_iterator cbegin() const { return data(); } + const_iterator cend() const { return data() + size(); } + // (Missing, reverse iterators) + + // Operations + void clear() + { + string_data::len = 0; + string_data::data = (char*) &NUL; + } + + // Compare + int compare(string const& that) 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; + } + bool operator==(string const& that) const + { + return this->size() == that.size() + && std::memcmp(this->c_str(), that.c_str(), this->size()) == 0; + } + bool operator!=(string const& that) const + { + return !(*this == that); + } + bool operator<(string const& that) const + { + return compare(that) < 0; + } + bool operator<=(string const& that) const + { + return compare(that) <= 0; + } + bool operator>(string const& that) const + { + return compare(that) > 0; + } + bool operator>=(string const& that) const + { + return compare(that) >= 0; + } + + // Compare with std::string + bool operator==(std::string const& that) const + { + return this->size() == that.size() + && std::memcmp(this->c_str(), that.c_str(), this->size()) == 0; + } + bool operator!=(std::string const& that) const + { + return !(*this == that); + } + bool operator<(std::string const& that) const + { + return compare(that) < 0; + } + bool operator<=(std::string const& that) const + { + return compare(that) <= 0; + } + bool operator>(std::string const& that) const + { + return compare(that) > 0; + } + bool operator>=(std::string const& that) const + { + return compare(that) >= 0; + } +}; + +inline +bool operator==(std::string const& a, string const& b) +{ + return b == a; +} +inline +bool operator!=(std::string const& a, string const& b) +{ + return b != a; +} +inline +bool operator<(std::string const& a, string const& b) +{ + return b > a; +} +inline +bool operator<=(std::string const& a, string const& b) +{ + return b >= a; +} +inline +bool operator>(std::string const& a, string const& b) +{ + return b < a; +} +inline +bool operator>=(std::string const& a, string const& b) +{ + return b <= a; +} + +} +} + +#else + +#include + +namespace simgrid { +namespace xbt { + +typedef std::string string; + +} +} + +#endif + +#endif \ No newline at end of file diff --git a/src/mc/ModelChecker.cpp b/src/mc/ModelChecker.cpp index 6e73a2de40..5c947d25a6 100644 --- a/src/mc/ModelChecker.cpp +++ b/src/mc/ModelChecker.cpp @@ -63,7 +63,6 @@ ModelChecker::~ModelChecker() const char* ModelChecker::get_host_name(const char* hostname) { - // FIXME, simgrid::Host // Lookup the host name in the dictionary (or create it): xbt_dictelm_t elt = xbt_dict_get_elm_or_null(this->hostnames_, hostname); if (!elt) { diff --git a/src/mc/mc_smx.cpp b/src/mc/mc_smx.cpp index 2b051ca43b..f513359bfe 100644 --- a/src/mc/mc_smx.cpp +++ b/src/mc/mc_smx.cpp @@ -7,6 +7,7 @@ #include #include +#include #include "src/simix/smx_private.h" @@ -179,21 +180,33 @@ const char* MC_smx_process_get_host_name(smx_process_t p) simgrid::mc::Process* process = &mc_model_checker->process(); - // FIXME, simgrid::Host - // Currently, smx_host_t = xbt_dictelm_t. - // TODO, add an static_assert on this if switching to C++ - // The host name is host->key and the host->key_len==strlen(host->key). - s_xbt_dictelm_t host_copy; + /* Horrible hack to find the offset of the id in the simgrid::Host. + + Offsetof is not supported for non-POD types but this should + work in pratice for the targets currently supported by the MC + as long as we do not add funny features to the Host class + (such as virtual base). + + We are using a (C++11) unrestricted union in order to avoid + any construction/destruction of the simgrid::Host. + */ + union fake_host { + simgrid::Host host; + fake_host() {} + ~fake_host() {} + }; + fake_host foo; + const size_t offset = (char*) &foo.host.id() - (char*) &foo.host; + + // Read the simgrid::xbt::string in the MCed process: mc_smx_process_info_t info = MC_smx_process_get_info(p); - if (!info->hostname) { - - // Read the hostname from the MCed process: - process->read_bytes(&host_copy, sizeof(host_copy), remote(p->host)); - int len = host_copy.key_len + 1; - char hostname[len]; - process->read_bytes(hostname, len, remote(host_copy.key)); - info->hostname = mc_model_checker->get_host_name(hostname); - } + 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); + 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); return info->hostname; } diff --git a/src/simgrid/host.cpp b/src/simgrid/host.cpp index 1c3cb95a81..d7ec5f14fe 100644 --- a/src/simgrid/host.cpp +++ b/src/simgrid/host.cpp @@ -202,8 +202,8 @@ int sg_host_get_pstate(sg_host_t host) { namespace simgrid { -Host::Host(std::string id) - : id_(std::move(id)) +Host::Host(std::string const& id) + : id_(id) { } diff --git a/src/xbt/string.cpp b/src/xbt/string.cpp new file mode 100644 index 0000000000..4489c33abe --- /dev/null +++ b/src/xbt/string.cpp @@ -0,0 +1,20 @@ +/* Copyright (c) 2015. The SimGrid Team. + * All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + +#include +#include + +namespace simgrid { +namespace xbt { + +#ifdef HAVE_MC + +const char string::NUL = '\0'; + +#endif + +} +} diff --git a/tools/cmake/DefinePackages.cmake b/tools/cmake/DefinePackages.cmake index c5b99221f0..0a8819c175 100644 --- a/tools/cmake/DefinePackages.cmake +++ b/tools/cmake/DefinePackages.cmake @@ -272,6 +272,7 @@ set(XBT_SRC src/xbt/parmap.cpp src/xbt/set.c src/xbt/snprintf.c + src/xbt/string.cpp src/xbt/swag.c src/xbt/xbt_log_appender_file.c src/xbt/xbt_log_layout_format.c @@ -740,6 +741,7 @@ set(headers_to_install include/xbt/config.h include/xbt/cunit.h include/xbt/dict.h + include/xbt/string.hpp include/xbt/dynar.h include/xbt/ex.h include/xbt/fifo.h