From 4d5c6aed22b8ae1c8a73cd04d8ab800322d177bf Mon Sep 17 00:00:00 2001 From: Martin Quinson Date: Sat, 5 Jan 2019 20:02:13 +0100 Subject: [PATCH] Change a subclass into a superclass around contexts SerialUContext was a subclass of UContext. SwappedContext does the same, as a super class of UContext. The idea is to make SwappedContext the ancestor of BoostContext and RawContext too, to factorize as much code as possible. --- src/kernel/context/ContextBoost.cpp | 3 +- src/kernel/context/ContextRaw.cpp | 3 +- src/kernel/context/ContextSwapped.cpp | 60 ++++++++++++++++++++++++++ src/kernel/context/ContextSwapped.hpp | 39 +++++++++++++++++ src/kernel/context/ContextUnix.cpp | 61 +++++---------------------- src/kernel/context/ContextUnix.hpp | 26 ++---------- tools/cmake/DefinePackages.cmake | 2 + 7 files changed, 119 insertions(+), 75 deletions(-) create mode 100644 src/kernel/context/ContextSwapped.cpp create mode 100644 src/kernel/context/ContextSwapped.hpp diff --git a/src/kernel/context/ContextBoost.cpp b/src/kernel/context/ContextBoost.cpp index 07bb785472..e9ea749708 100644 --- a/src/kernel/context/ContextBoost.cpp +++ b/src/kernel/context/ContextBoost.cpp @@ -163,8 +163,9 @@ void SerialBoostContext::suspend() void SerialBoostContext::resume() { + BoostContext* old = static_cast(self()); Context::set_current(this); - BoostContext::swap(BoostContext::get_maestro(), this); + BoostContext::swap(old, this); } void SerialBoostContext::run_all() diff --git a/src/kernel/context/ContextRaw.cpp b/src/kernel/context/ContextRaw.cpp index a0c065fcfa..93d7d86824 100644 --- a/src/kernel/context/ContextRaw.cpp +++ b/src/kernel/context/ContextRaw.cpp @@ -303,8 +303,9 @@ void SerialRawContext::suspend() void SerialRawContext::resume() { + RawContext* old = static_cast(self()); Context::set_current(this); - RawContext::swap(RawContext::get_maestro(), this); + RawContext::swap(old, this); } void SerialRawContext::run_all() diff --git a/src/kernel/context/ContextSwapped.cpp b/src/kernel/context/ContextSwapped.cpp new file mode 100644 index 0000000000..6897767f37 --- /dev/null +++ b/src/kernel/context/ContextSwapped.cpp @@ -0,0 +1,60 @@ +/* Copyright (c) 2009-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 "src/kernel/context/context_private.hpp" +#include "src/simix/ActorImpl.hpp" +#include "src/simix/smx_private.hpp" + +#include "ContextSwapped.hpp" + +XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix_context); + +namespace simgrid { +namespace kernel { +namespace context { + +unsigned long SwappedContext::process_index_; + +SwappedContext* SwappedContext::maestro_context_ = nullptr; + +void SwappedContext::suspend() +{ + /* determine the next context */ + SwappedContext* 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_); + } else { + /* all processes were run, return to maestro */ + XBT_DEBUG("No more process to run"); + next_context = static_cast(get_maestro()); + } + Context::set_current(next_context); + this->swap_into(next_context); +} + +void SwappedContext::resume() +{ + SwappedContext* old = static_cast(self()); + Context::set_current(this); + old->swap_into(this); +} + +void SwappedContext::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(); +} +} // namespace context +} // namespace kernel +} // namespace simgrid diff --git a/src/kernel/context/ContextSwapped.hpp b/src/kernel/context/ContextSwapped.hpp new file mode 100644 index 0000000000..8b5188d941 --- /dev/null +++ b/src/kernel/context/ContextSwapped.hpp @@ -0,0 +1,39 @@ +/* Copyright (c) 2009-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. */ + +#ifndef SIMGRID_SIMIX_SWAPPED_CONTEXT_HPP +#define SIMGRID_SIMIX_SWAPPED_CONTEXT_HPP + +#include "Context.hpp" + +namespace simgrid { +namespace kernel { +namespace context { + +class SwappedContext : public Context { +public: + SwappedContext(std::function code, void_pfn_smxprocess_t cleanup_func, smx_actor_t process) + : Context(std::move(code), cleanup_func, process) + { + } + virtual void suspend(); + virtual void resume(); + + static void run_all(); + + virtual void swap_into(SwappedContext* to) = 0; + + static SwappedContext* get_maestro() { return maestro_context_; } + static void set_maestro(SwappedContext* maestro) { maestro_context_ = maestro; } + +private: + static unsigned long process_index_; + static SwappedContext* maestro_context_; +}; + +} // namespace context +} // namespace kernel +} // namespace simgrid +#endif diff --git a/src/kernel/context/ContextUnix.cpp b/src/kernel/context/ContextUnix.cpp index e2641444c2..ba2bce922a 100644 --- a/src/kernel/context/ContextUnix.cpp +++ b/src/kernel/context/ContextUnix.cpp @@ -11,6 +11,7 @@ #include "simgrid/Exception.hpp" #include "src/mc/mc_ignore.hpp" #include "src/simix/ActorImpl.hpp" +#include "src/simix/smx_private.hpp" #include "ContextUnix.hpp" @@ -48,7 +49,7 @@ Context* UContextFactory::create_context(std::function code, void_pfn_sm if (parallel_) return new_context(std::move(code), cleanup, process); else - return new_context(std::move(code), cleanup, process); + return new_context(std::move(code), cleanup, process); } /* This function is called by maestro at the beginning of a scheduling round to get all working threads executing some @@ -60,15 +61,13 @@ void UContextFactory::run_all() if (parallel_) ParallelUContext::run_all(); else - SerialUContext::run_all(); + SwappedContext::run_all(); } // UContext -UContext* UContext::maestro_context_ = nullptr; - UContext::UContext(std::function code, void_pfn_smxprocess_t cleanup_func, smx_actor_t process) - : Context(std::move(code), cleanup_func, process) + : SwappedContext(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()) { @@ -84,8 +83,8 @@ UContext::UContext(std::function code, void_pfn_smxprocess_t cleanup_fun #endif UContext::make_ctx(&this->uc_, UContext::smx_ctx_sysv_wrapper, this); } else { - if (process != nullptr && maestro_context_ == nullptr) - maestro_context_ = this; + if (process != nullptr && get_maestro() == nullptr) + set_maestro(this); } #if SIMGRID_HAVE_MC @@ -135,12 +134,13 @@ void UContext::make_ctx(ucontext_t* ucp, void (*func)(int, int), UContext* arg) makecontext(ucp, (void (*)())func, 2, ctx_addr[0], ctx_addr[1]); } -inline void UContext::swap(UContext* from, UContext* to) +void UContext::swap_into(SwappedContext* to_) { + UContext* to = static_cast(to_); ASAN_ONLY(void* fake_stack = nullptr); ASAN_ONLY(to->asan_ctx_ = from); ASAN_START_SWITCH(from->asan_stop_ ? nullptr : &fake_stack, to->asan_stack_, to->asan_stack_size_); - swapcontext(&from->uc_, &to->uc_); + swapcontext(&this->uc_, &to->uc_); ASAN_FINISH_SWITCH(fake_stack, &from->asan_ctx_->asan_stack_, &from->asan_ctx_->asan_stack_size_); } @@ -150,45 +150,6 @@ void UContext::stop() throw StopRequest(); } -// SerialUContext - -unsigned long SerialUContext::process_index_; /* index of the next process to run in the list of runnable processes */ - -void SerialUContext::suspend() -{ - /* determine the next context */ - SerialUContext* 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_); - } else { - /* all processes were run, return to maestro */ - XBT_DEBUG("No more process to run"); - next_context = static_cast(UContext::get_maestro()); - } - Context::set_current(next_context); - UContext::swap(this, next_context); -} - -void SerialUContext::resume() -{ - Context::set_current(this); - UContext::swap(UContext::get_maestro(), this); -} - -void SerialUContext::run_all() -{ - if (simix_global->process_to_run.empty()) - return; - smx_actor_t first_process = simix_global->process_to_run.front(); - process_index_ = 1; - static_cast(first_process->context_)->resume(); -} - // ParallelUContext simgrid::xbt::Parmap* ParallelUContext::parmap_; @@ -257,7 +218,7 @@ void ParallelUContext::suspend() Context::set_current(next_context); // Get the next soul to run, either simulated or initial minion's one: - UContext::swap(this, next_context); + this->swap_into(next_context); } /** Run one particular simulated process on the current thread. */ @@ -272,7 +233,7 @@ void ParallelUContext::resume() // Write in simix that I switched my soul Context::set_current(this); // Actually do that using the relevant library call: - UContext::swap(worker_context, this); + worker_context->swap_into(this); // No body runs that soul anymore at this point. Instead the current body took the soul of simulated process The // simulated process wakes back after the call to "SIMIX_context_suspend(self->context);" within // smx_process.c::SIMIX_process_yield() diff --git a/src/kernel/context/ContextUnix.hpp b/src/kernel/context/ContextUnix.hpp index 71f8999249..e295305be0 100644 --- a/src/kernel/context/ContextUnix.hpp +++ b/src/kernel/context/ContextUnix.hpp @@ -17,27 +17,22 @@ #include #include -#include "Context.hpp" #include "src/internal_config.h" -#include "src/simix/smx_private.hpp" +#include "src/kernel/context/ContextSwapped.hpp" namespace simgrid { namespace kernel { namespace context { -class UContext : public Context { +class UContext : public SwappedContext { public: UContext(std::function code, void_pfn_smxprocess_t cleanup_func, smx_actor_t process); ~UContext() override; void stop() override; - virtual void resume() = 0; - static void swap(UContext* from, UContext* to); - static UContext* get_maestro() { return maestro_context_; } - static void set_maestro(UContext* maestro) { maestro_context_ = maestro; } + void swap_into(SwappedContext* to) override; private: - static UContext* maestro_context_; void* stack_ = nullptr; /* the thread stack */ ucontext_t uc_; /* the ucontext that executes the code */ @@ -52,21 +47,6 @@ private: static void make_ctx(ucontext_t* ucp, void (*func)(int, int), UContext* arg); }; -class SerialUContext : public UContext { -public: - SerialUContext(std::function code, void_pfn_smxprocess_t cleanup_func, smx_actor_t process) - : UContext(std::move(code), cleanup_func, process) - { - } - void suspend() override; - void resume() override; - - static void run_all(); - -private: - static unsigned long process_index_; -}; - class ParallelUContext : public UContext { public: ParallelUContext(std::function code, void_pfn_smxprocess_t cleanup_func, smx_actor_t process) diff --git a/tools/cmake/DefinePackages.cmake b/tools/cmake/DefinePackages.cmake index 85040bb72c..050a0820e5 100644 --- a/tools/cmake/DefinePackages.cmake +++ b/tools/cmake/DefinePackages.cmake @@ -383,6 +383,8 @@ set(SIMIX_SRC src/kernel/context/Context.hpp src/kernel/context/ContextRaw.cpp src/kernel/context/ContextRaw.hpp + src/kernel/context/ContextSwapped.cpp + src/kernel/context/ContextSwapped.hpp src/kernel/context/ContextThread.cpp src/kernel/context/ContextThread.hpp src/simix/smx_deployment.cpp -- 2.20.1