X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/7f4f03348bd07609e258eb3b545bdafc2c881847..f5acac9da28f84a6625be7afaa01fc4ec6c643e7:/src/simix/ThreadContext.cpp diff --git a/src/simix/ThreadContext.cpp b/src/simix/ThreadContext.cpp index e676dc4ef2..722ff30f60 100644 --- a/src/simix/ThreadContext.cpp +++ b/src/simix/ThreadContext.cpp @@ -9,11 +9,12 @@ #include "xbt/function_types.h" #include "smx_private.h" -#include "src/portable.h" /* loads context system definitions */ +#include "src/internal_config.h" /* loads context system definitions */ #include "xbt/swag.h" #include "xbt/xbt_os_thread.h" #include "src/xbt_modinter.h" /* prototype of os thread module's init/exit in XBT */ +#include "src/simix/smx_private.hpp" #include "src/simix/ThreadContext.hpp" XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix_context); @@ -51,35 +52,7 @@ ThreadContext* ThreadContextFactory::create_context( std::function code, void_pfn_smxprocess_t cleanup, smx_process_t process) { - return this->new_context(std::move(code), cleanup, process); -} - -ThreadContext::ThreadContext(std::function code, - void_pfn_smxprocess_t cleanup, smx_process_t process) - : Context(std::move(code), cleanup, process) -{ - /* If the user provided a function for the process then use it - otherwise is the context for maestro */ - if (has_code()) { - this->begin_ = xbt_os_sem_init(0); - this->end_ = xbt_os_sem_init(0); - if (smx_context_stack_size_was_set) - xbt_os_thread_setstacksize(smx_context_stack_size); - if (smx_context_guard_size_was_set) - xbt_os_thread_setguardsize(smx_context_guard_size); - - /* create and start the process */ - /* NOTE: The first argument to xbt_os_thread_create used to be the process * - * name, but now the name is stored at SIMIX level, so we pass a null */ - this->thread_ = - xbt_os_thread_create(NULL, ThreadContext::wrapper, this, this); - - /* wait the starting of the newly created process */ - xbt_os_sem_acquire(this->end_); - - } else { - xbt_os_thread_set_extra_data(this); - } + return this->new_context(std::move(code), cleanup, process, !code); } void ThreadContextFactory::run_all() @@ -110,17 +83,57 @@ ThreadContext* ThreadContextFactory::self() return static_cast(xbt_os_thread_get_extra_data()); } +ThreadContext* ThreadContextFactory::attach(void_pfn_smxprocess_t cleanup_func, smx_process_t process) +{ + return this->new_context( + std::function(), cleanup_func, process, false); +} + +ThreadContext* ThreadContextFactory::create_maestro(std::function code, smx_process_t process) +{ + return this->new_context(std::move(code), nullptr, process, true); +} + +ThreadContext::ThreadContext(std::function code, + void_pfn_smxprocess_t cleanup, smx_process_t process, bool maestro) + : AttachContext(std::move(code), cleanup, process) +{ + // We do not need the semaphores when maestro is in main, but we create them anyway for simplicity wrt the case where maestro is externalized + this->begin_ = xbt_os_sem_init(0); + this->end_ = xbt_os_sem_init(0); + + /* If the user provided a function for the process then use it */ + if (has_code()) { + if (smx_context_stack_size_was_set) + xbt_os_thread_setstacksize(smx_context_stack_size); + if (smx_context_guard_size_was_set) + xbt_os_thread_setguardsize(smx_context_guard_size); + + /* create and start the process */ + /* NOTE: The first argument to xbt_os_thread_create used to be the process * + * name, but now the name is stored at SIMIX level, so we pass a null */ + this->thread_ = + xbt_os_thread_create(NULL, + maestro ? ThreadContext::maestro_wrapper : ThreadContext::wrapper, + this, this); + /* wait the starting of the newly created process */ + xbt_os_sem_acquire(this->end_); + } + + /* Otherwise, we attach to the current thread */ + else { + xbt_os_thread_set_extra_data(this); + } +} + ThreadContext::~ThreadContext() { - /* check if this is the context of maestro (it doesn't have a real thread) */ - if (this->thread_) { - /* wait about the thread terminason */ + if (this->thread_) /* If there is a thread (maestro don't have any), wait for its termination */ xbt_os_thread_join(this->thread_, nullptr); - /* destroy the synchronisation objects */ - xbt_os_sem_destroy(this->begin_); - xbt_os_sem_destroy(this->end_); - } + /* destroy the synchronization objects */ + xbt_os_sem_destroy(this->begin_); + xbt_os_sem_destroy(this->end_); } void *ThreadContext::wrapper(void *param) @@ -137,15 +150,49 @@ void *ThreadContext::wrapper(void *param) #endif /* Tell the maestro we are starting, and wait for its green light */ xbt_os_sem_release(context->end_); + xbt_os_sem_acquire(context->begin_); if (smx_ctx_thread_sem) /* parallel run */ xbt_os_sem_acquire(smx_ctx_thread_sem); (*context)(); context->stop(); + return nullptr; } +void *ThreadContext::maestro_wrapper(void *param) +{ + ThreadContext* context = static_cast(param); + +#ifndef WIN32 + /* Install alternate signal stack, for SIGSEGV handler. */ + stack_t stack; + stack.ss_sp = sigsegv_stack; + stack.ss_size = sizeof sigsegv_stack; + stack.ss_flags = 0; + sigaltstack(&stack, nullptr); +#endif + /* Tell the caller we are starting */ + xbt_os_sem_release(context->end_); + + // Wait for the caller to give control back to us: + xbt_os_sem_acquire(context->begin_); + (*context)(); + + // Tell main that we have finished: + xbt_os_sem_release(context->end_); + + return nullptr; +} + +void ThreadContext::start() +{ + xbt_os_sem_acquire(this->begin_); + if (smx_ctx_thread_sem) /* parallel run */ + xbt_os_sem_acquire(smx_ctx_thread_sem); +} + void ThreadContext::stop() { Context::stop(); @@ -168,5 +215,25 @@ void ThreadContext::suspend() xbt_os_sem_acquire(smx_ctx_thread_sem); } +void ThreadContext::attach_start() +{ + // We're breaking the layers here by depending on the upper layer: + ThreadContext* maestro = (ThreadContext*) simix_global->maestro_process->context; + xbt_os_sem_release(maestro->begin_); + this->start(); +} + +void ThreadContext::attach_stop() +{ + if (smx_ctx_thread_sem) + xbt_os_sem_release(smx_ctx_thread_sem); + xbt_os_sem_release(this->end_); + + ThreadContext* maestro = (ThreadContext*) simix_global->maestro_process->context; + xbt_os_sem_acquire(maestro->end_); + + xbt_os_thread_set_extra_data(nullptr); +} + } }