X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/1fc042e8bc9c51f9267fa1936deaebe59ae01ee7..92ba078919550eaefcf69489ee3a28e42381c786:/src/kernel/context/ContextBoost.cpp diff --git a/src/kernel/context/ContextBoost.cpp b/src/kernel/context/ContextBoost.cpp index 3e1836237d..e508c5646a 100644 --- a/src/kernel/context/ContextBoost.cpp +++ b/src/kernel/context/ContextBoost.cpp @@ -1,83 +1,27 @@ -/* Copyright (c) 2015-2017. The SimGrid Team. All rights reserved. */ +/* Copyright (c) 2015-2018. 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 -#include -#include - -#include - -#include -#include - -#include "src/internal_config.h" -#include "src/kernel/context/ContextBoost.hpp" +#include "ContextBoost.hpp" +#include "context_private.hpp" #include "src/simix/smx_private.hpp" -#if HAVE_SANITIZE_ADDRESS_FIBER_SUPPORT -#include -#define ASAN_EVAL(expr) (expr) -#define ASAN_START_SWITCH(fake_stack_save, bottom, size) __sanitizer_start_switch_fiber(fake_stack_save, bottom, size) -#define ASAN_FINISH_SWITCH(fake_stack_save, bottom_old, size_old) \ - __sanitizer_finish_switch_fiber(fake_stack_save, bottom_old, size_old) -#else -#define ASAN_EVAL(expr) (void)0 -#define ASAN_START_SWITCH(fake_stack_save, bottom, size) (void)0 -#define ASAN_FINISH_SWITCH(fake_stack_save, bottom_old, size_old) (void)(fake_stack_save) -#endif - XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix_context); namespace simgrid { namespace kernel { namespace context { -class BoostSerialContext : public BoostContext { -public: - BoostSerialContext(std::function code, - void_pfn_smxprocess_t cleanup_func, - smx_actor_t process) - : BoostContext(std::move(code), cleanup_func, process) {} - void suspend() override; -}; - -#if HAVE_THREAD_CONTEXTS -class BoostParallelContext : public BoostContext { -public: - BoostParallelContext(std::function code, - void_pfn_smxprocess_t cleanup_func, - smx_actor_t process) - : BoostContext(std::move(code), cleanup_func, process) {} - void suspend() override; - void resume() override; -}; -#endif - // BoostContextFactory -bool BoostContext::parallel_ = false; -simgrid::xbt::Parmap* BoostContext::parmap_ = nullptr; -uintptr_t 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::workers_context_; - BoostContextFactory::BoostContextFactory() - : ContextFactory("BoostContextFactory") + : ContextFactory("BoostContextFactory"), parallel_(SIMIX_context_is_parallel()) { - BoostContext::parallel_ = SIMIX_context_is_parallel(); - if (BoostContext::parallel_) { + BoostContext::setMaestro(nullptr); + if (parallel_) { #if HAVE_THREAD_CONTEXTS - BoostContext::parmap_ = nullptr; - BoostContext::workers_context_.clear(); - BoostContext::workers_context_.resize(SIMIX_context_get_nthreads(), nullptr); - BoostContext::maestro_context_ = nullptr; - xbt_os_thread_key_create(&BoostContext::worker_id_key_); + ParallelBoostContext::initialize(); #else xbt_die("No thread support for parallel context execution"); #endif @@ -87,103 +31,45 @@ BoostContextFactory::BoostContextFactory() BoostContextFactory::~BoostContextFactory() { #if HAVE_THREAD_CONTEXTS - delete BoostContext::parmap_; - BoostContext::parmap_ = nullptr; - BoostContext::workers_context_.clear(); + if (parallel_) + ParallelBoostContext::finalize(); #endif } smx_context_t BoostContextFactory::create_context(std::function code, void_pfn_smxprocess_t cleanup_func, smx_actor_t process) { - BoostContext* context = nullptr; - if (BoostContext::parallel_) #if HAVE_THREAD_CONTEXTS - context = this->new_context(std::move(code), cleanup_func, process); -#else - xbt_die("No support for parallel execution"); + if (parallel_) + return this->new_context(std::move(code), cleanup_func, process); #endif - else - context = this->new_context(std::move(code), cleanup_func, process); - return context; + + return this->new_context(std::move(code), cleanup_func, process); } void BoostContextFactory::run_all() { #if HAVE_THREAD_CONTEXTS - if (BoostContext::parallel_) { - BoostContext::threads_working_ = 0; - if (not BoostContext::parmap_) - BoostContext::parmap_ = - new simgrid::xbt::Parmap(SIMIX_context_get_nthreads(), SIMIX_context_get_parallel_mode()); - BoostContext::parmap_->apply( - [](smx_actor_t process) { - BoostContext* context = static_cast(process->context); - return context->resume(); - }, - simix_global->process_to_run); - } else + if (parallel_) + ParallelBoostContext::run_all(); + else #endif - { - if (simix_global->process_to_run.empty()) - return; - smx_actor_t first_process = simix_global->process_to_run.front(); - BoostContext::process_index_ = 1; - /* execute the first process */ - static_cast(first_process->context)->resume(); - } + SerialBoostContext::run_all(); } - // BoostContext -void BoostContext::smx_ctx_boost_wrapper(BoostContext::ctx_arg_type arg) -{ -#if BOOST_VERSION < 106100 - BoostContext* context = reinterpret_cast(arg); -#else - ASAN_FINISH_SWITCH(nullptr, &static_cast(arg.data)[0]->asan_stack_, - &static_cast(arg.data)[0]->asan_stack_size_); - static_cast(arg.data)[0]->fc_ = arg.fctx; - BoostContext* context = static_cast(arg.data)[1]; -#endif - try { - (*context)(); - context->Context::stop(); - } catch (StopRequest const&) { - XBT_DEBUG("Caught a StopRequest"); - } - ASAN_EVAL(context->asan_stop_ = true); - context->suspend(); -} - -inline void BoostContext::smx_ctx_boost_jump_fcontext(BoostContext* from, BoostContext* to) -{ -#if BOOST_VERSION < 105600 - boost::context::jump_fcontext(from->fc_, to->fc_, reinterpret_cast(to)); -#elif BOOST_VERSION < 106100 - boost::context::jump_fcontext(&from->fc_, to->fc_, reinterpret_cast(to)); -#else - BoostContext* ctx[2] = {from, to}; - void* fake_stack; - ASAN_START_SWITCH(from->asan_stop_ ? nullptr : &fake_stack, to->asan_stack_, to->asan_stack_size_); - boost::context::detail::transfer_t arg = boost::context::detail::jump_fcontext(to->fc_, ctx); - ASAN_FINISH_SWITCH(fake_stack, &static_cast(arg.data)[0]->asan_stack_, - &static_cast(arg.data)[0]->asan_stack_size_); - static_cast(arg.data)[0]->fc_ = arg.fctx; -#endif -} +BoostContext* BoostContext::maestro_context_ = nullptr; -BoostContext::BoostContext(std::function code, - void_pfn_smxprocess_t cleanup_func, smx_actor_t process) - : Context(std::move(code), cleanup_func, process) +BoostContext::BoostContext(std::function code, void_pfn_smxprocess_t cleanup_func, smx_actor_t process) + : Context(std::move(code), cleanup_func, process) { /* if the user provided a function for the process then use it, otherwise it is the context for maestro */ if (has_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: + /* 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 = static_cast(this->stack_) + smx_context_usable_stack_size; #else @@ -191,9 +77,9 @@ BoostContext::BoostContext(std::function code, #endif ASAN_EVAL(this->asan_stack_ = stack); #if BOOST_VERSION < 106100 - this->fc_ = boost::context::make_fcontext(stack, smx_context_usable_stack_size, smx_ctx_boost_wrapper); + this->fc_ = boost::context::make_fcontext(stack, smx_context_usable_stack_size, BoostContext::wrapper); #else - this->fc_ = boost::context::detail::make_fcontext(stack, smx_context_usable_stack_size, smx_ctx_boost_wrapper); + this->fc_ = boost::context::detail::make_fcontext(stack, smx_context_usable_stack_size, BoostContext::wrapper); #endif } else { #if BOOST_VERSION < 105600 @@ -215,7 +101,43 @@ BoostContext::~BoostContext() SIMIX_context_stack_delete(this->stack_); } -// BoostSerialContext +void BoostContext::wrapper(BoostContext::arg_type arg) +{ +#if BOOST_VERSION < 106100 + BoostContext* context = reinterpret_cast(arg); +#else + BoostContext* context = static_cast(arg.data)[1]; + ASAN_ASSERT(context->asan_ctx_ == static_cast(arg.data)[0]); + ASAN_FINISH_SWITCH(nullptr, &context->asan_ctx_->asan_stack_, &context->asan_ctx_->asan_stack_size_); + static_cast(arg.data)[0]->fc_ = arg.fctx; +#endif + try { + (*context)(); + context->Context::stop(); + } catch (StopRequest const&) { + XBT_DEBUG("Caught a StopRequest"); + } + ASAN_EVAL(context->asan_stop_ = true); + context->suspend(); +} + +inline void BoostContext::swap(BoostContext* from, BoostContext* to) +{ +#if BOOST_VERSION < 105600 + boost::context::jump_fcontext(from->fc_, to->fc_, reinterpret_cast(to)); +#elif BOOST_VERSION < 106100 + boost::context::jump_fcontext(&from->fc_, to->fc_, reinterpret_cast(to)); +#else + BoostContext* ctx[2] = {from, to}; + void* fake_stack = nullptr; + ASAN_EVAL(to->asan_ctx_ = from); + ASAN_START_SWITCH(from->asan_stop_ ? nullptr : &fake_stack, to->asan_stack_, to->asan_stack_size_); + boost::context::detail::transfer_t arg = boost::context::detail::jump_fcontext(to->fc_, ctx); + ASAN_ASSERT(from->asan_ctx_ == static_cast(arg.data)[0]); + ASAN_FINISH_SWITCH(fake_stack, &from->asan_ctx_->asan_stack_, &from->asan_ctx_->asan_stack_size_); + static_cast(arg.data)[0]->fc_ = arg.fctx; +#endif +} void BoostContext::stop() { @@ -223,63 +145,111 @@ void BoostContext::stop() throw StopRequest(); } -void BoostContext::resume() -{ - SIMIX_context_set_current(this); - smx_ctx_boost_jump_fcontext(maestro_context_, this); -} +// SerialBoostContext + +unsigned long SerialBoostContext::process_index_; -void BoostSerialContext::suspend() +void SerialBoostContext::suspend() { /* determine the next context */ - BoostSerialContext* next_context; + SerialBoostContext* next_context; unsigned long int i = process_index_; process_index_++; if (i < simix_global->process_to_run.size()) { /* execute the next process */ XBT_DEBUG("Run next process"); - next_context = static_cast(simix_global->process_to_run[i]->context); + next_context = static_cast(simix_global->process_to_run[i]->context); } else { /* all processes were run, return to maestro */ XBT_DEBUG("No more process to run"); - next_context = static_cast(maestro_context_); + next_context = static_cast(BoostContext::getMaestro()); } - SIMIX_context_set_current(static_cast(next_context)); - smx_ctx_boost_jump_fcontext(this, next_context); + SIMIX_context_set_current(next_context); + BoostContext::swap(this, next_context); +} + +void SerialBoostContext::resume() +{ + SIMIX_context_set_current(this); + BoostContext::swap(BoostContext::getMaestro(), this); +} + +void SerialBoostContext::run_all() +{ + if (simix_global->process_to_run.empty()) + return; + smx_actor_t first_process = simix_global->process_to_run.front(); + process_index_ = 1; + /* execute the first process */ + static_cast(first_process->context)->resume(); } -// BoostParallelContext +// ParallelBoostContext #if HAVE_THREAD_CONTEXTS -void BoostParallelContext::suspend() +simgrid::xbt::Parmap* ParallelBoostContext::parmap_; +std::atomic ParallelBoostContext::threads_working_; +xbt_os_thread_key_t ParallelBoostContext::worker_id_key_; +std::vector ParallelBoostContext::workers_context_; + +void ParallelBoostContext::initialize() +{ + parmap_ = nullptr; + workers_context_.clear(); + workers_context_.resize(SIMIX_context_get_nthreads(), nullptr); + xbt_os_thread_key_create(&worker_id_key_); +} + +void ParallelBoostContext::finalize() +{ + delete parmap_; + parmap_ = nullptr; + workers_context_.clear(); + xbt_os_thread_key_destroy(worker_id_key_); +} + +void ParallelBoostContext::run_all() +{ + threads_working_ = 0; + if (parmap_ == nullptr) + parmap_ = new simgrid::xbt::Parmap(SIMIX_context_get_nthreads(), SIMIX_context_get_parallel_mode()); + parmap_->apply( + [](smx_actor_t process) { + ParallelBoostContext* context = static_cast(process->context); + context->resume(); + }, + simix_global->process_to_run); +} + +void ParallelBoostContext::suspend() { boost::optional next_work = parmap_->next(); - BoostParallelContext* next_context; + ParallelBoostContext* next_context; if (next_work) { XBT_DEBUG("Run next process"); - next_context = static_cast(next_work.get()->context); + next_context = static_cast(next_work.get()->context); } else { XBT_DEBUG("No more processes to run"); uintptr_t worker_id = reinterpret_cast(xbt_os_thread_get_specific(worker_id_key_)); - next_context = static_cast(workers_context_[worker_id]); + next_context = workers_context_[worker_id]; } - SIMIX_context_set_current(static_cast(next_context)); - smx_ctx_boost_jump_fcontext(this, next_context); + SIMIX_context_set_current(next_context); + BoostContext::swap(this, next_context); } -void BoostParallelContext::resume() +void ParallelBoostContext::resume() { - uintptr_t worker_id = __sync_fetch_and_add(&threads_working_, 1); + uintptr_t worker_id = threads_working_.fetch_add(1, std::memory_order_relaxed); xbt_os_thread_set_specific(worker_id_key_, reinterpret_cast(worker_id)); - BoostParallelContext* worker_context = static_cast(SIMIX_context_self()); - workers_context_[worker_id] = worker_context; + ParallelBoostContext* worker_context = static_cast(SIMIX_context_self()); + workers_context_[worker_id] = worker_context; SIMIX_context_set_current(this); - smx_ctx_boost_jump_fcontext(worker_context, this); + BoostContext::swap(worker_context, this); } #endif @@ -289,5 +259,4 @@ XBT_PRIVATE ContextFactory* boost_factory() XBT_VERB("Using Boost contexts. Welcome to the 21th century."); return new BoostContextFactory(); } - }}} // namespace