X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/10ceac5fd14fb0426b5c93bda85676a79b02d0be..d185bae25f7b17fd34cdea9b4f038a021b6f526d:/src/kernel/context/ContextUnix.cpp diff --git a/src/kernel/context/ContextUnix.cpp b/src/kernel/context/ContextUnix.cpp index 550172e6ce..0ee4c14a1c 100644 --- a/src/kernel/context/ContextUnix.cpp +++ b/src/kernel/context/ContextUnix.cpp @@ -1,20 +1,17 @@ -/* Copyright (c) 2009-2015. The SimGrid Team. - * All rights reserved. */ +/* Copyright (c) 2009-2017. 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 UContext.cpp Context switching with ucontexts from System V */ +/* \file UContext.cpp Context switching with ucontexts from System V */ -#include - -#include #include /* context relative declarations */ -#include "xbt/parmap.h" -#include "src/simix/smx_private.h" -#include "src/internal_config.h" #include "mc/mc.h" +#include "src/mc/mc_ignore.h" +#include "src/simix/ActorImpl.hpp" +#include "src/simix/smx_private.h" +#include "xbt/parmap.hpp" /** Many integers are needed to store a pointer * @@ -57,7 +54,7 @@ namespace context { }}} #if HAVE_THREAD_CONTEXTS -static xbt_parmap_t sysv_parmap; +static simgrid::xbt::Parmap* sysv_parmap; static simgrid::kernel::context::ParallelUContext** sysv_workers_context; /* space to save the worker's context in each thread */ static uintptr_t sysv_threads_working; /* number of threads that have started their work */ static xbt_os_thread_key_t sysv_worker_id_key; /* thread-specific storage for the thread id */ @@ -84,6 +81,7 @@ public: UContext(std::function code, void_pfn_smxprocess_t cleanup_func, smx_actor_t process); ~UContext() override; + void stop() override; }; class SerialUContext : public UContext { @@ -92,7 +90,6 @@ public: void_pfn_smxprocess_t cleanup_func, smx_actor_t process) : UContext(std::move(code), cleanup_func, process) {} - void stop() override; void suspend() override; void resume(); }; @@ -103,7 +100,6 @@ public: void_pfn_smxprocess_t cleanup_func, smx_actor_t process) : UContext(std::move(code), cleanup_func, process) {} - void stop() override; void suspend() override; void resume(); }; @@ -148,8 +144,7 @@ UContextFactory::UContextFactory() : ContextFactory("UContextFactory") UContextFactory::~UContextFactory() { #if HAVE_THREAD_CONTEXTS - if (sysv_parmap) - xbt_parmap_destroy(sysv_parmap); + delete sysv_parmap; xbt_free(sysv_workers_context); #endif } @@ -161,7 +156,7 @@ UContextFactory::~UContextFactory() void UContextFactory::run_all() { if (sysv_parallel) { - #if HAVE_THREAD_CONTEXTS +#if HAVE_THREAD_CONTEXTS sysv_threads_working = 0; // Parmap_apply ensures that every working thread get an index in the // process_to_run array (through an atomic fetch_and_add), @@ -171,29 +166,26 @@ void UContextFactory::run_all() // with simix_global->context_factory (which might not be initialized // when bootstrapping): if (sysv_parmap == nullptr) - sysv_parmap = xbt_parmap_new( - SIMIX_context_get_nthreads(), SIMIX_context_get_parallel_mode()); - - xbt_parmap_apply(sysv_parmap, - [](void* arg) { - smx_actor_t process = (smx_actor_t) arg; - ParallelUContext* context = static_cast(process->context); - context->resume(); - }, - simix_global->process_to_run); - #else + sysv_parmap = + new simgrid::xbt::Parmap(SIMIX_context_get_nthreads(), SIMIX_context_get_parallel_mode()); + + sysv_parmap->apply( + [](smx_actor_t process) { + ParallelUContext* context = static_cast(process->context); + context->resume(); + }, + simix_global->process_to_run); +#else xbt_die("You asked for a parallel execution, but you don't have any threads."); - #endif +#endif } else { // Serial: - if (xbt_dynar_is_empty(simix_global->process_to_run)) + if (simix_global->process_to_run.empty()) return; - smx_actor_t first_process = - xbt_dynar_get_as(simix_global->process_to_run, 0, smx_actor_t); + smx_actor_t first_process = simix_global->process_to_run.front(); sysv_process_index = 1; - SerialUContext* context = - static_cast(first_process->context); + SerialUContext* context = static_cast(first_process->context); context->resume(); } } @@ -224,7 +216,7 @@ UContext::UContext(std::function code, sysv_maestro_context = this; } -#if HAVE_MC +#if SIMGRID_HAVE_MC if (MC_is_active() && has_code()) { MC_register_stack_area(this->stack_, process, &(this->uc_), smx_context_usable_stack_size); @@ -237,6 +229,11 @@ UContext::~UContext() SIMIX_context_stack_delete(this->stack_); } +void UContext::stop() +{ + Context::stop(); + throw StopRequest(); +} }}} // namespace simgrid::kernel::context static void smx_ctx_sysv_wrapper(int first, ...) @@ -254,36 +251,33 @@ static void smx_ctx_sysv_wrapper(int first, ...) } memcpy(&context, ctx_addr, sizeof(simgrid::kernel::context::UContext*)); - (*context)(); - context->stop(); + try { + (*context)(); + context->Context::stop(); + } catch (simgrid::kernel::context::Context::StopRequest const&) { + XBT_DEBUG("Caught a StopRequest"); + } + context->suspend(); } namespace simgrid { namespace kernel { namespace context { -void SerialUContext::stop() -{ - Context::stop(); - this->suspend(); -} - void SerialUContext::suspend() { /* determine the next context */ SerialUContext* next_context = nullptr; unsigned long int i = sysv_process_index++; - if (i < xbt_dynar_length(simix_global->process_to_run)) { + if (i < simix_global->process_to_run.size()) { /* execute the next process */ XBT_DEBUG("Run next process"); - next_context = (SerialUContext*) xbt_dynar_get_as( - simix_global->process_to_run,i, smx_actor_t)->context; - } - else { + 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 = (SerialUContext*) sysv_maestro_context; + next_context = static_cast(sysv_maestro_context); } SIMIX_context_set_current(next_context); swapcontext(&this->uc_, &next_context->uc_); @@ -294,13 +288,7 @@ void SerialUContext::suspend() void SerialUContext::resume() { SIMIX_context_set_current(this); - swapcontext(&((SerialUContext*)sysv_maestro_context)->uc_, &this->uc_); -} - -void ParallelUContext::stop() -{ - UContext::stop(); - this->suspend(); + swapcontext(&static_cast(sysv_maestro_context)->uc_, &this->uc_); } /** Run one particular simulated process on the current thread. */ @@ -312,11 +300,11 @@ void ParallelUContext::resume() // Store the number of my containing body in os-thread-specific area : xbt_os_thread_set_specific(sysv_worker_id_key, (void*) worker_id); // Get my current soul: - ParallelUContext* worker_context = (ParallelUContext*) SIMIX_context_self(); + ParallelUContext* worker_context = static_cast(SIMIX_context_self()); // Write down that this soul is hosted in that body (for now) sysv_workers_context[worker_id] = worker_context; // Retrieve the system-level info that fuels this soul: - ucontext_t* worker_stack = &((ParallelUContext*) worker_context)->uc_; + ucontext_t* worker_stack = &worker_context->uc_; // Write in simix that I switched my soul SIMIX_context_set_current(this); // Actually do that using the relevant library call: @@ -350,17 +338,13 @@ void ParallelUContext::suspend() #if HAVE_THREAD_CONTEXTS /* determine the next context */ // Get the next soul to embody now: - smx_actor_t next_work = (smx_actor_t) xbt_parmap_next(sysv_parmap); - ParallelUContext* next_context = nullptr; - // Will contain the next soul to run, either simulated or initial minion's one - ucontext_t* next_stack; - - if (next_work != nullptr) { + boost::optional next_work = sysv_parmap->next(); + ParallelUContext* next_context; + if (next_work) { // There is a next soul to embody (ie, a next process to resume) XBT_DEBUG("Run next process"); - next_context = (ParallelUContext*) next_work->context; - } - else { + next_context = static_cast(next_work.get()->context); + } else { // All processes were run, go to the barrier XBT_DEBUG("No more processes to run"); // Get back the identity of my body that was stored when starting @@ -368,11 +352,12 @@ void ParallelUContext::suspend() uintptr_t worker_id = (uintptr_t) xbt_os_thread_get_specific(sysv_worker_id_key); // Deduce the initial soul of that body - next_context = (ParallelUContext*) sysv_workers_context[worker_id]; + next_context = sysv_workers_context[worker_id]; // When given that soul, the body will wait for the next scheduling round } - next_stack = &next_context->uc_; + // Will contain the next soul to run, either simulated or initial minion's one + ucontext_t* next_stack = &next_context->uc_; SIMIX_context_set_current(next_context); // Get that next soul: