From: mquinson Date: Thu, 9 Dec 2010 11:16:21 +0000 (+0000) Subject: draft of hardcore ultra brutal manual context switching (TBC after lunch) X-Git-Tag: v3.6_beta2~819 X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/commitdiff_plain/8991ed0684cc383d92a815959d85e2d05995d9d2 draft of hardcore ultra brutal manual context switching (TBC after lunch) git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/simgrid/simgrid/trunk@9104 48e7efb5-ca39-0410-a469-dd3cf9ba447f --- diff --git a/buildtools/Cmake/DefinePackages.cmake b/buildtools/Cmake/DefinePackages.cmake index 4f44d6263c..197126ecde 100644 --- a/buildtools/Cmake/DefinePackages.cmake +++ b/buildtools/Cmake/DefinePackages.cmake @@ -215,6 +215,7 @@ set(SIMIX_SRC src/simix/smx_context_base.c src/simix/smx_user.c src/simix/smx_smurf.c + src/simix/smx_context_raw.c src/replay/replay.h src/replay/replay.c src/replay/state_machine_context.c diff --git a/src/simix/private.h b/src/simix/private.h index ff1d66f3d1..ccbec1e1e4 100644 --- a/src/simix/private.h +++ b/src/simix/private.h @@ -155,6 +155,7 @@ void SIMIX_context_mod_exit(void); /* All factories init */ void SIMIX_ctx_thread_factory_init(smx_context_factory_t *factory); void SIMIX_ctx_sysv_factory_init(smx_context_factory_t *factory); +void SIMIX_ctx_raw_factory_init(smx_context_factory_t *factory); /* ****************************** */ /* context manipulation functions */ diff --git a/src/simix/smx_context_raw.c b/src/simix/smx_context_raw.c new file mode 100644 index 0000000000..c67ea319f2 --- /dev/null +++ b/src/simix/smx_context_raw.c @@ -0,0 +1,209 @@ +/* context_raw - context switching with ucontextes from System V */ + +/* Copyright (c) 2009, 2010. The SimGrid Team. + * All rights reserved. */ + +/* 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 "xbt/threadpool.h" +#include "simix/private.h" + +#ifdef HAVE_VALGRIND_VALGRIND_H +# include +#endif /* HAVE_VALGRIND_VALGRIND_H */ + +#ifdef _XBT_WIN32 +#include "win32_ucontext.h" +#include "win32_ucontext.c" +#else +#include "ucontext.h" +#endif + +/* lower this if you want to reduce the memory consumption */ +#ifndef CONTEXT_STACK_SIZE /* allow lua to override this */ +#define CONTEXT_STACK_SIZE 128*1024 +#endif /*CONTEXT_STACK_SIZE */ + + +typedef char * raw_stack_t; + +typedef struct s_smx_ctx_raw { + s_smx_ctx_base_t super; /* Fields of super implementation */ + char *malloced_stack; /* malloced area containing the stack */ + raw_stack_t stack_top; /* pointer to stack top (within previous area) */ +#ifdef HAVE_VALGRIND_VALGRIND_H + unsigned int valgrind_stack_id; /* the valgrind stack id */ +#endif +} s_smx_ctx_raw_t, *smx_ctx_raw_t; + +smx_ctx_raw_t maestro_context; + +static inline __attribute__((regparm(2))) void raw_swapcontext(raw_stack_t*old, raw_stack_t*new) { + __asm__ __volatile__ ( + "ret" + ); +} +typedef void (*rawctx_entry_point_t)(void *); +static inline raw_stack_t raw_makecontext(char*malloced_stack, int stack_size, + rawctx_entry_point_t entry_point, void *arg) { + __asm__ __volatile__ ( + "popl %ebx" + ); + return NULL; +} +XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix_context); + +static xbt_tpool_t tpool; + +static void smx_ctx_raw_wrapper(smx_ctx_raw_t context); + + +static int smx_ctx_raw_factory_finalize(smx_context_factory_t *factory) +{ + if(tpool) + xbt_tpool_destroy(tpool); + return smx_ctx_base_factory_finalize(factory); +} + +static smx_context_t +smx_ctx_raw_create_context_sized(size_t size, xbt_main_func_t code, + int argc, char **argv, + void_pfn_smxprocess_t cleanup_func, + void *data) +{ + + smx_ctx_raw_t context = + (smx_ctx_raw_t) smx_ctx_base_factory_create_context_sized(size, + code, + argc, + argv, + cleanup_func, + data); + + /* If the user provided a function for the process then use it + otherwise is the context for maestro */ + if (code) { + context->malloced_stack = xbt_malloc0(CONTEXT_STACK_SIZE); + context->stack_top = + raw_makecontext(context->malloced_stack,CONTEXT_STACK_SIZE, + (void(*)(void*))smx_ctx_raw_wrapper,context); + +#ifdef HAVE_VALGRIND_VALGRIND_H + context->valgrind_stack_id = + VALGRIND_STACK_REGISTER(context->malloced_stack, + context->malloced_stack + CONTEXT_STACK_SIZE); +#endif /* HAVE_VALGRIND_VALGRIND_H */ + + }else{ + maestro_context = context; + } + + return (smx_context_t) context; + +} + +static smx_context_t +smx_ctx_raw_create_context(xbt_main_func_t code, int argc, char **argv, + void_pfn_smxprocess_t cleanup_func, + void *data) +{ + + return smx_ctx_raw_create_context_sized(sizeof(s_smx_ctx_raw_t), + code, argc, argv, cleanup_func, + data); + +} + +static void smx_ctx_raw_free(smx_context_t context) +{ + + if (context) { + +#ifdef HAVE_VALGRIND_VALGRIND_H + VALGRIND_STACK_DEREGISTER(((smx_ctx_raw_t) + context)->valgrind_stack_id); +#endif /* HAVE_VALGRIND_VALGRIND_H */ + + } + smx_ctx_base_free(context); +} + +static void smx_ctx_raw_suspend(smx_context_t context) +{ + smx_current_context = (smx_context_t)maestro_context; + raw_swapcontext(&((smx_ctx_raw_t) context)->stack_top, &maestro_context->stack_top); +} + +static void smx_ctx_raw_stop(smx_context_t context) +{ + smx_ctx_base_stop(context); + smx_ctx_raw_suspend(context); +} + +static void smx_ctx_raw_wrapper(smx_ctx_raw_t context) +{ + (context->super.code) (context->super.argc, context->super.argv); + + smx_ctx_raw_stop((smx_context_t) context); +} + +static void smx_ctx_raw_resume(smx_context_t context) +{ + smx_current_context = context; + raw_swapcontext(&maestro_context->stack_top, &((smx_ctx_raw_t) context)->stack_top); +} + +static void smx_ctx_raw_runall(xbt_swag_t processes) +{ + smx_process_t process; + + while ((process = xbt_swag_extract(processes))) + smx_ctx_raw_resume(process->context); +} + +static void smx_ctx_raw_resume_parallel(smx_context_t context) +{ + xbt_os_thread_set_extra_data(context); + raw_swapcontext(&maestro_context->stack_top, &((smx_ctx_raw_t) context)->stack_top); +} + +static void smx_ctx_raw_runall_parallel(xbt_swag_t processes) +{ + smx_process_t process; + while((process = xbt_swag_extract(processes))){ + xbt_tpool_queue_job(tpool, (void_f_pvoid_t)smx_ctx_raw_resume_parallel, process->context); + } + xbt_tpool_wait_all(tpool); +} + +static smx_context_t smx_ctx_raw_self_parallel(void) +{ + smx_context_t self_context = (smx_context_t) xbt_os_thread_get_extra_data(); + return self_context ? self_context : (smx_context_t) maestro_context; +} + +void SIMIX_ctx_raw_factory_init(smx_context_factory_t *factory) +{ + smx_ctx_base_factory_init(factory); + + (*factory)->finalize = smx_ctx_raw_factory_finalize; + (*factory)->create_context = smx_ctx_raw_create_context; + /* Do not overload that method (*factory)->finalize */ + (*factory)->free = smx_ctx_raw_free; + (*factory)->stop = smx_ctx_raw_stop; + (*factory)->suspend = smx_ctx_raw_suspend; + (*factory)->name = "smx_raw_context_factory"; + + if(_surf_parallel_contexts){ +#ifdef CONTEXT_THREADS /* To use parallel ucontexts a thread pool is needed */ + tpool = xbt_tpool_new(2, 10); + (*factory)->runall = smx_ctx_raw_runall_parallel; + (*factory)->self = smx_ctx_raw_self_parallel; +#else + THROW0(arg_error, 0, "No thread support for parallel context execution"); +#endif + }else{ + (*factory)->runall = smx_ctx_raw_runall; + } +}