X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/4c809a6e671dd2d46724fd05644020a7084b880d..11819220e15518f0aacff177da8655da0a9f9826:/src/xbt/context.c diff --git a/src/xbt/context.c b/src/xbt/context.c index c96a2cde82..c732042694 100644 --- a/src/xbt/context.c +++ b/src/xbt/context.c @@ -13,6 +13,17 @@ #include "context_private.h" #include "xbt/log.h" #include "xbt/dynar.h" +#include "xbt/xbt_thread.h" +/*#include */ /* I need pthread_join that is not yet available in xbt_thread.*/ + +#ifdef CONTEXT_THREADS + /* This file (context.c) is only loaded in libsimgrid, not libgras. + * xbt_thread is only loaded in libgras explicitly, and we need it in + * libsimgrid, but only when it is the backend used to implement the + * xbt_context. So, do load it on need. + */ +#include "xbt/xbt_thread.c" +#endif XBT_LOG_NEW_DEFAULT_SUBCATEGORY(xbt_ctx, xbt, "Context"); @@ -22,56 +33,33 @@ static xbt_context_t current_context = NULL; static xbt_context_t init_context = NULL; static xbt_swag_t context_to_destroy = NULL; static xbt_swag_t context_living = NULL; +static xbt_mutex_t creation_mutex; +static xbt_thcond_t creation_cond; -#if (!defined(USE_PTHREADS) && !defined(USE_WIN_THREADS)) /* USE_PTHREADS and USE_CONTEXT are exclusive */ -# ifndef USE_UCONTEXT -/* don't want to play with conditional compilation in automake tonight, sorry. - include directly the c file from here when needed. */ -# include "context_win32.c" -# define USE_WIN_CONTEXT -# endif -#endif - +static void __context_exit(xbt_context_t context ,int value); static void __xbt_context_yield(xbt_context_t context) { xbt_assert0(current_context,"You have to call context_init() first."); - + DEBUG2("--------- current_context (%p) is yielding to context(%p) ---------",current_context,context); - - #ifdef USE_PTHREADS + + #ifdef CONTEXT_THREADS if (context){ xbt_context_t self = current_context; - DEBUG0("**** Locking ****"); - pthread_mutex_lock(&(context->mutex)); - DEBUG0("**** Updating current_context ****"); + DEBUG1("[%p] **** Locking ****", self); + xbt_mutex_lock(context->mutex); + DEBUG1("[%p] **** Updating current_context ****", self); current_context = context; - DEBUG0("**** Releasing the prisonner ****"); - pthread_cond_signal(&(context->cond)); - DEBUG0("**** Going to jail ****"); - pthread_cond_wait(&(context->cond), &(context->mutex)); - DEBUG0("**** Unlocking ****"); - pthread_mutex_unlock(&(context->mutex)); - DEBUG0("**** Updating current_context ****"); + DEBUG1("[%p] **** Releasing the prisonner ****", self); + xbt_thcond_signal(context->cond); + DEBUG1("[%p] **** Going to jail ****", self); + xbt_thcond_wait(context->cond, context->mutex); + DEBUG1("[%p] **** Unlocking ****", self); + xbt_mutex_unlock(context->mutex); + DEBUG1("[%p] **** Updating current_context ****", self); current_context = self; } - #elif defined(USE_WIN_THREADS) - if (context){ - xbt_context_t self = current_context; - DEBUG0("**** Locking ****"); - win_thread_mutex_lock(&(context->mutex)); - DEBUG0("**** Updating current_context ****"); - current_context = context; - DEBUG0("**** Releasing the prisonner ****"); - win_thread_cond_signal(&(context->cond)); - DEBUG0("**** Going to jail ****"); - win_thread_cond_wait(&(context->cond), &(context->mutex)); - DEBUG0("**** Unlocking ****"); - win_thread_mutex_unlock(&(context->mutex)); - DEBUG0("**** Updating current_context ****"); - current_context = self; - - } - #else + #else /* use SUSv2 contexts */ if(current_context) VOIRP(current_context->save); @@ -86,7 +74,7 @@ static void __xbt_context_yield(xbt_context_t context) if(context->save==NULL){ - DEBUG0("**** Yielding to somebody else ****"); + DEBUG1("[%p] **** Yielding to somebody else ****", current_context); DEBUG2("Saving current_context value (%p) to context(%p)->save",current_context,context); context->save = current_context ; DEBUG1("current_context becomes context(%p) ",context); @@ -97,7 +85,7 @@ static void __xbt_context_yield(xbt_context_t context) DEBUG1("I am (%p). Coming back\n",context); } else { xbt_context_t old_context = context->save ; - DEBUG0("**** Back ! ****"); + DEBUG1("[%p] **** Back ! ****", context); DEBUG2("Setting current_context (%p) to context(%p)->save",current_context,context); current_context = context->save ; DEBUG1("Setting context(%p)->save to NULL",context); @@ -110,36 +98,36 @@ static void __xbt_context_yield(xbt_context_t context) } } #endif + if(current_context->iwannadie) + __context_exit(current_context, 1); + return; } -static void xbt_context_destroy(xbt_context_t context) +static void xbt_context_free(xbt_context_t context) { - #ifdef USE_PTHREADS + if (!context) return; + DEBUG1("Freeing %p",context); +#ifdef CONTEXT_THREADS + /*DEBUG1("\t joining %p",(void *)context->thread->t);*/ + DEBUG1("\t joining %p",(void *)context->thread); + /*pthread_join(context->thread->t,NULL);*/ + xbt_thread_join(context->thread,NULL); + DEBUG1("\t xbt_free %p",(void *)context->thread); xbt_free(context->thread); - pthread_mutex_destroy(&(context->mutex)); - pthread_cond_destroy(&(context->cond)); - #elif defined(USE_WIN_THREADS) - /*xbt_free(context->thread);*/ - - if(context->mutex) - win_thread_mutex_destroy(&(context->mutex)); - - - if(context->cond) - win_thread_cond_destroy(&(context->cond)); - - - #endif + DEBUG1("\t mutex_destroy %p",(void *)context->mutex); + xbt_mutex_destroy(context->mutex); + DEBUG1("\t cond_destroy %p",(void *)context->cond); + xbt_thcond_destroy(context->cond); + + context->thread = NULL; + context->mutex = NULL; + context->cond = NULL; +#endif if(context->exception) free(context->exception); - - #ifdef USE_WIN_CONTEXT - if(context->uc.uc_stack.ss_sp) - free (context->uc.uc_stack.ss_sp); - #endif - + free(context); return; } @@ -147,6 +135,15 @@ static void xbt_context_destroy(xbt_context_t context) static void __context_exit(xbt_context_t context ,int value) { int i; + + DEBUG1("--------- %p is exiting ---------",context); + + DEBUG0("Calling cleanup functions"); + if(context->cleanup_func){ + DEBUG0("Calling cleanup function"); + context->cleanup_func(context->cleanup_arg); + } + DEBUG0("Freeing arguments"); for(i=0;iargc; i++) if(context->argv[i]) @@ -154,81 +151,52 @@ static void __context_exit(xbt_context_t context ,int value) if(context->argv) free(context->argv); - - if(context->cleanup_func){ - DEBUG0("Calling cleanup function"); - context->cleanup_func(context->cleanup_arg); - } - + DEBUG0("Putting context in the to_destroy set"); xbt_swag_remove(context, context_living); xbt_swag_insert(context, context_to_destroy); DEBUG0("Context put in the to_destroy set"); + DEBUG0("Yielding"); - #ifdef USE_PTHREADS - DEBUG0("**** Locking ****"); - pthread_mutex_lock(&(context->mutex)); - DEBUG0("**** Updating current_context ****"); - current_context = context; - DEBUG0("**** Releasing the prisonner ****"); - pthread_cond_signal(&(context->cond)); - DEBUG0("**** Unlocking ****"); - pthread_mutex_unlock(&(context->mutex)); - DEBUG0("**** Exiting ****"); - pthread_exit(0); - #elif defined(USE_WIN_THREADS) - DEBUG0("**** Locking ****"); - win_thread_mutex_lock(&(context->mutex)); - DEBUG0("**** Updating current_context ****"); - current_context = context; - DEBUG0("**** Releasing the prisonner ****"); - win_thread_cond_signal(&(context->cond)); - DEBUG0("**** Unlocking ****"); - win_thread_mutex_unlock(&(context->mutex)); - DEBUG0("**** Exiting ****"); - win_thread_exit(context->thread,0); + #ifdef CONTEXT_THREADS + DEBUG1("[%p] **** Locking ****", context); + xbt_mutex_lock(context->mutex); +/* DEBUG1("[%p] **** Updating current_context ****"); */ +/* current_context = context; */ + DEBUG1("[%p] **** Releasing the prisonner ****", context); + xbt_thcond_signal(context->cond); + DEBUG1("[%p] **** Unlocking ****", context); + xbt_mutex_unlock(context->mutex); + DEBUG1("[%p] **** Exiting ****", context); + xbt_thread_exit(NULL); // We should provide return value in case other wants it #else __xbt_context_yield(context); #endif xbt_assert0(0,"You can't be here!"); } -#ifdef USE_WIN_THREADS -static DWORD WINAPI /* special thread proc signature */ -#else static void * -#endif -__context_wrapper(void* c) -{ +__context_wrapper(void* c) { xbt_context_t context = (xbt_context_t)c; - #ifdef USE_PTHREADS - DEBUG2("**[%p:%p]** Lock ****",context,(void*)pthread_self()); - pthread_mutex_lock(&(context->mutex)); + #ifdef CONTEXT_THREADS + context->thread = xbt_thread_self(); + + DEBUG2("**[%p:%p]** Lock ****",context,(void*)xbt_thread_self()); + xbt_mutex_lock(creation_mutex); - DEBUG2("**[%p:%p]** Releasing the prisonner ****",context,(void*)pthread_self()); - pthread_cond_signal(&(context->cond)); + DEBUG2("**[%p:%p]** Releasing the creator ****",context,(void*)xbt_thread_self()); + xbt_thcond_signal(creation_cond); + xbt_mutex_unlock(creation_mutex); - DEBUG2("**[%p:%p]** Going to Jail ****",context,(void*)pthread_self()); - pthread_cond_wait(&(context->cond), &(context->mutex)); + DEBUG2("**[%p:%p]** Going to Jail ****",context,(void*)xbt_thread_self()); + xbt_mutex_lock(context->mutex); + xbt_thcond_wait(context->cond, context->mutex); - DEBUG2("**[%p:%p]** Unlocking ****",context,(void*)pthread_self()); - pthread_mutex_unlock(&(context->mutex)); + DEBUG2("**[%p:%p]** Unlocking ****",context,(void*)xbt_thread_self()); + xbt_mutex_unlock(context->mutex); - #elif defined(USE_WIN_THREADS) - DEBUG2("**[%p:%p]** Lock ****",context,(void*)win_thread_self()); - win_thread_mutex_lock(&(context->mutex)); - - DEBUG2("**[%p:%p]** Releasing the prisonner ****",context,(void*)win_thread_self()); - win_thread_cond_signal(&(context->cond)); - - DEBUG2("**[%p:%p]** Going to Jail ****",context,(void*)win_thread_self()); - win_thread_cond_wait(&(context->cond), &(context->mutex)); - - DEBUG2("**[%p:%p]** Unlocking ****",context,(void*)win_thread_self()); - win_thread_mutex_unlock(&(context->mutex)); - #endif if(context->startup_func) @@ -271,12 +239,8 @@ void xbt_context_init(void) { if(!current_context){ current_context = init_context = xbt_new0(s_xbt_context_t,1); - - /*#ifdef USE_WIN_THREADS - win_thread_mutex_init(&(current_context->mutex)); - win_thread_cond_init(&(current_context->cond)); - #endif*/ - + DEBUG1("Init Context (%p)",init_context); + init_context->exception = xbt_new(ex_ctx_t,1); XBT_CTX_INITIALIZE(init_context->exception); __xbt_ex_ctx = __context_ex_ctx; @@ -284,6 +248,10 @@ void xbt_context_init(void) context_to_destroy = xbt_swag_new(xbt_swag_offset(*current_context,hookup)); context_living = xbt_swag_new(xbt_swag_offset(*current_context,hookup)); xbt_swag_insert(init_context, context_living); +#ifdef CONTEXT_THREADS + creation_mutex = xbt_mutex_init(); + creation_cond = xbt_thcond_init(); +#endif } } @@ -295,9 +263,10 @@ void xbt_context_init(void) void xbt_context_empty_trash(void) { xbt_context_t context=NULL; - + DEBUG1("Emptying trashbin (%d contexts to free)", + xbt_swag_size(context_to_destroy)); while((context=xbt_swag_extract(context_to_destroy))) - xbt_context_destroy(context); + xbt_context_free(context); } /** @@ -308,28 +277,19 @@ void xbt_context_empty_trash(void) */ void xbt_context_start(xbt_context_t context) { - #ifdef USE_PTHREADS + #ifdef CONTEXT_THREADS /* Launch the thread */ DEBUG1("**[%p]** Locking ****",context); - pthread_mutex_lock(&(context->mutex)); - DEBUG1("**[%p]** Pthread create ****",context); - xbt_assert0(!pthread_create(context->thread, NULL, __context_wrapper, context),"Unable to create a thread."); - DEBUG2("**[%p]** Pthread created : %p ****",context,(void*)(*(context->thread))); + xbt_mutex_lock(creation_mutex); + + DEBUG1("**[%p]** Thread create ****",context); + context->thread = xbt_thread_create(__context_wrapper, context); + DEBUG2("**[%p]** Thread created : %p ****",context,context->thread); + DEBUG1("**[%p]** Going to jail ****",context); - pthread_cond_wait(&(context->cond), &(context->mutex)); + xbt_thcond_wait(creation_cond, creation_mutex); DEBUG1("**[%p]** Unlocking ****",context); - pthread_mutex_unlock(&(context->mutex)); - #elif defined(USE_WIN_THREADS) - /* Launch the thread */ - DEBUG1("**[%p]** Locking ****",context); - win_thread_mutex_lock(&(context->mutex)); - DEBUG1("**[%p]** Windows thread create ****",context); - xbt_assert0(!win_thread_create(&(context->thread), __context_wrapper, context),"Unable to create a thread."); - DEBUG2("**[%p]** Windows created : %p ****",context,(void*)(context->thread)); - DEBUG1("**[%p]** Going to jail ****",context); - win_thread_cond_wait(&(context->cond), &(context->mutex)); - DEBUG1("**[%p]** Unlocking ****",context); - win_thread_mutex_unlock(&(context->mutex)); + xbt_mutex_unlock(creation_mutex); #else makecontext (&(context->uc), (void (*) (void)) __context_wrapper,1, context); #endif @@ -357,30 +317,20 @@ xbt_context_t xbt_context_new(xbt_context_function_t code, res = xbt_new0(s_xbt_context_t,1); res->code = code; - #ifdef USE_PTHREADS - res->thread = xbt_new0(pthread_t,1); - xbt_assert0(!pthread_mutex_init(&(res->mutex), NULL), "Mutex initialization error"); - xbt_assert0(!pthread_cond_init(&(res->cond), NULL), "Condition initialization error"); - #elif defined(USE_WIN_THREADS) - /*res->thread = xbt_new0(pthread_t,1);*/ - xbt_assert0(!win_thread_mutex_init(&(res->mutex)), "Mutex initialization error"); - xbt_assert0(!win_thread_cond_init(&(res->cond)), "Condition initialization error"); + #ifdef CONTEXT_THREADS + res->mutex = xbt_mutex_init(); + res->cond = xbt_thcond_init(); #else - /* FIXME: strerror is not thread safe */ + xbt_assert2(getcontext(&(res->uc))==0,"Error in context saving: %d (%s)", errno, strerror(errno)); res->uc.uc_link = NULL; /* res->uc.uc_link = &(current_context->uc); */ /* WARNING : when this context is over, the current_context (i.e. the father), is awaken... Theorically, the wrapper should prevent using this feature. */ - # ifdef USE_WIN_CONTEXT - res->uc.uc_stack.ss_sp = xbt_malloc(STACK_SIZE); - res->uc.uc_stack.ss_size = STACK_SIZE ; - #else res->uc.uc_stack.ss_sp = pth_skaddr_makecontext(res->stack,STACK_SIZE); res->uc.uc_stack.ss_size = pth_sksize_makecontext(res->stack,STACK_SIZE); - # endif /* USE_WIN_CONTEXT */ - #endif /* USE_PTHREADS or not */ + #endif /* CONTEXT_THREADS or not */ res->argc = argc; res->argv = argv; @@ -426,21 +376,24 @@ void xbt_context_schedule(xbt_context_t context) */ void xbt_context_exit(void) { xbt_context_t context=NULL; - - /*#ifdef USE_WIN_THREADS - win_thread_mutex_destroy(&(current_context->mutex)); - win_thread_cond_destroy(&(current_context->cond)); - #endif*/ + + xbt_context_empty_trash(); + while((context=xbt_swag_extract(context_living))) { + if(context!=init_context) { + xbt_context_kill(context); + } + } + // xbt_context_kill(init_context); xbt_context_empty_trash(); xbt_swag_free(context_to_destroy); - - while((context=xbt_swag_extract(context_living))) - xbt_context_free(context); - xbt_swag_free(context_living); init_context = current_context = NULL ; +#ifdef CONTEXT_THREADS + xbt_mutex_destroy(creation_mutex); + xbt_thcond_destroy(creation_cond); +#endif } /** @@ -448,23 +401,14 @@ void xbt_context_exit(void) { * * This function simply kills \a context... scarry isn't it ? */ -void xbt_context_free(xbt_context_t context) +void xbt_context_kill(xbt_context_t context) { - int i ; - - xbt_swag_remove(context, context_living); - - for(i=0;iargc; i++) - if(context->argv[i]) - free(context->argv[i]); - - if(context->argv) - free(context->argv); - - if(context->cleanup_func) - context->cleanup_func(context->cleanup_arg); - - xbt_context_destroy(context); + DEBUG1("Killing %p", context); + + context->iwannadie=1; + DEBUG1("Scheduling %p",context); + __xbt_context_yield(context); + DEBUG1("End of Scheduling %p",context); return; }