message("-- Support for thread context factory")
endif()
+# Temp hack to disable context:
+# set(CONTEXT_THREADS 0)
+set(CONTEXT_UCONTEXT 0)
+set(HAVE_RAWCTX 0)
+
###############
## GIT version check
##
#include "simgrid/datatypes.h"
#include "simgrid/host.h"
+
+#ifdef __cplusplus
+
+namespace simgrid {
+namespace simix {
+ class Context;
+ class ContextFactory;
+}
+}
+
+typedef simgrid::simix::Context *smx_context_t;
+
+#else
+
+typedef struct s_smx_context *smx_context_t;
+
+#endif
+
+
+
SG_BEGIN_DECL()
/**************************** Scalar Values **********************************/
XBT_PUBLIC(void*) SIMIX_comm_get_src_data(smx_synchro_t synchro);
XBT_PUBLIC(void*) SIMIX_comm_get_dst_data(smx_synchro_t synchro);
-/******************************** Context *************************************/
-typedef struct s_smx_context *smx_context_t;
-typedef struct s_smx_context_factory *smx_context_factory_t;
-
/* Process creation/destruction callbacks */
typedef void (*void_pfn_smxprocess_t) (smx_process_t);
/* for auto-restart function */
typedef void (*void_pfn_sghost_t) (sg_host_t);
-/* The following function pointer types describe the interface that any context
- factory should implement */
-
-
-typedef smx_context_t (*smx_pfn_context_factory_create_context_t)(
- xbt_main_func_t, int, char **, void_pfn_smxprocess_t, smx_process_t process);
-typedef int (*smx_pfn_context_factory_finalize_t) (smx_context_factory_t*);
-typedef void (*smx_pfn_context_free_t) (smx_context_t);
-typedef void (*smx_pfn_context_start_t) (smx_context_t);
-typedef void (*smx_pfn_context_stop_t) (smx_context_t);
-typedef void (*smx_pfn_context_suspend_t) (smx_context_t context);
-typedef void (*smx_pfn_context_runall_t) (void);
-typedef smx_context_t (*smx_pfn_context_self_t) (void);
-typedef smx_process_t (*smx_pfn_context_get_process_t) (smx_context_t context);
-
-/* interface of the context factories */
-typedef struct s_smx_context_factory {
- const char *name;
- smx_pfn_context_factory_create_context_t create_context;
- smx_pfn_context_factory_finalize_t finalize;
- smx_pfn_context_free_t free;
- smx_pfn_context_stop_t stop;
- smx_pfn_context_suspend_t suspend;
- smx_pfn_context_runall_t runall;
- smx_pfn_context_self_t self;
- smx_pfn_context_get_process_t get_process;
-} s_smx_context_factory_t;
-
-/* Hack: let msg load directly the right factory */
-typedef void (*smx_ctx_factory_initializer_t)(smx_context_factory_t*);
-XBT_PUBLIC_DATA(smx_ctx_factory_initializer_t) smx_factory_initializer_to_use;
extern char* smx_context_factory_name;
extern int smx_context_stack_size;
extern int smx_context_stack_size_was_set;
extern int smx_context_guard_size;
extern int smx_context_guard_size_was_set;
-/* *********************** */
-/* Context type definition */
-/* *********************** */
-/* the following function pointers types describe the interface that all context
- concepts must implement */
-/* each context type derive from this structure, so they must contain this structure
- * at their beginning -- OOP in C :/ */
-typedef struct s_smx_context {
- s_xbt_swag_hookup_t hookup;
- xbt_main_func_t code;
- void_pfn_smxprocess_t cleanup_func;
- smx_process_t process;
- char **argv;
- int argc;
- unsigned iwannadie:1;
-} s_smx_ctx_base_t;
-
-/* methods of this class */
-XBT_PUBLIC(void) smx_ctx_base_factory_init(smx_context_factory_t *factory);
-XBT_PUBLIC(int) smx_ctx_base_factory_finalize(smx_context_factory_t *factory);
-
-XBT_PUBLIC(smx_context_t)
-smx_ctx_base_factory_create_context_sized(size_t size, xbt_main_func_t code,
- int argc, char **argv,
- void_pfn_smxprocess_t cleanup,
- smx_process_t process);
-XBT_PUBLIC(void) smx_ctx_base_free(smx_context_t context);
-XBT_PUBLIC(void) smx_ctx_base_stop(smx_context_t context);
-XBT_PUBLIC(smx_context_t) smx_ctx_base_self(void);
-XBT_PUBLIC(smx_process_t) smx_ctx_base_get_process(smx_context_t context);
-
XBT_PUBLIC(xbt_dynar_t) SIMIX_process_get_runnable(void);
XBT_PUBLIC(smx_process_t) SIMIX_process_from_PID(int PID);
XBT_PUBLIC(xbt_dynar_t) SIMIX_processes_as_dynar(void);
--- /dev/null
+/* Copyright (c) 2007-2010, 2012-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 SIMGRID_SIMIX_HPP
+#define SIMGRID_SIMIX_HPP
+
+#include <utility>
+#include <memory>
+
+#include <xbt/function_types.h>
+#include <simgrid/simix.h>
+
+namespace simgrid {
+namespace simix {
+
+class Context;
+class ContextFactory;
+
+class ContextFactory {
+private:
+ std::string name_;
+public:
+
+ ContextFactory(std::string name) : name_(std::move(name)) {}
+ virtual ~ContextFactory();
+ virtual Context* create_context(
+ xbt_main_func_t, int, char **, void_pfn_smxprocess_t,
+ smx_process_t process
+ ) = 0;
+ virtual void run_all() = 0;
+ virtual Context* self();
+ std::string const& name() const
+ {
+ return name_;
+ }
+private:
+ void declare_context(void* T, std::size_t size);
+public:
+ template<class T, class... Args>
+ T* new_context(Args&&... args)
+ {
+ T* context = new T(std::forward<Args>(args)...);
+ this->declare_context(context, sizeof(T));
+ return context;
+ }
+};
+
+class Context {
+private:
+ xbt_main_func_t code_ = nullptr;
+ int argc_ = 0;
+ char **argv_ = nullptr;
+ void_pfn_smxprocess_t cleanup_func_ = nullptr;
+ smx_process_t process_ = nullptr;
+public:
+ bool iwannadie;
+public:
+ Context(xbt_main_func_t code,
+ int argc, char **argv,
+ void_pfn_smxprocess_t cleanup_func,
+ smx_process_t process);
+ int operator()()
+ {
+ return code_(argc_, argv_);
+ }
+ smx_process_t process()
+ {
+ return this->process_;
+ }
+
+ // Virtual methods
+ virtual ~Context();
+ virtual void stop();
+ virtual void suspend() = 0;
+};
+
+}
+}
+
+#endif
\ No newline at end of file
--- /dev/null
+/* 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. */
+
+/** @file BoostContext.cpp Userspace context switching implementation based on Boost.Context */
+
+#include <cstdint>
+
+#include <boost/context/all.hpp>
+
+#include <xbt/log.h>
+#include <xbt/xbt_os_thread.h>
+
+#include "smx_private.h"
+#include "smx_private.hpp"
+#include "src/internal_config.h"
+#include "src/simix/BoostContext.hpp"
+
+XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix_context);
+
+namespace simgrid {
+namespace simix {
+
+class BoostSerialContext : public BoostContext {
+public:
+ BoostSerialContext(xbt_main_func_t code,
+ int argc, char **argv,
+ void_pfn_smxprocess_t cleanup_func,
+ smx_process_t process)
+ : BoostContext(code, argc, argv, cleanup_func, process) {}
+ void stop() override;
+ void suspend() override;
+ void resume();
+};
+
+#ifdef CONTEXT_THREADS
+class BoostParallelContext : public BoostContext {
+public:
+ BoostParallelContext(xbt_main_func_t code,
+ int argc, char **argv,
+ void_pfn_smxprocess_t cleanup_func,
+ smx_process_t process)
+ : BoostContext(code, argc, argv, cleanup_func, process) {}
+ void stop() override;
+ void suspend() override;
+ void resume();
+};
+#endif
+
+// BoostContextFactory
+
+bool BoostContext::parallel_ = false;
+xbt_parmap_t BoostContext::parmap_ = nullptr;
+unsigned long BoostContext::threads_working_ = 0;
+xbt_os_thread_key_t BoostContext::worker_id_key_;
+unsigned long BoostContext::process_index_ = 0;
+BoostContext* BoostContext::maestro_context_ = nullptr;
+std::vector<BoostContext*> BoostContext::workers_context_;
+
+BoostContextFactory::BoostContextFactory()
+ : ContextFactory("BoostContextFactory")
+{
+ BoostContext::parallel_ = SIMIX_context_is_parallel();
+ if (BoostContext::parallel_) {
+#ifndef CONTEXT_THREADS
+ xbt_die("No thread support for parallel context execution");
+#else
+ int nthreads = SIMIX_context_get_nthreads();
+ BoostContext::parmap_ = xbt_parmap_new(nthreads, SIMIX_context_get_parallel_mode());
+ BoostContext::workers_context_.clear();
+ BoostContext::workers_context_.resize(nthreads, nullptr);
+ BoostContext::maestro_context_ = nullptr;
+ xbt_os_thread_key_create(&BoostContext::worker_id_key_);
+#endif
+ }
+}
+
+BoostContextFactory::~BoostContextFactory()
+{
+#ifdef CONTEXT_THREADS
+ if (BoostContext::parmap_) {
+ xbt_parmap_destroy(BoostContext::parmap_);
+ BoostContext::parmap_ = nullptr;
+ }
+ BoostContext::workers_context_.clear();
+#endif
+}
+
+smx_context_t BoostContextFactory::create_context(
+ xbt_main_func_t code, int argc, char ** argv,
+ void_pfn_smxprocess_t cleanup_func, smx_process_t process)
+{
+ BoostContext* context = nullptr;
+ if (BoostContext::parallel_)
+#ifdef CONTEXT_THREADS
+ context = this->new_context<BoostParallelContext>(
+ code, argc, argv, cleanup_func, process);
+#else
+ xbt_die("No support for parallel execution");
+#endif
+ else
+ context = this->new_context<BoostSerialContext>(
+ code, argc, argv, cleanup_func, process);
+ return context;
+}
+
+void BoostContextFactory::run_all()
+{
+#ifdef CONTEXT_THREADS
+ if (BoostContext::parallel_) {
+ BoostContext::threads_working_ = 0;
+ xbt_parmap_apply(BoostContext::parmap_,
+ [](void* arg) {
+ smx_process_t process = static_cast<smx_process_t>(arg);
+ BoostContext* context = static_cast<BoostContext*>(process->context);
+ return context->resume();
+ },
+ simix_global->process_to_run);
+ } else
+#endif
+ {
+ smx_process_t first_process =
+ xbt_dynar_get_as(simix_global->process_to_run, 0, smx_process_t);
+ BoostContext::process_index_ = 1;
+ /* execute the first process */
+ static_cast<BoostContext*>(first_process->context)->resume();
+ }
+}
+
+
+// BoostContext
+
+static void smx_ctx_boost_wrapper(std::intptr_t arg)
+{
+ BoostContext* context = (BoostContext*) arg;
+ (*context)();
+ context->stop();
+}
+
+BoostContext::BoostContext(xbt_main_func_t code,
+ int argc, char **argv,
+ void_pfn_smxprocess_t cleanup_func,
+ smx_process_t process)
+ : Context(code, argc, argv, cleanup_func, process)
+{
+
+ /* if the user provided a function for the process then use it,
+ otherwise it is the context for maestro */
+ if (code) {
+ this->stack_ = SIMIX_context_stack_new();
+ // We need to pass the bottom of the stack to make_fcontext,
+ // depending on the stack direction it may be the lower or higher address:
+ #if PTH_STACKGROWTH == -1
+ void* stack = (char*) this->stack_ + smx_context_usable_stack_size - 1;
+ #else
+ void* stack = this->stack_;
+ #endif
+ this->fc_ = boost::context::make_fcontext(
+ stack,
+ smx_context_usable_stack_size,
+ smx_ctx_boost_wrapper);
+ } else {
+ #if HAVE_BOOST_CONTEXT == 1
+ this->fc_ = new boost::context::fcontext_t();
+ #endif
+ if (BoostContext::maestro_context_ == nullptr)
+ BoostContext::maestro_context_ = this;
+ }
+}
+
+BoostContext::~BoostContext()
+{
+#if HAVE_BOOST_CONTEXT == 1
+ if (!this->stack_)
+ delete this->fc_;
+#endif
+ if (this == maestro_context_)
+ maestro_context_ = nullptr;
+ SIMIX_context_stack_delete(this->stack_);
+}
+
+// BoostSerialContext
+
+void BoostContext::resume()
+{
+ SIMIX_context_set_current(this);
+#if HAVE_BOOST_CONTEXT == 1
+ boost::context::jump_fcontext(
+ maestro_context_->fc_, this->fc_,
+ (intptr_t) this);
+#else
+ boost::context::jump_fcontext(
+ &boost_maestro_context_->fc_, this->fc_,
+ (intptr_t) this);
+#endif
+}
+
+void BoostSerialContext::suspend()
+{
+ /* determine the next context */
+ BoostSerialContext* next_context = nullptr;
+ unsigned long int i = process_index_++;
+
+ if (i < xbt_dynar_length(simix_global->process_to_run)) {
+ /* execute the next process */
+ XBT_DEBUG("Run next process");
+ next_context = static_cast<BoostSerialContext*>(xbt_dynar_get_as(
+ simix_global->process_to_run, i, smx_process_t)->context);
+ }
+ else {
+ /* all processes were run, return to maestro */
+ XBT_DEBUG("No more process to run");
+ next_context = static_cast<BoostSerialContext*>(
+ maestro_context_);
+ }
+ SIMIX_context_set_current((smx_context_t) next_context);
+ #if HAVE_BOOST_CONTEXT == 1
+ boost::context::jump_fcontext(
+ this->fc_, next_context->fc_, (intptr_t) next_context);
+ #else
+ boost::context::jump_fcontext(
+ &this->fc_, next_context->fc_, (intptr_t) next_context);
+ #endif
+}
+
+void BoostSerialContext::stop()
+{
+ BoostContext::stop();
+ this->suspend();
+}
+
+// BoostParallelContext
+
+#ifdef CONTEXT_THREADS
+
+void BoostParallelContext::suspend()
+{
+ smx_process_t next_work = (smx_process_t) xbt_parmap_next(parmap_);
+ BoostParallelContext* next_context = nullptr;
+
+ if (next_work != nullptr) {
+ XBT_DEBUG("Run next process");
+ next_context = static_cast<BoostParallelContext*>(next_work->context);
+ }
+ else {
+ XBT_DEBUG("No more processes to run");
+ unsigned long worker_id =
+ (unsigned long) xbt_os_thread_get_specific(worker_id_key_);
+ next_context = static_cast<BoostParallelContext*>(
+ workers_context_[worker_id]);
+ }
+
+ SIMIX_context_set_current((smx_context_t) next_context);
+#if HAVE_BOOST_CONTEXT == 1
+ boost::context::jump_fcontext(
+ this->fc_, next_context->fc_, (intptr_t)next_context);
+#else
+ boost::context::jump_fcontext(
+ &this->fc_, next_context->fc_, (intptr_t)next_context);
+#endif
+}
+
+void BoostParallelContext::stop()
+{
+ BoostContext::stop();
+ this->suspend();
+}
+
+void BoostParallelContext::resume()
+{
+ unsigned long worker_id = __sync_fetch_and_add(&threads_working_, 1);
+ xbt_os_thread_set_specific(worker_id_key_, (void*) worker_id);
+
+ BoostParallelContext* worker_context =
+ static_cast<BoostParallelContext*>(SIMIX_context_self());
+ workers_context_[worker_id] = worker_context;
+
+ SIMIX_context_set_current(this);
+#if HAVE_BOOST_CONTEXT == 1
+ boost::context::jump_fcontext(
+ worker_context->fc_, this->fc_, (intptr_t) this);
+#else
+ boost::context::jump_fcontext(
+ &worker_context->fc_, this->fc_, (intptr_t) this);
+#endif
+}
+
+#endif
+
+XBT_PRIVATE ContextFactory* boost_factory()
+{
+ return new BoostContextFactory();
+}
+
+}
+}
--- /dev/null
+/* 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. */
+
+/** @file BoostContext.hpp
+ Userspace context switching implementation based on Boost.Context */
+
+#ifndef SIMGRID_SIMIX_BOOST_CONTEXT_HPP
+#define SIMGRID_SIMIX_BOOST_CONTEXT_HPP
+
+#include <vector>
+
+#include <xbt/parmap.h>
+
+#include <simgrid/simix.hpp>
+
+
+namespace simgrid {
+namespace simix {
+
+class BoostContext;
+class BoostSerialContext;
+class BoostParallelContext;
+class BoostContextFactory;
+
+class BoostContext : public Context {
+protected: // static
+ static bool parallel_;
+ static xbt_parmap_t parmap_;
+ static std::vector<BoostContext*> workers_context_;
+ static unsigned long threads_working_;
+ static xbt_os_thread_key_t worker_id_key_;
+ static unsigned long process_index_;
+ static BoostContext* maestro_context_;
+protected:
+#if HAVE_BOOST_CONTEXT == 1
+ boost::context::fcontext_t* fc_ = nullptr;
+#else
+ boost::context::fcontext_t fc_;
+#endif
+ void* stack_ = nullptr;
+public:
+ friend BoostContextFactory;
+ BoostContext(xbt_main_func_t code,
+ int argc, char **argv,
+ void_pfn_smxprocess_t cleanup_func,
+ smx_process_t process);
+ ~BoostContext();
+ void resume();
+};
+
+class BoostContextFactory : public ContextFactory {
+public:
+ friend BoostContext;
+ friend BoostSerialContext;
+ friend BoostParallelContext;
+
+ BoostContextFactory();
+ virtual ~BoostContextFactory();
+ virtual Context* create_context(
+ xbt_main_func_t, int, char **, void_pfn_smxprocess_t,
+ smx_process_t process
+ ) override;
+ void run_all() override;
+};
+
+}
+}
+
+#endif
--- /dev/null
+/* Copyright (c) 2007-2010, 2012-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 <simgrid/simix.hpp>
+
+#include "mc/mc.h"
+
+#include <src/simix/smx_private.h>
+
+namespace simgrid {
+namespace simix {
+
+ContextFactoryInitializer factory_initializer = nullptr;
+
+ContextFactory::~ContextFactory() {}
+
+Context* ContextFactory::self()
+{
+ return SIMIX_context_get_current();
+}
+
+void ContextFactory::declare_context(void* context, std::size_t size)
+{
+#ifdef HAVE_MC
+ /* Store the address of the stack in heap to compare it apart of heap comparison */
+ if(MC_is_active())
+ MC_ignore_heap(context, size);
+#endif
+}
+
+Context::Context(xbt_main_func_t code,
+ int argc, char **argv,
+ void_pfn_smxprocess_t cleanup_func,
+ smx_process_t process)
+ : process_(process), iwannadie(false)
+{
+ /* If the user provided a function for the process then use it.
+ Otherwise, it is the context for maestro and we should set it as the
+ current context */
+ if (code) {
+ this->cleanup_func_ = cleanup_func;
+ this->argc_ = argc;
+ this->argv_ = argv;
+ this->code_ = code;
+ } else {
+ SIMIX_context_set_current(this);
+ }
+}
+
+Context::~Context()
+{
+ if (this->argv_) {
+ for (int i = 0; i < this->argc_; i++)
+ free(this->argv_[i]);
+ free(this->argv_);
+ }
+}
+
+void Context::stop()
+{
+ if (this->cleanup_func_)
+ this->cleanup_func_(this->process_);
+ this->process_->suspended = 0;
+
+ this->iwannadie = false;
+ simcall_process_cleanup(this->process_);
+ this->iwannadie = true;
+}
+
+}
+}
\ No newline at end of file
#include "xbt/swag.h"
#include "xbt/xbt_os_thread.h"
#include "smx_private.h"
+#include "smx_private.hpp"
#include "simgrid/sg_config.h"
#include "src/internal_config.h"
#include "simgrid/modelchecker.h"
"Context switching mechanism");
char* smx_context_factory_name = NULL; /* factory name specified by --cfg=contexts/factory:value */
-smx_ctx_factory_initializer_t smx_factory_initializer_to_use = NULL;
int smx_context_stack_size;
int smx_context_stack_size_was_set = 0;
int smx_context_guard_size;
#endif
if (!simix_global->context_factory) {
/* select the context factory to use to create the contexts */
- if (smx_factory_initializer_to_use) {
- smx_factory_initializer_to_use(&simix_global->context_factory);
- }
+ if (simgrid::simix::factory_initializer)
+ simix_global->context_factory = simgrid::simix::factory_initializer();
else { /* use the factory specified by --cfg=contexts/factory:value */
-
-
- if (!strcmp(smx_context_factory_name, "thread")) {
- /* use os threads (either pthreads or windows ones) */
- SIMIX_ctx_thread_factory_init(&simix_global->context_factory);
- }
+#if defined(CONTEXT_THREADS) && 0
+ if (!strcmp(smx_context_factory_name, "thread"))
+ simix_global->context_factory = simgrid::simix::thread_factory();
+#else
+ if (0);
+#endif
#ifdef CONTEXT_UCONTEXT
- else if (!strcmp(smx_context_factory_name, "ucontext")) {
- /* use ucontext */
- SIMIX_ctx_sysv_factory_init(&simix_global->context_factory);
- }
+ else if (!strcmp(smx_context_factory_name, "ucontext"))
+ simix_global->context_factory = simgrid::simix::sysv_factory();
#endif
#ifdef HAVE_RAWCTX
- else if (!strcmp(smx_context_factory_name, "raw")) {
- /* use raw contexts */
- SIMIX_ctx_raw_factory_init(&simix_global->context_factory);
- }
+ else if (!strcmp(smx_context_factory_name, "raw"))
+ simix_global->context_factory = simgrid::simix::raw_factory();
#endif
#ifdef HAVE_BOOST_CONTEXT
- else if (!strcmp(smx_context_factory_name, "boost")) {
- /* use Boost.Context */
- SIMIX_ctx_boost_factory_init(&simix_global->context_factory);
- }
+ else if (!strcmp(smx_context_factory_name, "boost"))
+ simix_global->context_factory = simgrid::simix::boost_factory();
#endif
else {
XBT_ERROR("Invalid context factory specified. Valid factories on this machine:");
*/
void SIMIX_context_mod_exit(void)
{
- if (simix_global->context_factory) {
- smx_pfn_context_factory_finalize_t finalize_factory;
-
- /* finalize the context factory */
- finalize_factory = simix_global->context_factory->finalize;
- finalize_factory(&simix_global->context_factory);
- }
+ delete simix_global->context_factory;
+ simix_global->context_factory = nullptr;
xbt_dict_remove((xbt_dict_t) _sg_cfg_set,"contexts/factory");
}
+++ /dev/null
-/* context_base - Code factorization across context switching implementations */
-
-/* Copyright (c) 2010-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 "xbt/function_types.h"
-#include "simgrid/simix.h"
-#include "smx_private.h"
-#include "mc/mc.h"
-
-XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix_context);
-
-void smx_ctx_base_factory_init(smx_context_factory_t *factory)
-{
- /* instantiate the context factory */
- *factory = xbt_new0(s_smx_context_factory_t, 1);
-
- (*factory)->create_context = NULL;
- (*factory)->finalize = smx_ctx_base_factory_finalize;
- (*factory)->free = smx_ctx_base_free;
- (*factory)->stop = smx_ctx_base_stop;
- (*factory)->suspend = NULL;
- (*factory)->runall = NULL;
- (*factory)->self = smx_ctx_base_self;
- (*factory)->get_process = smx_ctx_base_get_process;
-
- (*factory)->name = "base context factory";
-}
-
-int smx_ctx_base_factory_finalize(smx_context_factory_t * factory)
-{
- free(*factory);
- *factory = NULL;
- return 0;
-}
-
-smx_context_t
-smx_ctx_base_factory_create_context_sized(size_t size, xbt_main_func_t code,
- int argc, char **argv,
- void_pfn_smxprocess_t cleanup_func,
- smx_process_t process)
-{
- smx_context_t context = (smx_context_t) xbt_malloc0(size);
-
- /* Store the address of the stack in heap to compare it apart of heap comparison */
- if(MC_is_active())
- MC_ignore_heap(context, size);
-
- /* If the user provided a function for the process then use it.
- Otherwise, it is the context for maestro and we should set it as the
- current context */
- if (code) {
- context->cleanup_func = cleanup_func;
- context->argc = argc;
- context->argv = argv;
- context->code = code;
- } else {
- SIMIX_context_set_current(context);
- }
- context->process = process;
-
- return context;
-}
-
-void smx_ctx_base_free(smx_context_t context)
-{
- int i;
- if (context) {
-
- /* free argv */
- if (context->argv) {
- for (i = 0; i < context->argc; i++)
- free(context->argv[i]);
-
- free(context->argv);
- }
-
- /* free structure */
- free(context);
- }
-}
-
-void smx_ctx_base_stop(smx_context_t context)
-{
- if (context->cleanup_func)
- context->cleanup_func(context->process);
- context->process->suspended = 0;
- context->iwannadie = 0;
- simcall_process_cleanup(context->process);
- context->iwannadie = 1;
-}
-
-smx_context_t smx_ctx_base_self(void)
-{
- return SIMIX_context_get_current();
-}
-
-smx_process_t smx_ctx_base_get_process(smx_context_t context)
-{
- return context->process;
-}
+++ /dev/null
-/* 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. */
-
-/** @file smx_context_boost.cpp Userspace context switching implementation based on Boost.Context */
-
-#include <cstdint>
-
-#include <boost/context/all.hpp>
-
-#include "xbt/log.h"
-#include "smx_private.h"
-#include "src/internal_config.h"
-
-XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix_context);
-
-typedef struct s_smx_ctx_boost {
- s_smx_ctx_base_t super; /* Fields of super implementation */
-#if HAVE_BOOST_CONTEXT == 1
- boost::context::fcontext_t* fc;
-#else
- boost::context::fcontext_t fc;
-#endif
- void* stack;
-} s_smx_ctx_boost_t, *smx_ctx_boost_t;
-
-static int smx_ctx_boost_factory_finalize(smx_context_factory_t *factory);
-static smx_context_t
-smx_ctx_boost_create_context(xbt_main_func_t code, int argc, char **argv,
- void_pfn_smxprocess_t cleanup_func, smx_process_t process);
-static void smx_ctx_boost_free(smx_context_t context);
-
-static void smx_ctx_boost_wrapper(std::intptr_t arg);
-
-static void smx_ctx_boost_stop_serial(smx_context_t context);
-static void smx_ctx_boost_suspend_serial(smx_context_t context);
-static void smx_ctx_boost_resume_serial(smx_process_t first_process);
-static void smx_ctx_boost_runall_serial(void);
-
-#ifdef CONTEXT_THREADS
-static void smx_ctx_boost_stop_parallel(smx_context_t context);
-static void smx_ctx_boost_suspend_parallel(smx_context_t context);
-static void smx_ctx_boost_resume_parallel(smx_process_t first_process);
-static void smx_ctx_boost_runall_parallel(void);
-#endif
-
-#ifdef CONTEXT_THREADS
-static xbt_parmap_t boost_parmap;
-static smx_ctx_boost_t* boost_workers_context;
-static unsigned long boost_threads_working;
-static xbt_os_thread_key_t boost_worker_id_key;
-#endif
-
-static unsigned long boost_process_index = 0;
-static smx_ctx_boost_t boost_maestro_context;
-
-void SIMIX_ctx_boost_factory_init(smx_context_factory_t *factory)
-{
- smx_ctx_base_factory_init(factory);
- XBT_VERB("Activating boost context factory");
-
- (*factory)->finalize = smx_ctx_boost_factory_finalize;
- (*factory)->create_context = smx_ctx_boost_create_context;
- /* Do not overload that method (*factory)->finalize */
- (*factory)->free = smx_ctx_boost_free;
- (*factory)->name = "smx_boost_context_factory";
-
- if (SIMIX_context_is_parallel()) {
-#ifndef CONTEXT_THREADS
- THROWF(arg_error, 0, "No thread support for parallel context execution");
-#else
- int nthreads = SIMIX_context_get_nthreads();
- boost_parmap = xbt_parmap_new(nthreads, SIMIX_context_get_parallel_mode());
- boost_workers_context = xbt_new(smx_ctx_boost_t, nthreads);
- boost_maestro_context = NULL;
-
- xbt_os_thread_key_create(&boost_worker_id_key);
-
- (*factory)->stop = smx_ctx_boost_stop_parallel;
- (*factory)->suspend = smx_ctx_boost_suspend_parallel;
- (*factory)->runall = smx_ctx_boost_runall_parallel;
-#endif
- } else {
- (*factory)->stop = smx_ctx_boost_stop_serial;
- (*factory)->suspend = smx_ctx_boost_suspend_serial;
- (*factory)->runall = smx_ctx_boost_runall_serial;
- }
-}
-
-/* Initialization functions */
-
-static int smx_ctx_boost_factory_finalize(smx_context_factory_t *factory)
-{
-#ifdef CONTEXT_THREADS
- if (boost_parmap) {
- xbt_parmap_destroy(boost_parmap);
- boost_parmap = nullptr;
- }
- xbt_free(boost_workers_context);
- boost_workers_context = nullptr;
-#endif
- return smx_ctx_base_factory_finalize(factory);
-}
-
-static smx_context_t
-smx_ctx_boost_create_context(xbt_main_func_t code, int argc, char **argv,
- void_pfn_smxprocess_t cleanup_func, smx_process_t process)
-{
- smx_ctx_boost_t context =
- (smx_ctx_boost_t) smx_ctx_base_factory_create_context_sized(
- sizeof(s_smx_ctx_boost_t),
- code,
- argc,
- argv,
- cleanup_func,
- process);
-
- /* if the user provided a function for the process then use it,
- otherwise it is the context for maestro */
- if (code) {
- context->stack = SIMIX_context_stack_new();
- // We need to pass the bottom of the stack to make_fcontext,
- // depending on the stack direction it may be the lower or higher address:
-#if PTH_STACKGROWTH == -1
- void* stack = (char*) context->stack + smx_context_usable_stack_size - 1;
-#else
- void* stack = context->stack;
-#endif
- context->fc = boost::context::make_fcontext(
- stack,
- smx_context_usable_stack_size,
- smx_ctx_boost_wrapper);
- } else {
- context->stack = nullptr;
-#if HAVE_BOOST_CONTEXT == 1
- context->fc = new boost::context::fcontext_t();
-#endif
- if (boost_maestro_context == nullptr)
- boost_maestro_context = context;
- }
-
- return (smx_context_t) context;
-}
-
-static void smx_ctx_boost_free(smx_context_t c)
-{
- smx_ctx_boost_t context = (smx_ctx_boost_t) c;
- if (!context)
- return;
-#if HAVE_BOOST_CONTEXT == 1
- if (!context->stack)
- delete context->fc;
-#endif
- if ((smx_ctx_boost_t) c == boost_maestro_context)
- boost_maestro_context = nullptr;
- SIMIX_context_stack_delete(context->stack);
- smx_ctx_base_free(c);
-}
-
-static void smx_ctx_boost_wrapper(std::intptr_t arg)
-{
- smx_context_t context = (smx_context_t) arg;
- context->code(context->argc, context->argv);
- smx_ctx_boost_stop_serial(context);
-}
-
-static void smx_ctx_boost_stop_serial(smx_context_t context)
-{
- smx_ctx_base_stop(context);
- simix_global->context_factory->suspend(context);
-}
-
-static void smx_ctx_boost_suspend_serial(smx_context_t context)
-{
- /* determine the next context */
- smx_ctx_boost_t next_context;
- unsigned long int i = boost_process_index++;
-
- if (i < xbt_dynar_length(simix_global->process_to_run)) {
- /* execute the next process */
- XBT_DEBUG("Run next process");
- next_context = (smx_ctx_boost_t) xbt_dynar_get_as(
- simix_global->process_to_run, i, smx_process_t)->context;
- }
- else {
- /* all processes were run, return to maestro */
- XBT_DEBUG("No more process to run");
- next_context = (smx_ctx_boost_t) boost_maestro_context;
- }
- SIMIX_context_set_current((smx_context_t) next_context);
-#if HAVE_BOOST_CONTEXT == 1
- boost::context::jump_fcontext(
- ((smx_ctx_boost_t)context)->fc, next_context->fc, (intptr_t)next_context);
-#else
- boost::context::jump_fcontext(
- &((smx_ctx_boost_t)context)->fc, next_context->fc, (intptr_t)next_context);
-#endif
-}
-
-static void smx_ctx_boost_resume_serial(smx_process_t first_process)
-{
- smx_ctx_boost_t context = (smx_ctx_boost_t) first_process->context;
- SIMIX_context_set_current((smx_context_t) context);
-#if HAVE_BOOST_CONTEXT == 1
- boost::context::jump_fcontext(boost_maestro_context->fc, context->fc,
- (intptr_t)context);
-#else
- boost::context::jump_fcontext(&boost_maestro_context->fc, context->fc,
- (intptr_t)context);
-#endif
-}
-
-static void smx_ctx_boost_runall_serial(void)
-{
- smx_process_t first_process =
- xbt_dynar_get_as(simix_global->process_to_run, 0, smx_process_t);
- boost_process_index = 1;
-
- /* execute the first process */
- smx_ctx_boost_resume_serial(first_process);
-}
-
-// **** Parallel code
-
-#ifdef CONTEXT_THREADS
-
-static void smx_ctx_boost_stop_parallel(smx_context_t context)
-{
- smx_ctx_base_stop(context);
- smx_ctx_boost_suspend_parallel(context);
-}
-
-static void smx_ctx_boost_suspend_parallel(smx_context_t context)
-{
- smx_process_t next_work = (smx_process_t) xbt_parmap_next(boost_parmap);
- smx_ctx_boost_t next_context;
-
- if (next_work != NULL) {
- XBT_DEBUG("Run next process");
- next_context = (smx_ctx_boost_t) next_work->context;
- }
- else {
- XBT_DEBUG("No more processes to run");
- unsigned long worker_id =
- (unsigned long) xbt_os_thread_get_specific(boost_worker_id_key);
- next_context = boost_workers_context[worker_id];
- }
-
- SIMIX_context_set_current((smx_context_t) next_context);
-#if HAVE_BOOST_CONTEXT == 1
- boost::context::jump_fcontext(
- ((smx_ctx_boost_t)context)->fc, next_context->fc, (intptr_t)next_context);
-#else
- boost::context::jump_fcontext(
- &((smx_ctx_boost_t)context)->fc, next_context->fc, (intptr_t)next_context);
-#endif
-}
-
-static void smx_ctx_boost_resume_parallel(smx_process_t process)
-{
- unsigned long worker_id = __sync_fetch_and_add(&boost_threads_working, 1);
- xbt_os_thread_set_specific(boost_worker_id_key, (void*) worker_id);
-
- smx_ctx_boost_t worker_context = (smx_ctx_boost_t)SIMIX_context_self();
- boost_workers_context[worker_id] = worker_context;
- smx_ctx_boost_t context = (smx_ctx_boost_t) process->context;
-
- SIMIX_context_set_current((smx_context_t) context);
-#if HAVE_BOOST_CONTEXT == 1
- boost::context::jump_fcontext(worker_context->fc, context->fc,
- (intptr_t)context);
-#else
- boost::context::jump_fcontext(&worker_context->fc, context->fc,
- (intptr_t)context);
-#endif
-}
-
-static void smx_ctx_boost_runall_parallel(void)
-{
- boost_threads_working = 0;
- xbt_parmap_apply(boost_parmap, (void_f_pvoid_t) smx_ctx_boost_resume_parallel,
- simix_global->process_to_run);
-}
-
-#endif
#endif
#include "smx_private.h"
+#include "smx_private.hpp"
#include "xbt/heap.h"
#include "xbt/sysdep.h"
#include "xbt/log.h"
#include "popping_private.h"
#include "smx_synchro_private.h"
+#ifdef __cplusplus
+
+#include <simgrid/simix.hpp>
+
+namespace simgrid {
+namespace simix {
+
+/* Hack: let msg load directly the right factory
+ *
+ * This is a factory of factory! How nice is this?
+ */
+typedef ContextFactory* (*ContextFactoryInitializer)(void);
+XBT_PUBLIC_DATA(ContextFactoryInitializer) factory_initializer;
+
+}
+}
+
+typedef simgrid::simix::ContextFactory *smx_context_factory_t;
+
+#else
+
+typedef struct s_smx_context_factory *smx_context_factory_t;
+
+#endif
+
SG_BEGIN_DECL()
/* Define only for SimGrid benchmarking purposes */
#ifdef TIME_BENCH_PER_SR
XBT_PRIVATE void smx_ctx_raw_new_sr(void);
#endif
+
/********************************** Simix Global ******************************/
typedef struct s_smx_global {
smx_context_factory_t context_factory;
XBT_PRIVATE void SIMIX_context_set_current(smx_context_t context);
XBT_PRIVATE smx_context_t SIMIX_context_get_current(void);
-/* All factories init */
-
-XBT_PRIVATE void SIMIX_ctx_thread_factory_init(smx_context_factory_t *factory);
-XBT_PRIVATE void SIMIX_ctx_sysv_factory_init(smx_context_factory_t *factory);
-XBT_PRIVATE void SIMIX_ctx_raw_factory_init(smx_context_factory_t *factory);
-XBT_PRIVATE void SIMIX_ctx_boost_factory_init(smx_context_factory_t *factory);
-
/* ****************************** */
/* context manipulation functions */
/* ****************************** */
-/* Scenario for the end of a context:
- *
- * CASE 1: death after end of the main function
- * the context_wrapper, called internally by the context module, calls
- * SIMIX_context_stop after user code stops, smx_context_stop calls user
- * cleanup_func if any (in context settings), add current process to trashbin
- * and yields back to maestro.
- * From time to time, maestro calls SIMIX_context_empty_trash, which destroy
- * all the process and context data structures, and frees the memory
- *
- * CASE 2: brutal death
- * SIMIX_process_kill (from any process) set process->iwannadie = 1 and then
- * schedules the process. Then the process is awaken in the middle of the
- * SIMIX_process_yield function, and at the end of it, it checks that
- * iwannadie == 1, and call SIMIX_context_stop(same than first case afterward)
- */
-
-/**
- * \brief creates a new context for a user level process
- * \param code a main function
- * \param argc the number of arguments of the main function
- * \param argv the vector of arguments of the main function
- * \param cleanup_func the function to call when the context stops
- * \param cleanup_arg the argument of the cleanup_func function
- */
-static XBT_INLINE smx_context_t SIMIX_context_new(xbt_main_func_t code,
- int argc, char **argv,
- void_pfn_smxprocess_t cleanup_func,
- smx_process_t simix_process)
-{
- if (!simix_global)
- xbt_die("simix is not initialized, please call MSG_init first");
- return simix_global->context_factory->create_context(code,
- argc, argv,
- cleanup_func,
- simix_process);
-}
-
-/**
- * \brief destroy a context
- * \param context the context to destroy
- * Argument must be stopped first -- runs in maestro context
- */
-static XBT_INLINE void SIMIX_context_free(smx_context_t context)
-{
- simix_global->context_factory->free(context);
-}
-
-/**
- * \brief stops the execution of a context
- * \param context to stop
- */
-static XBT_INLINE void SIMIX_context_stop(smx_context_t context)
-{
- simix_global->context_factory->stop(context);
-}
-
-/**
- \brief suspends a context and return the control back to the one which
- scheduled it
- \param context the context to be suspended (it must be the running one)
- */
-static XBT_INLINE void SIMIX_context_suspend(smx_context_t context)
-{
- simix_global->context_factory->suspend(context);
-}
-
-/**
- \brief Executes all the processes to run (in parallel if possible).
- */
-static XBT_INLINE void SIMIX_context_runall(void)
-{
- if (!xbt_dynar_is_empty(simix_global->process_to_run)) {
- simix_global->context_factory->runall();
- }
-}
-
-/**
- \brief returns the current running context
- */
-static XBT_INLINE smx_context_t SIMIX_context_self(void)
-{
- if (simix_global && simix_global->context_factory) {
- return simix_global->context_factory->self();
- }
- return NULL;
-}
-
-/**
- \brief returns the SIMIX process associated to a context
- \param context The context
- \return The SIMIX process
- */
-static XBT_INLINE smx_process_t SIMIX_context_get_process(smx_context_t context)
-{
- return simix_global->context_factory->get_process(context);
-}
-
XBT_PUBLIC(int) SIMIX_process_get_maxpid(void);
XBT_PRIVATE void SIMIX_post_create_environment(void);
--- /dev/null
+/* Copyright (c) 2007-2010, 2012-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 SIMGRID_SIMIX_PRIVATE_HPP
+#define SIMGRID_SIMIX_PRIVATE_HPP
+
+#include <simgrid/simix.hpp>
+#include "smx_private.h"
+
+/**
+ * \brief creates a new context for a user level process
+ * \param code a main function
+ * \param argc the number of arguments of the main function
+ * \param argv the vector of arguments of the main function
+ * \param cleanup_func the function to call when the context stops
+ * \param cleanup_arg the argument of the cleanup_func function
+ */
+static inline smx_context_t SIMIX_context_new(xbt_main_func_t code,
+ int argc, char **argv,
+ void_pfn_smxprocess_t cleanup_func,
+ smx_process_t simix_process)
+{
+ if (!simix_global)
+ xbt_die("simix is not initialized, please call MSG_init first");
+ return simix_global->context_factory->create_context(
+ code, argc, argv, cleanup_func, simix_process);
+}
+
+/**
+ * \brief destroy a context
+ * \param context the context to destroy
+ * Argument must be stopped first -- runs in maestro context
+ */
+static XBT_INLINE void SIMIX_context_free(smx_context_t context)
+{
+ delete context;
+}
+
+/**
+ * \brief stops the execution of a context
+ * \param context to stop
+ */
+static XBT_INLINE void SIMIX_context_stop(smx_context_t context)
+{
+ context->stop();
+}
+
+/**
+ \brief suspends a context and return the control back to the one which
+ scheduled it
+ \param context the context to be suspended (it must be the running one)
+ */
+static XBT_INLINE void SIMIX_context_suspend(smx_context_t context)
+{
+ context->suspend();
+}
+
+/**
+ \brief Executes all the processes to run (in parallel if possible).
+ */
+static XBT_INLINE void SIMIX_context_runall(void)
+{
+ if (!xbt_dynar_is_empty(simix_global->process_to_run))
+ simix_global->context_factory->run_all();
+}
+
+/**
+ \brief returns the current running context
+ */
+static XBT_INLINE smx_context_t SIMIX_context_self(void)
+{
+ if (simix_global && simix_global->context_factory)
+ return simix_global->context_factory->self();
+ else
+ return nullptr;
+}
+
+/**
+ \brief returns the SIMIX process associated to a context
+ \param context The context
+ \return The SIMIX process
+ */
+static XBT_INLINE smx_process_t SIMIX_context_get_process(smx_context_t context)
+{
+ return context->process();
+}
+
+namespace simgrid {
+namespace simix {
+
+XBT_PRIVATE ContextFactory* thread_factory();
+XBT_PRIVATE ContextFactory* sysv_factory();
+XBT_PRIVATE ContextFactory* raw_factory();
+XBT_PRIVATE ContextFactory* boost_factory();
+
+}
+}
+
+#endif
#include "mc/mc.h"
#include "src/mc/mc_replay.h"
#include "src/mc/mc_client.h"
+#include "src/simix/smx_private.hpp"
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_process, simix,
"Logging specific to SIMIX (process)");
if (argc && argv) {
proc = SIMIX_process_self();
//FIXME: dirty cleanup method to avoid using msg cleanup functions on these processes when using MSG+SMPI
- proc->context->cleanup_func=SIMIX_process_cleanup;
+ // proc->context->cleanup_func=SIMIX_process_cleanup;
char* instance_id = (*argv)[1];
int rank = atoi((*argv)[2]);
index = smpi_process_index_of_smx_process(proc);
#include "xbt/xbt_os_thread.h"
#include "xbt/sysdep.h"
#include "src/simix/smx_private.h"
+#include "src/simix/smx_private.hpp"
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(xbt_parmap, xbt, "parmap: parallel map");
src/simix/smx_io_private.h
src/simix/smx_network_private.h
src/simix/smx_private.h
+ src/simix/smx_private.hpp
src/simix/smx_process_private.h
src/simix/smx_synchro_private.h
src/smpi/README
set(SIMIX_SRC
src/simix/libsmx.cpp
src/simix/smx_context.cpp
- src/simix/smx_context_base.cpp
+ src/simix/Context.cpp
src/simix/smx_deployment.cpp
src/simix/smx_environment.cpp
src/simix/smx_global.cpp
)
# Don't try to compile our inline assembly with MSVC
-if (MSVC)
+if (1)
set(EXTRA_DIST
${EXTRA_DIST}
src/simix/smx_context_raw.cpp)
if (HAVE_BOOST_CONTEXT)
set(SIMIX_SRC
${SIMIX_SRC}
- src/simix/smx_context_boost.cpp)
+ src/simix/BoostContext.hpp
+ src/simix/BoostContext.cpp)
else()
set(EXTRA_DIST
${EXTRA_DIST}
- src/simix/smx_context_boost.cpp)
+ src/simix/BoostContext.hpp
+ src/simix/BoostContext.cpp)
endif()
set(S4U_SRC
include/simgrid/platf_generator.h
include/simgrid/plugins.h
include/simgrid/simix.h
+ include/simgrid/simix.hpp
include/simgrid/host.h
include/simgrid/link.h
include/simgrid/s4u/actor.hpp
### depend of some variables setted upper
# -->CONTEXT_THREADS CONTEXT_UCONTEXT
-if(${CONTEXT_THREADS}) #pthread
+if(0) #pthread
set(SURF_SRC
${SURF_SRC}
src/simix/smx_context_thread.cpp
- src/xbt/xbt_os_thread.c
)
else() # NOT pthread
set(EXTRA_DIST
${EXTRA_DIST}
src/simix/smx_context_thread.cpp
+ )
+endif()
+
+if(${CONTEXT_THREADS}) #pthread
+ set(SURF_SRC
+ ${SURF_SRC}
+ src/xbt/xbt_os_thread.c
+ )
+else() # NOT pthread
+ set(EXTRA_DIST
+ ${EXTRA_DIST}
src/xbt/xbt_os_thread.c
)
endif()