X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/ee6ffc12bf5523e4d2d2193138c791d991ec0ae4..7bac600c529ba83f8f246a2dcfa9ddd9c0095675:/src/simix/ThreadContext.cpp diff --git a/src/simix/ThreadContext.cpp b/src/simix/ThreadContext.cpp index 19be3d43cd..c84dc52918 100644 --- a/src/simix/ThreadContext.cpp +++ b/src/simix/ThreadContext.cpp @@ -4,6 +4,9 @@ /* 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 +#include + #include "xbt/function_types.h" #include "smx_private.h" #include "src/portable.h" /* loads context system definitions */ @@ -11,6 +14,7 @@ #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); @@ -45,41 +49,10 @@ ThreadContextFactory::~ThreadContextFactory() } ThreadContext* ThreadContextFactory::create_context( - xbt_main_func_t code, int argc, char ** argv, - void_pfn_smxprocess_t cleanup, - smx_process_t process) + std::function code, + void_pfn_smxprocess_t cleanup, smx_process_t process) { - return this->new_context(code, argc, argv, cleanup, process); -} - -ThreadContext::ThreadContext(xbt_main_func_t code, - int argc, char **argv, - void_pfn_smxprocess_t cleanup, - smx_process_t process) - : Context(code, argc, argv, cleanup, process) -{ - /* If the user provided a function for the process then use it - otherwise is the context for maestro */ - if (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,6 +83,51 @@ 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: + // if (!(maestro && !code)) { + 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) */ @@ -137,15 +155,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 +220,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); +} + } }