X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/a76526cb68465af7b566a4afc6fff7893be6a94d..ccf671a80a47f0489c33fb1dc2a8aadfc28b5b88:/src/kernel/context/ContextSwapped.cpp diff --git a/src/kernel/context/ContextSwapped.cpp b/src/kernel/context/ContextSwapped.cpp index 292cb593d2..bd913fb87c 100644 --- a/src/kernel/context/ContextSwapped.cpp +++ b/src/kernel/context/ContextSwapped.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2009-2020. The SimGrid Team. All rights reserved. */ +/* Copyright (c) 2009-2021. 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. */ @@ -7,12 +7,14 @@ #include "simgrid/modelchecker.h" #include "src/internal_config.h" #include "src/kernel/actor/ActorImpl.hpp" -#include "src/kernel/context/context_private.hpp" #include "src/simix/smx_private.hpp" #include "xbt/parmap.hpp" #include "src/kernel/context/ContextSwapped.hpp" +#include +#include + #ifdef _WIN32 #include #include @@ -28,9 +30,38 @@ #if HAVE_VALGRIND_H #include #endif +#if HAVE_SANITIZER_ADDRESS_FIBER_SUPPORT +#include +#endif +#if HAVE_SANITIZER_THREAD_FIBER_SUPPORT +#include +#endif XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix_context); +// The name of this function is currently hardcoded in MC (as string). +// Do not change it without fixing those references as well. +void smx_ctx_wrapper(simgrid::kernel::context::SwappedContext* context) +{ +#if HAVE_SANITIZER_ADDRESS_FIBER_SUPPORT + __sanitizer_finish_switch_fiber(nullptr, &context->asan_ctx_->asan_stack_, &context->asan_ctx_->asan_stack_size_); +#endif + try { + (*context)(); + context->Context::stop(); + } catch (simgrid::ForcefulKillException const&) { + XBT_DEBUG("Caught a ForcefulKillException"); + } catch (simgrid::Exception const& e) { + XBT_INFO("Actor killed by an uncaught exception %s", boost::core::demangle(typeid(e).name()).c_str()); + throw; + } +#if HAVE_SANITIZER_ADDRESS_FIBER_SUPPORT + context->asan_stop_ = true; +#endif + context->suspend(); + THROW_IMPOSSIBLE; +} + namespace simgrid { namespace kernel { namespace context { @@ -39,16 +70,16 @@ namespace context { thread_local SwappedContext* SwappedContext::worker_context_ = nullptr; SwappedContext::SwappedContext(std::function&& code, smx_actor_t actor, SwappedContextFactory* factory) - : Context(std::move(code), actor), factory_(factory) + : Context(std::move(code), actor), factory_(*factory) { - // Save maestro (=context created first) in preparation for run_all - if (not SIMIX_context_is_parallel() && factory->maestro_context_ == nullptr) - factory->maestro_context_ = this; + // Save maestro (=first created context) in preparation for run_all + if (not SIMIX_context_is_parallel() && factory_.maestro_context_ == nullptr) + factory_.maestro_context_ = this; if (has_code()) { - xbt_assert((smx_context_stack_size & 0xf) == 0, "smx_context_stack_size should be multiple of 16"); + xbt_assert((actor->get_stacksize() & 0xf) == 0, "Actor stack size should be multiple of 16"); if (smx_context_guard_size > 0 && not MC_is_active()) { -#if !defined(PTH_STACKGROWTH) || (PTH_STACKGROWTH != -1) +#if PTH_STACKGROWTH != -1 xbt_die( "Stack overflow protection is known to be broken on your system: you stacks grow upwards (or detection is " "broken). " @@ -57,11 +88,11 @@ SwappedContext::SwappedContext(std::function&& code, smx_actor_t actor, * Protected pages need to be put after the stack when PTH_STACKGROWTH == 1. */ #endif - size_t size = smx_context_stack_size + smx_context_guard_size; + size_t size = actor->get_stacksize() + smx_context_guard_size; #if SIMGRID_HAVE_MC /* Cannot use posix_memalign when SIMGRID_HAVE_MC. Align stack by hand, and save the * pointer returned by xbt_malloc0. */ - unsigned char* alloc = static_cast(xbt_malloc0(size + xbt_pagesize)); + auto* alloc = static_cast(xbt_malloc0(size + xbt_pagesize)); stack_ = alloc - (reinterpret_cast(alloc) & (xbt_pagesize - 1)) + xbt_pagesize; reinterpret_cast(stack_)[-1] = alloc; #elif !defined(_WIN32) @@ -88,17 +119,23 @@ SwappedContext::SwappedContext(std::function&& code, smx_actor_t actor, #endif this->stack_ = this->stack_ + smx_context_guard_size; } else { - this->stack_ = static_cast(xbt_malloc0(smx_context_stack_size)); + this->stack_ = static_cast(xbt_malloc0(actor->get_stacksize())); } -#if PTH_STACKGROWTH == -1 - ASAN_ONLY(this->asan_stack_ = this->stack_ + smx_context_stack_size); -#else - ASAN_ONLY(this->asan_stack_ = this->stack_); -#endif #if HAVE_VALGRIND_H if (RUNNING_ON_VALGRIND) - this->valgrind_stack_id_ = VALGRIND_STACK_REGISTER(this->stack_, this->stack_ + smx_context_stack_size); + this->valgrind_stack_id_ = VALGRIND_STACK_REGISTER(this->stack_, this->stack_ + actor->get_stacksize()); +#endif +#if HAVE_SANITIZER_ADDRESS_FIBER_SUPPORT + this->asan_stack_ = get_stack_bottom(); +#endif +#if HAVE_SANITIZER_THREAD_FIBER_SUPPORT + this->tsan_fiber_ = __tsan_create_fiber(0); +#endif + } else { + // not has_code(): in maestro context +#if HAVE_SANITIZER_THREAD_FIBER_SUPPORT + this->tsan_fiber_ = __tsan_get_current_fiber(); #endif } } @@ -108,6 +145,9 @@ SwappedContext::~SwappedContext() if (stack_ == nullptr) // maestro has no extra stack return; +#if HAVE_SANITIZER_THREAD_FIBER_SUPPORT + __tsan_destroy_fiber(tsan_fiber_); +#endif #if HAVE_VALGRIND_H if (RUNNING_ON_VALGRIND) VALGRIND_STACK_DEREGISTER(valgrind_stack_id_); @@ -130,9 +170,14 @@ SwappedContext::~SwappedContext() xbt_free(stack_); } -unsigned char* SwappedContext::get_stack() +unsigned char* SwappedContext::get_stack_bottom() const { + // Depending on the stack direction, its bottom (that make_fcontext needs) may be the lower or higher end +#if PTH_STACKGROWTH == 1 return stack_; +#else + return stack_ + get_actor()->get_stacksize(); +#endif } void SwappedContext::stop() @@ -142,6 +187,24 @@ void SwappedContext::stop() throw ForcefulKillException(); } +void SwappedContext::swap_into(SwappedContext* to) +{ +#if HAVE_SANITIZER_ADDRESS_FIBER_SUPPORT + void* fake_stack = nullptr; + to->asan_ctx_ = this; + __sanitizer_start_switch_fiber(this->asan_stop_ ? nullptr : &fake_stack, to->asan_stack_, to->asan_stack_size_); +#endif +#if HAVE_SANITIZER_THREAD_FIBER_SUPPORT + __tsan_switch_to_fiber(to->tsan_fiber_, 0); +#endif + + swap_into_for_real(to); + +#if HAVE_SANITIZER_ADDRESS_FIBER_SUPPORT + __sanitizer_finish_switch_fiber(fake_stack, &this->asan_ctx_->asan_stack_, &this->asan_ctx_->asan_stack_size_); +#endif +} + /** Maestro wants to run all ready actors */ void SwappedContextFactory::run_all() { @@ -152,8 +215,8 @@ void SwappedContextFactory::run_all() if (SIMIX_context_is_parallel()) { // We lazily create the parmap so that all options are actually processed when doing so. if (parmap_ == nullptr) - parmap_.reset( - new simgrid::xbt::Parmap(SIMIX_context_get_nthreads(), SIMIX_context_get_parallel_mode())); + parmap_ = std::make_unique>(SIMIX_context_get_nthreads(), + SIMIX_context_get_parallel_mode()); // Usually, Parmap::apply() executes the provided function on all elements of the array. // Here, the executed function does not return the control to the parmap before all the array is processed: @@ -163,7 +226,7 @@ void SwappedContextFactory::run_all() // - So, resume() is only launched from the parmap for the first job of each minion. parmap_->apply( [](const actor::ActorImpl* process) { - SwappedContext* context = static_cast(process->context_.get()); + auto* context = static_cast(process->context_.get()); context->resume(); }, simix_global->actors_to_run); @@ -187,7 +250,7 @@ void SwappedContextFactory::run_all() */ void SwappedContext::resume() { - SwappedContext* old = static_cast(self()); + auto* old = static_cast(self()); if (SIMIX_context_is_parallel()) { // Save my current soul (either maestro, or one of the minions) in a thread-specific area worker_context_ = old; @@ -212,7 +275,7 @@ void SwappedContext::suspend() SwappedContext* next_context; if (SIMIX_context_is_parallel()) { // Get some more work to directly swap into the next executable actor instead of yielding back to the parmap - boost::optional next_work = factory_->parmap_->next(); + boost::optional next_work = factory_.parmap_->next(); if (next_work) { // There is a next soul to embody (ie, another executable actor) XBT_DEBUG("Run next process"); @@ -226,8 +289,8 @@ void SwappedContext::suspend() } } else { // sequential execution /* determine the next context */ - unsigned long int i = factory_->process_index_; - factory_->process_index_++; + unsigned long int i = factory_.process_index_; + factory_.process_index_++; if (i < simix_global->actors_to_run.size()) { /* Actually swap into the next actor directly without transiting to maestro */ @@ -236,7 +299,7 @@ void SwappedContext::suspend() } else { /* all processes were run, actually return to maestro */ XBT_DEBUG("No more actors to run"); - next_context = factory_->maestro_context_; + next_context = factory_.maestro_context_; } } Context::set_current(next_context);