*
* 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<void()>& code);
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()
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_;
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::Context> context_; /* the context (uctx/raw/thread) that executes the user function */
void set_wannadie(bool value = true) { iwannadie_ = value; }
void operator()() { code_(); }
bool has_code() const { return static_cast<bool>(code_); }
- actor::ActorImpl* get_actor() { return this->actor_; }
+ actor::ActorImpl* get_actor() const { return this->actor_; }
// Scheduling methods
virtual void stop();
#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);
BoostContext::BoostContext(std::function<void()>&& 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
}
}
RawContext::RawContext(std::function<void()>&& 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_));
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(
* 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. */
#endif
this->stack_ = this->stack_ + smx_context_guard_size;
} else {
- this->stack_ = static_cast<unsigned char*>(xbt_malloc0(smx_context_stack_size));
+ this->stack_ = static_cast<unsigned char*>(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();
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();
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<simgrid::xbt::Parmap<smx_actor_t>> parmap_{nullptr};
+ std::unique_ptr<simgrid::xbt::Parmap<actor::ActorImpl*>> parmap_{nullptr};
};
class SwappedContext : public Context {
friend void ::smx_ctx_wrapper(simgrid::kernel::context::SwappedContext*);
public:
- SwappedContext(std::function<void()>&& code, smx_actor_t get_actor, SwappedContextFactory* factory);
+ SwappedContext(std::function<void()>&& code, actor::ActorImpl* get_actor, SwappedContextFactory* factory);
SwappedContext(const SwappedContext&) = delete;
SwappedContext& operator=(const SwappedContext&) = delete;
virtual ~SwappedContext();
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;
UContext::UContext(std::function<void()>&& 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.
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<void()>& code)
{
simgrid::kernel::actor::simcall([this, &code] { pimpl_->start(code); });
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();
> [::(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