CpuConstant res = new CpuConstant(this, name, cpu_properties, core, power_peak[pstate], power_scale);
cpus.add(res);
- Surf.setCpu(name, res);
return res;
}
// ========== SURF CPU ============
XBT_PUBLIC(surf_cpu_t) sg_host_surfcpu(sg_host_t host);
XBT_PUBLIC(void) sg_host_surfcpu_set(sg_host_t host, surf_cpu_t cpu);
-XBT_PUBLIC(void) sg_host_surfcpu_register(sg_host_t host, surf_cpu_t cpu);
XBT_PUBLIC(void) sg_host_surfcpu_destroy(sg_host_t host);
// ========== RoutingEdge ============
#define SIMGRID_XBT_LIB_HPP
#include <cstddef>
-
+#include <limits>
#include <vector>
namespace simgrid {
namespace xbt {
+template<class T, class U> class FacetLevel;
+template<class T> class Facetable;
+
+template<class T, class U>
+class FacetLevel {
+ static const std::size_t INVALID_ID = std::numeric_limits<std::size_t>::max();
+ std::size_t id_;
+ friend class Facetable<T>;
+ constexpr FacetLevel(std::size_t id) : id_(id) {}
+public:
+ constexpr FacetLevel() : id_(INVALID_ID) {}
+ std::size_t id() const { return id_; }
+ bool valid() { return id_ != INVALID_ID; }
+};
+
/** A Facetable is an object that you can extend with external facets.
*
* Facets are similar to the concept of mixins, that is, a set of behavior that is injected into a class without derivation.
* Instead, you should add a new facet to the Host class, that happens to be Facetable.
*
*/
-
template<class T>
class Facetable {
private:
protected:
std::vector<void*> facets_;
public:
- static std::size_t add_level(void (*deleter)(void*))
+ static size_t add_level(void (*deleter)(void*))
{
std::size_t res = deleters_.size();
deleters_.push_back(deleter);
return res;
}
+ template<class U>
+ static FacetLevel<T,U> add_level(void (*deleter)(void*))
+ {
+ return FacetLevel<T,U>(add_level(deleter));
+ }
template<class U> static
- std::size_t add_level()
+ FacetLevel<T,U> add_level()
{
- return add_level([](void* p){ delete (U*)p; });
+ return add_level([](void* p){ delete static_cast<U*>(p); });
}
Facetable() : facets_(deleters_.size(), nullptr) {}
~Facetable()
deleters_[i](facets_[i]);
}
- // TODO, make type-safe versions of this
+ // Type-unsafe versions of the facet access methods:
void* facet(std::size_t level)
{
if (level >= facets_.size())
if (use_dtor && old_value != nullptr && deleters_[level])
deleters_[level](old_value);
}
+
+ // Type safe versions of the facet access methods:
+ template<class U>
+ U* facet(FacetLevel<T,U> level)
+ {
+ return static_cast<U*>(facet(level.id()));
+ }
+ template<class U>
+ void set_facet(FacetLevel<T,U> level, U* value, bool use_dtor = true)
+ {
+ set_facet(level.id(), value, use_dtor);
+ }
+
+ // Convnience facet access when the type has a associated LEVEL:
+ template<class U> U* facet() { return facet<U>(U::LEVEL); }
+ template<class U> void set_facet(U* p) { set_facet<U>(U::LEVEL, p); }
};
template<class T>
/** A std::string with well-known representation
*
- * This is a (incomplete) drop-in replacement for std::string.
+ * This is a (incomplete) drop-in replacement for `std::string`.
+ * It has a fixed POD representation (`simgrid::xbt::string_data`)
+ * which can be used to easily read the string content from another
+ * process.
*
- * This is used for cross-process access to strings
- * (when the MC is enabled).
+ * The internal representation of a `std::string` is private.
+ * We could add some code to read this for a given implementation.
+ * However, even if we focus on GNU libstdc++ with Itanium ABI
+ * GNU libstdc++ currently has two different ABIs
+ *
+ * * the pre-C++11 is a pointer to a ref-counted
+ * string-representation (with support for COW);
+ *
+ * * the [C++11-conforming implementation](https://gcc.gnu.org/gcc-5/changes.html)
+ * does not use refcouting/COW but has a small string optimization.
*/
XBT_PUBLIC_CLASS string : private string_data {
static const char NUL;
}
void setCpu(char *name, simgrid::surf::Cpu *cpu) {
- sg_host_surfcpu_set(sg_host_by_name(name), cpu);
+ // No-op here for compatibility with previous versions
}
LinkDynar getRoute(char *srcName, char *dstName) {
xbt_dict_cursor_t cursor = NULL;
simgrid_Host* host = NULL;
xbt_dict_foreach(host_list, cursor, name, host){
- surf_Host* surf_host = (surf_Host*) sg_host_get_facet(host, SURF_HOST_LEVEL);
+ surf_Host* surf_host = (surf_Host*) surf_host_resource_priv(host);
if (surf_host != NULL)
__SD_workstation_create(surf_host, NULL);
}
int SD_HOST_LEVEL;
int SIMIX_HOST_LEVEL;
int ROUTING_HOST_LEVEL;
-int SURF_CPU_LEVEL;
int USER_HOST_LEVEL;
#include "src/msg/msg_private.h" // MSG_host_priv_free. FIXME: killme
});
SD_HOST_LEVEL = simgrid::Host::add_level(__SD_workstation_destroy);
SIMIX_HOST_LEVEL = simgrid::Host::add_level(SIMIX_host_destroy);
- SURF_CPU_LEVEL = simgrid::Host::add_level(surf_cpu_free);
+ simgrid::surf::Cpu::init();
ROUTING_HOST_LEVEL = simgrid::Host::add_level(routing_asr_host_free);
USER_HOST_LEVEL = simgrid::Host::add_level(NULL);
}
// ========== SURF CPU ============
surf_cpu_t sg_host_surfcpu(sg_host_t host) {
- return (surf_cpu_t) host->facet(SURF_CPU_LEVEL);
+ return host->facet<simgrid::surf::Cpu>();
}
void sg_host_surfcpu_set(sg_host_t host, surf_cpu_t cpu) {
- host->set_facet(SURF_CPU_LEVEL, cpu);
-}
-void sg_host_surfcpu_register(sg_host_t host, surf_cpu_t cpu)
-{
- surf_callback_emit(simgrid::surf::cpuCreatedCallbacks, cpu);
- surf_callback_emit(simgrid::surf::cpuStateChangedCallbacks, cpu, SURF_RESOURCE_ON, cpu->getState());
- sg_host_surfcpu_set(host, cpu);
+ host->set_facet(simgrid::surf::Cpu::LEVEL, cpu);
}
void sg_host_surfcpu_destroy(sg_host_t host) {
- host->set_facet(SURF_CPU_LEVEL, nullptr);
+ host->set_facet<simgrid::surf::Cpu>(nullptr);
}
// ========== RoutingEdge ============
surf_RoutingEdge *sg_host_edge(sg_host_t host) {
tmgr_trace_t state_trace,
xbt_dict_t cpu_properties)
{
- Cpu *cpu = NULL;
- sg_host_t host = sg_host_by_name(name);
xbt_assert(xbt_dynar_getfirst_as(speedPeak, double) > 0.0,
"Speed has to be >0.0. Did you forget to specify the mandatory power attribute?");
xbt_assert(core > 0, "Invalid number of cores %d. Must be larger than 0", core);
-
- cpu = new CpuCas01(this, name, speedPeak, pstate, speedScale, speedTrace, core, state_initial, state_trace, cpu_properties);
- sg_host_surfcpu_register(host, cpu);
+ Cpu *cpu = new CpuCas01(this, name, speedPeak, pstate, speedScale, speedTrace, core, state_initial, state_trace, cpu_properties);
return cpu;
}
namespace simgrid {
namespace surf {
+simgrid::xbt::FacetLevel<simgrid::Host, Cpu> Cpu::LEVEL;
+
+void Cpu::init()
+{
+ if (!LEVEL.valid())
+ LEVEL = simgrid::Host::add_level<simgrid::surf::Cpu>();
+}
+
/*************
* Callbacks *
*************/
surf_callback_emit(cpuStateChangedCallbacks, this, old, state);
}
+void Cpu::plug(simgrid::Host* host)
+{
+ if (this->m_host != nullptr)
+ xbt_die("Aleady plugged into host %s", host->id().c_str());
+ host->set_facet(this);
+ this->m_host = host;
+ simgrid::surf::cpuCreatedCallbacks(this);
+ simgrid::surf::cpuStateChangedCallbacks(this,
+ SURF_RESOURCE_ON, this->getState());
+}
+
/**********
* Action *
**********/
*/
XBT_PUBLIC_CLASS Cpu : public simgrid::surf::Resource {
public:
+ static simgrid::xbt::FacetLevel<simgrid::Host, Cpu> LEVEL;
+ static void init();
Cpu();
/**
virtual int getPstate()=0;
void setState(e_surf_resource_state_t state);
+ void plug(simgrid::Host* host);
void addTraces(void);
int m_core = 1; /* Amount of cores */
double m_speedPeak; /*< CPU speed peak, ie max value */
double m_speedScale; /*< Percentage of CPU available according to the trace, in [O,1] */
+ simgrid::Host* m_host = nullptr;
/* Note (hypervisor): */
lmm_constraint_t *p_constraintCore=NULL;
void **p_constraintCoreId=NULL;
+
};
/**********
xbt_dict_t cpuProperties)
{
xbt_assert(core==1,"Multi-core not handled with this model yet");
- sg_host_t host = sg_host_by_name(name);
xbt_assert(xbt_dynar_getfirst_as(speedPeak, double) > 0.0,
"Speed has to be >0.0. Did you forget to specify the mandatory speed attribute?");
CpuTi *cpu = new CpuTi(this, name, speedPeak, pstate, speedScale, speedTrace,
core, stateInitial, stateTrace, cpuProperties);
- sg_host_surfcpu_register(host, cpu);
return cpu;
}
}
#endif /* SURF_MODEL_CPUTI_H_ */
-
Host *host = new simgrid::surf::HostCLM03(surf_host_model, name, NULL,
(xbt_dynar_t)xbt_lib_get_or_null(storage_lib, name, ROUTING_STORAGE_HOST_LEVEL),
netElm, cpu);
- surf_callback_emit(hostCreatedCallbacks, host);
XBT_DEBUG("Create host %s with %ld mounted disks", name, xbt_dynar_length(host->p_storage));
- simgrid::Host::by_name_or_null(name)->set_facet(SURF_HOST_LEVEL, host);
return host;
}
#include "host_interface.hpp"
+#include <simgrid/Host.hpp>
+
#include "src/simix/smx_private.h"
#include "cpu_cas01.hpp"
#include "simgrid/sg_config.h"
namespace simgrid {
namespace surf {
-
+
+simgrid::xbt::FacetLevel<simgrid::Host, Host> Host::LEVEL;
+
surf_callback(void, simgrid::surf::Host*) hostCreatedCallbacks;
surf_callback(void, simgrid::surf::Host*) hostDestructedCallbacks;
surf_callback(void, simgrid::surf::Host*, e_surf_resource_state_t, e_surf_resource_state_t) hostStateChangedCallbacks;
/************
* Resource *
************/
+
+void Host::init()
+{
+ if (!LEVEL.valid()) {
+ LEVEL = simgrid::Host::add_level<simgrid::surf::Host>();
+ SURF_HOST_LEVEL = LEVEL.id();
+ }
+}
+
Host::Host(simgrid::surf::Model *model, const char *name, xbt_dict_t props,
xbt_dynar_t storage, RoutingEdge *netElm, Cpu *cpu)
: Resource(model, name, props)
surf_callback_emit(hostDestructedCallbacks, this);
}
+void Host::attach(simgrid::Host* host)
+{
+ if (p_host != nullptr)
+ xbt_die("Already attached to host %s", host->id().c_str());
+ host->set_facet(this);
+ p_host = host;
+ surf_callback_emit(hostCreatedCallbacks, this);
+}
+
void Host::setState(e_surf_resource_state_t state){
e_surf_resource_state_t old = Resource::getState();
Resource::setState(state);
*/
class Host : public simgrid::surf::Resource {
public:
+ static simgrid::xbt::FacetLevel<simgrid::Host, Host> LEVEL;
+ static void init();
/**
* @brief Host constructor
*
/** @brief Host destructor */
~Host();
+ void attach(simgrid::Host* host);
void setState(e_surf_resource_state_t state);
/**
xbt_dynar_t p_storage;
RoutingEdge *p_netElm;
Cpu *p_cpu;
+ simgrid::Host* p_host = nullptr;
/** @brief Get the list of virtual machines on the current Host */
xbt_dynar_t getVms();
Host *HostL07Model::createHost(const char *name,RoutingEdge *netElm, Cpu *cpu)
{
- HostL07 *host = new HostL07(this, name, NULL, netElm, cpu);
-
- surf_callback_emit(hostCreatedCallbacks, host);
- simgrid::Host::by_name_or_create(name)->set_facet(SURF_HOST_LEVEL, host);
-
- return host;
+ return new HostL07(this, name, NULL, netElm, cpu);
}
Action *NetworkL07Model::communicate(RoutingEdge *src, RoutingEdge *dst,
xbt_dict_t cpu_properties)
{
double power_initial = xbt_dynar_get_as(powerPeak, pstate, double);
- sg_host_t sg_host = sg_host_by_name(name);
-
CpuL07 *cpu = new CpuL07(this, name, cpu_properties,
power_initial, power_scale, power_trace,
core, state_initial, state_trace);
- sg_host_surfcpu_register(sg_host, cpu);
return cpu;
}
if (current_routing)
net = routing_add_host(current_routing, host);
+ sg_host_t h = simgrid::Host::by_name_or_create(host->id);
simgrid::surf::Cpu *cpu = surf_cpu_model_pm->createCpu(
host->id,
host->speed_peak,
host->initial_state,
host->state_trace,
host->properties);
- surf_host_model->createHost(host->id, net, cpu);
-
+ cpu->plug(h);
+ surf_host_model->createHost(host->id, net, cpu)->attach(h);
if (TRACE_is_enabled() && TRACE_needs_platform())
sg_instr_new_host(host);
}
surf_host_model_t surf_host_get_model(sg_host_t host)
{
simgrid::surf::Host* surf_host =
- (simgrid::surf::Host*) host->facet(SURF_HOST_LEVEL);
+ (simgrid::surf::Host*) host->facet<simgrid::surf::Host>();
return (surf_host_model_t) surf_host->getModel();
}
sg_host_surfcpu_destroy(resource);
sg_host_edge_destroy(resource,1);
// TODO, use backlink from simgrid::surf::Host to simgrid::Host
- simgrid::Host::by_name_or_null(name)->set_facet(SURF_HOST_LEVEL, nullptr);
+ simgrid::Host::by_name_or_null(name)->set_facet((simgrid::surf::Host*)nullptr);
/* TODO: comment out when VM storage is implemented. */
// host->set_facet(SURF_STORAGE_LEVEL, nullptr);
//xbt_dict_free(&elm); FIXME: leaking in some case? That's a sometimes double-free with AsCluster::~AsCluster
}
-static XBT_INLINE void surf_host_free(void *r)
-{
- delete static_cast<simgrid::surf::Host*>(r);
-}
-
static XBT_INLINE void surf_storage_free(void *r)
{
delete static_cast<simgrid::surf::Storage*>(r);
ROUTING_PROP_ASR_LEVEL = xbt_lib_add_level(as_router_lib,routing_asr_prop_free);
XBT_DEBUG("Add SURF levels");
- SURF_HOST_LEVEL = simgrid::Host::add_level(surf_host_free);
+ simgrid::surf::Host::init();
SURF_STORAGE_LEVEL = xbt_lib_add_level(storage_lib,surf_storage_free);
xbt_init(argc, argv);
: Host(model, name, props, NULL, netElm, cpu)
{
VMModel::ws_vms.push_back(*this);
- simgrid::Host::by_name_or_create(name)->set_facet(SURF_HOST_LEVEL, this);
+ simgrid::Host::by_name_or_create(name)->set_facet<simgrid::surf::Host>(this);
}
/*
#include <algorithm>
+#include <simgrid/host.h>
+
#include "cpu_cas01.hpp"
#include "vm_hl13.hpp"
* is still used by the physical machine. */
sg_host_t sg_sub_ws = sg_host_by_name_or_create(sub_ws->getName());
p_netElm = new RoutingEdgeWrapper(sg_host_edge(sg_sub_ws));
- sg_host_edge_set(sg_host_by_name_or_create(name), p_netElm);
+ sg_host_t host = sg_host_by_name_or_create(name);
+ sg_host_edge_set(host, p_netElm);
p_subWs = sub_ws;
p_currentState = SURF_VM_STATE_CREATED;
SURF_RESOURCE_ON, // host->initial_state,
NULL, // host->state_trace,
NULL); // host->properties,
+ p_cpu->plug(host);
/* We create cpu_action corresponding to a VM process on the host operating system. */
/* FIXME: TODO: we have to periodically input GUESTOS_NOISE to the system? how ? */