X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/ee6ffc12bf5523e4d2d2193138c791d991ec0ae4..38e2adf74c9fccec6487e953bcb6895b72786dc1:/src/simix/UContext.cpp diff --git a/src/simix/UContext.cpp b/src/simix/UContext.cpp index a5e8e8f564..8852c73597 100644 --- a/src/simix/UContext.cpp +++ b/src/simix/UContext.cpp @@ -8,19 +8,15 @@ #include +#include +#include /* context relative declarations */ + #include "xbt/parmap.h" -#include "smx_private.h" -#include "smx_private.hpp" +#include "src/simix/smx_private.h" +#include "src/simix/smx_private.hpp" #include "src/internal_config.h" -#include "src/context_sysv_config.h" /* loads context system definitions */ #include "mc/mc.h" -#ifdef _XBT_WIN32 -# include /* context relative declarations */ -#else -# include /* context relative declarations */ -#endif - /** Many integers are needed to store a pointer * * This is a bit paranoid about sizeof(smx_ctx_sysv_t) not being a multiple @@ -34,8 +30,7 @@ * Makecontext expects integer arguments, we the context * variable is decomposed into a serie of integers and * each integer is passed as argument to makecontext. */ -XBT_PRIVATE -void simgrid_makecontext(ucontext* ucp, void (*func)(int first, ...), void* arg) +static void simgrid_makecontext(ucontext_t* ucp, void (*func)(int first, ...), void* arg) { int ctx_addr[CTX_ADDR_LEN]; memcpy(ctx_addr, &arg, sizeof(void*)); @@ -47,8 +42,7 @@ void simgrid_makecontext(ucontext* ucp, void (*func)(int first, ...), void* arg) makecontext(ucp, (void (*)()) func, 2, ctx_addr[0], ctx_addr[1]); break; default: - xbt_die("Ucontexts are not supported on this arch yet (addr len = %zu/%zu = %zu)", - sizeof(void*), sizeof(int), CTX_ADDR_LEN); + xbt_die("Ucontexts are not supported on this arch yet (addr len = %zu/%zu = %zu)", sizeof(void*), sizeof(int), CTX_ADDR_LEN); } } @@ -63,10 +57,10 @@ namespace simix { } } -#ifdef CONTEXT_THREADS +#if HAVE_THREAD_CONTEXTS static xbt_parmap_t sysv_parmap; static simgrid::simix::ParallelUContext** sysv_workers_context; /* space to save the worker's context in each thread */ -static unsigned long sysv_threads_working; /* number of threads that have started their work */ +static uintptr_t sysv_threads_working; /* number of threads that have started their work */ static xbt_os_thread_key_t sysv_worker_id_key; /* thread-specific storage for the thread id */ #endif static unsigned long sysv_process_index = 0; /* index of the next process to run in the @@ -74,6 +68,10 @@ static unsigned long sysv_process_index = 0; /* index of the next process to r static simgrid::simix::UContext* sysv_maestro_context; static bool sysv_parallel; +// The name of this function is currently hardcoded in the code (as string). +// Do not change it without fixing those references as well. +static void smx_ctx_sysv_wrapper(int first, ...); + namespace simgrid { namespace simix { @@ -83,22 +81,16 @@ protected: char *stack_ = nullptr; /* the thread stack */ public: friend UContextFactory; - UContext(xbt_main_func_t code, - int argc, char **argv, - void_pfn_smxprocess_t cleanup_func, - smx_process_t process); + UContext(std::function code, + void_pfn_smxprocess_t cleanup_func, smx_process_t process); ~UContext(); -protected: - static void wrapper(int first, ...); }; class SerialUContext : public UContext { public: - SerialUContext(xbt_main_func_t code, - int argc, char **argv, - void_pfn_smxprocess_t cleanup_func, - smx_process_t process) - : UContext(code, argc, argv, cleanup_func, process) + SerialUContext(std::function code, + void_pfn_smxprocess_t cleanup_func, smx_process_t process) + : UContext(std::move(code), cleanup_func, process) {} void stop() override; void suspend() override; @@ -107,11 +99,9 @@ public: class ParallelUContext : public UContext { public: - ParallelUContext(xbt_main_func_t code, - int argc, char **argv, - void_pfn_smxprocess_t cleanup_func, - smx_process_t process) - : UContext(code, argc, argv, cleanup_func, process) + ParallelUContext(std::function code, + void_pfn_smxprocess_t cleanup_func, smx_process_t process) + : UContext(std::move(code), cleanup_func, process) {} void stop() override; void suspend() override; @@ -126,10 +116,8 @@ public: UContextFactory(); virtual ~UContextFactory(); - virtual Context* create_context( - xbt_main_func_t, int, char **, void_pfn_smxprocess_t, - smx_process_t process - ) override; + virtual Context* create_context(std::function code, + void_pfn_smxprocess_t, smx_process_t process) override; void run_all() override; }; @@ -143,7 +131,7 @@ UContextFactory::UContextFactory() : ContextFactory("UContextFactory") { if (SIMIX_context_is_parallel()) { sysv_parallel = true; -#ifdef CONTEXT_THREADS /* To use parallel ucontexts a thread pool is needed */ +#if HAVE_THREAD_CONTEXTS /* To use parallel ucontexts a thread pool is needed */ int nthreads = SIMIX_context_get_nthreads(); sysv_parmap = nullptr; sysv_workers_context = xbt_new(ParallelUContext*, nthreads); @@ -159,7 +147,7 @@ UContextFactory::UContextFactory() : ContextFactory("UContextFactory") UContextFactory::~UContextFactory() { -#ifdef CONTEXT_THREADS +#if HAVE_THREAD_CONTEXTS if (sysv_parmap) xbt_parmap_destroy(sysv_parmap); xbt_free(sysv_workers_context); @@ -173,7 +161,7 @@ UContextFactory::~UContextFactory() void UContextFactory::run_all() { if (sysv_parallel) { - #ifdef CONTEXT_THREADS + #if HAVE_THREAD_CONTEXTS sysv_threads_working = 0; // Parmap_apply ensures that every working thread get an index in the // process_to_run array (through an atomic fetch_and_add), @@ -207,43 +195,35 @@ void UContextFactory::run_all() } } -Context* UContextFactory::create_context( - xbt_main_func_t code, int argc, char ** argv, - void_pfn_smxprocess_t cleanup, - smx_process_t process - ) +Context* UContextFactory::create_context(std::function code, + void_pfn_smxprocess_t cleanup, smx_process_t process) { if (sysv_parallel) - return new_context(code, argc, argv, cleanup, process); + return new_context(std::move(code), cleanup, process); else - return new_context(code, argc, argv, cleanup, process); + return new_context(std::move(code), cleanup, process); } -UContext::UContext(xbt_main_func_t code, - int argc, char **argv, - void_pfn_smxprocess_t cleanup_func, - smx_process_t process) - : Context(code, argc, argv, cleanup_func, process) +UContext::UContext(std::function code, + void_pfn_smxprocess_t cleanup_func, smx_process_t process) + : Context(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 (code) { + /* if the user provided a function for the process then use it, otherwise it is the context for maestro */ + if (has_code()) { this->stack_ = (char*) SIMIX_context_stack_new(); getcontext(&this->uc_); this->uc_.uc_link = nullptr; - this->uc_.uc_stack.ss_sp = pth_skaddr_makecontext( - this->stack_, smx_context_usable_stack_size); - this->uc_.uc_stack.ss_size = pth_sksize_makecontext( - this->stack_, smx_context_usable_stack_size); - simgrid_makecontext(&this->uc_, UContext::wrapper, this); + this->uc_.uc_stack.ss_sp = sg_makecontext_stack_addr(this->stack_); + this->uc_.uc_stack.ss_size = sg_makecontext_stack_size(smx_context_usable_stack_size); + simgrid_makecontext(&this->uc_, smx_ctx_sysv_wrapper, this); } else { if (process != NULL && sysv_maestro_context == NULL) sysv_maestro_context = this; } -#ifdef HAVE_MC - if (MC_is_active() && code) { - MC_register_stack_area(this->stack_, context->process, +#if HAVE_MC + if (MC_is_active() && has_code()) { + MC_register_stack_area(this->stack_, process, &(this->uc_), smx_context_usable_stack_size); } #endif @@ -254,11 +234,14 @@ UContext::~UContext() SIMIX_context_stack_delete(this->stack_); } -void UContext::wrapper(int first, ...) +} +} + +static void smx_ctx_sysv_wrapper(int first, ...) { // Rebuild the Context* pointer from the integers: int ctx_addr[CTX_ADDR_LEN]; - UContext* context; + simgrid::simix::UContext* context; ctx_addr[0] = first; if (CTX_ADDR_LEN > 1) { va_list ap; @@ -267,12 +250,15 @@ void UContext::wrapper(int first, ...) ctx_addr[i] = va_arg(ap, int); va_end(ap); } - memcpy(&context, ctx_addr, sizeof(UContext*)); + memcpy(&context, ctx_addr, sizeof(simgrid::simix::UContext*)); (*context)(); context->stop(); } +namespace simgrid { +namespace simix { + void SerialUContext::stop() { Context::stop(); @@ -317,9 +303,9 @@ void ParallelUContext::stop() /** Run one particular simulated process on the current thread. */ void ParallelUContext::resume() { -#ifdef CONTEXT_THREADS +#if HAVE_THREAD_CONTEXTS // What is my containing body? - unsigned long worker_id = __sync_fetch_and_add(&sysv_threads_working, 1); + uintptr_t worker_id = __sync_fetch_and_add(&sysv_threads_working, 1); // Store the number of my containing body in os-thread-specific area : xbt_os_thread_set_specific(sysv_worker_id_key, (void*) worker_id); // Get my current soul: @@ -358,7 +344,7 @@ void ParallelUContext::resume() */ void ParallelUContext::suspend() { -#ifdef CONTEXT_THREADS +#if HAVE_THREAD_CONTEXTS /* determine the next context */ // Get the next soul to embody now: smx_process_t next_work = (smx_process_t) xbt_parmap_next(sysv_parmap); @@ -376,8 +362,8 @@ void ParallelUContext::suspend() XBT_DEBUG("No more processes to run"); // Get back the identity of my body that was stored when starting // the scheduling round - unsigned long worker_id = - (unsigned long) xbt_os_thread_get_specific(sysv_worker_id_key); + uintptr_t worker_id = + (uintptr_t) xbt_os_thread_get_specific(sysv_worker_id_key); // Deduce the initial soul of that body next_context = (ParallelUContext*) sysv_workers_context[worker_id]; // When given that soul, the body will wait for the next scheduling round