From: Martin Quinson Date: Thu, 5 Mar 2020 09:03:59 +0000 (+0100) Subject: allow to specify the stack size on a per-actor basis X-Git-Tag: v3.26~814 X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/commitdiff_plain/7f9bfecfa8f78da52f5451934dcd209acfa94787 allow to specify the stack size on a per-actor basis --- diff --git a/include/simgrid/s4u/Actor.hpp b/include/simgrid/s4u/Actor.hpp index a040274ba0..6d8ef155f4 100644 --- a/include/simgrid/s4u/Actor.hpp +++ b/include/simgrid/s4u/Actor.hpp @@ -107,6 +107,7 @@ public: * * This is usefull to set some properties or extension before actually starting it */ static ActorPtr init(const std::string& name, s4u::Host* host); + ActorPtr set_stacksize(unsigned stacksize); /** Start a previously initialized actor */ ActorPtr start(const std::function& code); diff --git a/src/kernel/actor/ActorImpl.cpp b/src/kernel/actor/ActorImpl.cpp index b890a8e789..7c801dfc21 100644 --- a/src/kernel/actor/ActorImpl.cpp +++ b/src/kernel/actor/ActorImpl.cpp @@ -54,8 +54,9 @@ ActorImpl* ActorImpl::self() ActorImpl::ActorImpl(xbt::string name, s4u::Host* host) : host_(host), name_(std::move(name)), piface_(this) { - pid_ = maxpid++; + pid_ = maxpid++; simcall.issuer_ = this; + stacksize_ = smx_context_stack_size; } ActorImpl::~ActorImpl() diff --git a/src/kernel/actor/ActorImpl.hpp b/src/kernel/actor/ActorImpl.hpp index bbbcd60d3e..1efe8da6b0 100644 --- a/src/kernel/actor/ActorImpl.hpp +++ b/src/kernel/actor/ActorImpl.hpp @@ -27,6 +27,7 @@ class XBT_PUBLIC ActorImpl : public xbt::PropertyHolder { aid_t ppid_ = -1; bool daemon_ = false; /* Daemon actors are automatically killed when the last non-daemon leaves */ bool auto_restart_ = false; + unsigned stacksize_; // set to default value in constructor public: xbt::string name_; @@ -58,6 +59,8 @@ public: bool is_daemon() { return daemon_; } /** Whether this actor has been daemonized */ bool has_to_auto_restart() { return auto_restart_; } void set_auto_restart(bool autorestart) { auto_restart_ = autorestart; } + void set_stacksize(unsigned stacksize) { stacksize_ = stacksize; } + unsigned get_stacksize() { return stacksize_; } std::unique_ptr context_; /* the context (uctx/raw/thread) that executes the user function */ diff --git a/src/kernel/context/Context.hpp b/src/kernel/context/Context.hpp index 84dc1081ff..813856f1ef 100644 --- a/src/kernel/context/Context.hpp +++ b/src/kernel/context/Context.hpp @@ -58,7 +58,7 @@ public: void set_wannadie(bool value = true) { iwannadie_ = value; } void operator()() { code_(); } bool has_code() const { return static_cast(code_); } - actor::ActorImpl* get_actor() { return this->actor_; } + actor::ActorImpl* get_actor() const { return this->actor_; } // Scheduling methods virtual void stop(); diff --git a/src/kernel/context/ContextBoost.cpp b/src/kernel/context/ContextBoost.cpp index ae9ade0c56..f7d76cbc31 100644 --- a/src/kernel/context/ContextBoost.cpp +++ b/src/kernel/context/ContextBoost.cpp @@ -5,6 +5,7 @@ #include "ContextBoost.hpp" #include "simgrid/Exception.hpp" +#include "src/internal_config.h" #include "src/simix/smx_private.hpp" XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix_context); @@ -24,14 +25,14 @@ BoostContext* BoostContextFactory::create_context(std::function&& code, BoostContext::BoostContext(std::function&& code, actor::ActorImpl* actor, SwappedContextFactory* factory) : SwappedContext(std::move(code), actor, factory) { - XBT_VERB("Creating a context of stack %uMb", smx_context_stack_size / 1024 / 1024); + XBT_VERB("Creating a context of stack %uMb", actor->get_stacksize() / 1024 / 1024); /* if the user provided a function for the process then use it, otherwise it is the context for maestro */ if (has_code()) { #if BOOST_VERSION < 106100 - this->fc_ = boost::context::make_fcontext(get_stack_bottom(), smx_context_stack_size, BoostContext::wrapper); + this->fc_ = boost::context::make_fcontext(get_stack_bottom(), actor->get_stacksize(), BoostContext::wrapper); #else this->fc_ = - boost::context::detail::make_fcontext(get_stack_bottom(), smx_context_stack_size, BoostContext::wrapper); + boost::context::detail::make_fcontext(get_stack_bottom(), actor->get_stacksize(), BoostContext::wrapper); #endif } } diff --git a/src/kernel/context/ContextRaw.cpp b/src/kernel/context/ContextRaw.cpp index 4cc658a0cf..3b36adaa82 100644 --- a/src/kernel/context/ContextRaw.cpp +++ b/src/kernel/context/ContextRaw.cpp @@ -197,9 +197,9 @@ RawContext* RawContextFactory::create_context(std::function&& code, acto RawContext::RawContext(std::function&& code, actor::ActorImpl* actor, SwappedContextFactory* factory) : SwappedContext(std::move(code), actor, factory) { - XBT_VERB("Creating a context of stack %uMb", smx_context_stack_size / 1024 / 1024); + XBT_VERB("Creating a context of stack %uMb", actor->get_stacksize() / 1024 / 1024); if (has_code()) { - this->stack_top_ = raw_makecontext(get_stack(), smx_context_stack_size, smx_ctx_wrapper, this); + this->stack_top_ = raw_makecontext(get_stack(), actor->get_stacksize(), smx_ctx_wrapper, this); } else { if (MC_is_active()) MC_ignore_heap(&stack_top_, sizeof(stack_top_)); diff --git a/src/kernel/context/ContextSwapped.cpp b/src/kernel/context/ContextSwapped.cpp index d64dac46d4..7b25012c58 100644 --- a/src/kernel/context/ContextSwapped.cpp +++ b/src/kernel/context/ContextSwapped.cpp @@ -74,7 +74,7 @@ SwappedContext::SwappedContext(std::function&& code, smx_actor_t actor, 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 PTH_STACKGROWTH != -1 xbt_die( @@ -85,7 +85,7 @@ 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. */ @@ -116,12 +116,12 @@ 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 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(); @@ -167,6 +167,12 @@ SwappedContext::~SwappedContext() xbt_free(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 + return PTH_STACKGROWTH == -1 ? stack_ + get_actor()->get_stacksize() : stack_; +} + void SwappedContext::stop() { Context::stop(); diff --git a/src/kernel/context/ContextSwapped.hpp b/src/kernel/context/ContextSwapped.hpp index 1b815aa3f4..414416d41f 100644 --- a/src/kernel/context/ContextSwapped.hpp +++ b/src/kernel/context/ContextSwapped.hpp @@ -40,14 +40,14 @@ private: SwappedContext* maestro_context_ = nullptr; // save maestro's context /* For the parallel execution, will be created lazily with the right parameters if needed (ie, in parallel) */ - std::unique_ptr> parmap_{nullptr}; + std::unique_ptr> parmap_{nullptr}; }; class SwappedContext : public Context { friend void ::smx_ctx_wrapper(simgrid::kernel::context::SwappedContext*); public: - SwappedContext(std::function&& code, smx_actor_t get_actor, SwappedContextFactory* factory); + SwappedContext(std::function&& code, actor::ActorImpl* get_actor, SwappedContextFactory* factory); SwappedContext(const SwappedContext&) = delete; SwappedContext& operator=(const SwappedContext&) = delete; virtual ~SwappedContext(); @@ -58,12 +58,11 @@ public: void swap_into(SwappedContext* to); +protected: unsigned char* get_stack() const { return stack_; } - // Return the address for the bottom of the stack. Depending on the stack direction it may be the lower or higher - // address - unsigned char* get_stack_bottom() const { return PTH_STACKGROWTH == -1 ? stack_ + smx_context_stack_size : stack_; } + unsigned char* get_stack_bottom() const; // Depending on the stack direction, its bottom (that Boost::make_fcontext + // needs) may be the lower or higher end -protected: // With ASan, after a context switch, check that the originating context is the expected one (see BoostContext) void verify_previous_context(const SwappedContext* context) const; diff --git a/src/kernel/context/ContextUnix.cpp b/src/kernel/context/ContextUnix.cpp index 6e2ebe54c3..28a62b9a3a 100644 --- a/src/kernel/context/ContextUnix.cpp +++ b/src/kernel/context/ContextUnix.cpp @@ -49,13 +49,13 @@ UContext* UContextFactory::create_context(std::function&& code, actor::A UContext::UContext(std::function&& code, actor::ActorImpl* actor, SwappedContextFactory* factory) : SwappedContext(std::move(code), actor, factory) { - XBT_VERB("Creating a context of stack %uMb", smx_context_stack_size / 1024 / 1024); + XBT_VERB("Creating a context of stack %uMb", actor->get_stacksize() / 1024 / 1024); /* if the user provided a function for the actor then use it. If not, nothing to do for maestro. */ if (has_code()) { getcontext(&this->uc_); this->uc_.uc_link = nullptr; this->uc_.uc_stack.ss_sp = sg_makecontext_stack_addr(get_stack()); - this->uc_.uc_stack.ss_size = sg_makecontext_stack_size(smx_context_stack_size); + this->uc_.uc_stack.ss_size = sg_makecontext_stack_size(actor->get_stacksize()); // Makecontext expects integer arguments; we want to pass a pointer. // This context address is decomposed into a series of integers, which are passed as arguments to makecontext. diff --git a/src/s4u/s4u_Actor.cpp b/src/s4u/s4u_Actor.cpp index 0ca43d2bda..b963779456 100644 --- a/src/s4u/s4u_Actor.cpp +++ b/src/s4u/s4u_Actor.cpp @@ -56,6 +56,15 @@ ActorPtr Actor::init(const std::string& name, s4u::Host* host) return actor->iface(); } +/** Set a non-default stack size for this context (in Kb) + * + * This must be done before starting the actor, and it won't work with the thread factory. */ +ActorPtr Actor::set_stacksize(unsigned stacksize) +{ + pimpl_->set_stacksize(stacksize * 1024); + return this; +} + ActorPtr Actor::start(const std::function& code) { simgrid::kernel::actor::simcall([this, &code] { pimpl_->start(code); }); diff --git a/teshsuite/kernel/context-stacksize/context-stacksize.cpp b/teshsuite/kernel/context-stacksize/context-stacksize.cpp index 49cba2e840..3d9a77e5e5 100644 --- a/teshsuite/kernel/context-stacksize/context-stacksize.cpp +++ b/teshsuite/kernel/context-stacksize/context-stacksize.cpp @@ -19,12 +19,22 @@ int main(int argc, char* argv[]) simgrid::s4u::Engine e(&argc, argv); e.load_platform(argv[1]); + // If you don't specify anything, you get the default size (8Mb) or the one passed on the command line simgrid::s4u::Actor::create("actor", simgrid::s4u::Host::by_name("Tremblay"), actor); + + // You can use set_config(string) to pass a size that will be parsed. That value will be used for any subsequent + // actors e.set_config("contexts/stack-size:16384"); simgrid::s4u::Actor::create("actor", simgrid::s4u::Host::by_name("Tremblay"), actor); + simgrid::s4u::Actor::create("actor", simgrid::s4u::Host::by_name("Tremblay"), actor); + + // You can use set_config(key, value) for the same effect. e.set_config("contexts/stack-size", 32 * 1024); simgrid::s4u::Actor::create("actor", simgrid::s4u::Host::by_name("Tremblay"), actor); - e.set_config("contexts/stack-size", 64 * 1024); + simgrid::s4u::Actor::create("actor", simgrid::s4u::Host::by_name("Tremblay"), actor); + + // Or you can use set_stacksize() before starting the actor to modify only this one + simgrid::s4u::Actor::init("actor", simgrid::s4u::Host::by_name("Tremblay"))->set_stacksize(64 * 1024)->start(actor); simgrid::s4u::Actor::create("actor", simgrid::s4u::Host::by_name("Tremblay"), actor); e.run(); diff --git a/teshsuite/kernel/context-stacksize/context-stacksize.tesh b/teshsuite/kernel/context-stacksize/context-stacksize.tesh index dd05180159..f6f564f8af 100644 --- a/teshsuite/kernel/context-stacksize/context-stacksize.tesh +++ b/teshsuite/kernel/context-stacksize/context-stacksize.tesh @@ -7,10 +7,16 @@ $ ./context-stacksize --log=simix_context.thresh:verbose --log=no_loc ${platfdir > [::(0) 0.000000] [simix_context/VERBOSE] Creating a context of stack 8Mb > [0.000000] [simix_context/VERBOSE] Creating a context of stack 8Mb > [0.000000] [simix_context/VERBOSE] Creating a context of stack 16Mb +> [0.000000] [simix_context/VERBOSE] Creating a context of stack 16Mb +> [0.000000] [simix_context/VERBOSE] Creating a context of stack 32Mb > [0.000000] [simix_context/VERBOSE] Creating a context of stack 32Mb > [0.000000] [simix_context/VERBOSE] Creating a context of stack 64Mb +> [0.000000] [simix_context/VERBOSE] Creating a context of stack 32Mb > [Tremblay:actor:(1) 0.000000] [s4u_test/INFO] Hello > [Tremblay:actor:(2) 0.000000] [s4u_test/INFO] Hello > [Tremblay:actor:(3) 0.000000] [s4u_test/INFO] Hello > [Tremblay:actor:(4) 0.000000] [s4u_test/INFO] Hello +> [Tremblay:actor:(5) 0.000000] [s4u_test/INFO] Hello +> [Tremblay:actor:(6) 0.000000] [s4u_test/INFO] Hello +> [Tremblay:actor:(7) 0.000000] [s4u_test/INFO] Hello > [0.000000] [s4u_test/INFO] Simulation time 0