From 49ee23364e64238e221aa5a06e142b24d28a7b1c Mon Sep 17 00:00:00 2001 From: mquinson Date: Tue, 27 May 2008 10:13:00 +0000 Subject: [PATCH] dos2unix + indent git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/simgrid/simgrid/trunk@5501 48e7efb5-ca39-0410-a469-dd3cf9ba447f --- src/xbt/xbt_context.c | 601 +++++++++++++++++----------------- src/xbt/xbt_context_java.c | 520 ++++++++++++++--------------- src/xbt/xbt_context_java.h | 42 ++- src/xbt/xbt_context_private.h | 229 +++++++------ src/xbt/xbt_context_sysv.c | 580 ++++++++++++++++---------------- src/xbt/xbt_context_thread.c | 600 ++++++++++++++++----------------- 6 files changed, 1259 insertions(+), 1313 deletions(-) diff --git a/src/xbt/xbt_context.c b/src/xbt/xbt_context.c index 8774486165..a1b719ee91 100644 --- a/src/xbt/xbt_context.c +++ b/src/xbt/xbt_context.c @@ -1,306 +1,295 @@ -/* a fast and simple context switching library */ - -/* Copyright (c) 2004 Arnaud Legrand. */ -/* Copyright (c) 2004, 2005 Martin Quinson. */ -/* 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 "portable.h" -#include "xbt/log.h" -#include "xbt/swag.h" -#include "xbt_context_private.h" - -/* the context associated with the current process */ -xbt_context_t current_context = NULL; - -/* the context associated with the maestro */ -xbt_context_t maestro_context = NULL; - - -/* this list contains the contexts to destroy */ -xbt_swag_t context_to_destroy = NULL; - -/* this list contains the contexts in use */ -xbt_swag_t context_living = NULL; - -/* the context factory used to create the appropriate context - * each context implementation define its own context factory - * a context factory is responsable of the creation of the context - * associated with the maestro and of all the context based on - * the selected implementation. - * - * for example, the context switch based on java thread use the - * java implementation of the context and the java factory build - * the context depending of this implementation. - */ -static xbt_context_factory_t -context_factory = NULL; - -/** - * This function is call by the xbt_init() function to initialize the context module. - */ -void -xbt_context_mod_init(void) -{ - if(!context_factory) - { - /* select context factory to use to create the context(depends of the macro definitions) */ - - #ifdef CONTEXT_THREADS - /* context switch based os thread */ - xbt_ctx_thread_factory_init(&context_factory); - #elif !defined(WIN32) - /* context switch based ucontext */ - xbt_ctx_sysv_factory_init(&context_factory); - #else - /* context switch is not allowed on Windows */ - #error ERROR [__FILE__, line __LINE__]: no context based implementation specified. - #endif - - /* maestro context specialisation (this create the maestro with the good implementation */ - (*(context_factory->create_maestro_context))(&maestro_context); - - /* the current context is the context of the maestro */ - current_context = maestro_context; - - /* the current context doesn't want to die */ - current_context->iwannadie = 0; - - /* intantiation of the lists containing the contexts to destroy and the contexts in use */ - context_to_destroy = xbt_swag_new(xbt_swag_offset(*current_context, hookup)); - context_living = xbt_swag_new(xbt_swag_offset(*current_context, hookup)); - - /* insert the current context in the list of the contexts in use */ - xbt_swag_insert(current_context, context_living); - - } -} - -/** - * This function is call by the xbt_exit() function to finalize the context module. - */ -void -xbt_context_mod_exit(void) -{ - if(context_factory) - { - xbt_context_t context = NULL; - xbt_pfn_context_factory_finalize_t finalize_factory; - - /* finalize the context factory */ - finalize_factory = context_factory->finalize; - - (*finalize_factory)(&context_factory); - - /* destroy all contexts in the list of contexts to destroy */ - xbt_context_empty_trash(); - - /* remove the context of the scheduler from the list of the contexts in use */ - xbt_swag_remove(maestro_context, context_living); - - /* - * kill all the contexts in use : - * the killed contexts are added in the list of the contexts to destroy - */ - while((context = xbt_swag_extract(context_living))) - (*(context->kill))(context); - - - /* destroy all contexts in the list of contexts to destroy */ - xbt_context_empty_trash(); - - free(maestro_context); - maestro_context = current_context = NULL; - - /* destroy the lists */ - xbt_swag_free(context_to_destroy); - xbt_swag_free(context_living); - } -} - -/*******************************/ -/* Object creation/destruction */ -/*******************************/ -/** - * \param code a main function - * \param startup_func a function to call when running the context for - * the first time and just before the main function \a code - * \param startup_arg the argument passed to the previous function (\a startup_func) - * \param cleanup_func a function to call when running the context, just after - the termination of the main function \a code - * \param cleanup_arg the argument passed to the previous function (\a cleanup_func) - * \param argc first argument of function \a code - * \param argv seconde argument of function \a code - */ -xbt_context_t -xbt_context_new(const char *name, - xbt_main_func_t code, - void_f_pvoid_t startup_func, - void *startup_arg, - void_f_pvoid_t cleanup_func, - void *cleanup_arg, int argc, char *argv[] -) -{ - /* use the appropriate context factory to create the appropriate context */ - xbt_context_t context = (*(context_factory->create_context))(name, code, startup_func, startup_arg, cleanup_func, cleanup_arg, argc, argv); - - /* add the context in the list of the contexts in use */ - xbt_swag_insert(context, context_living); - - return context; -} - -/* Scenario for the end of a context: - * - * CASE 1: death after end of function - * __context_wrapper, called by os thread, calls xbt_context_stop after user code stops - * xbt_context_stop calls user cleanup_func if any (in context settings), - * add current to trashbin - * yields back to maestro (destroy os thread on need) - * From time to time, maestro calls xbt_context_empty_trash, - * which maps xbt_context_free on the content - * xbt_context_free frees some more memory, - * joins os thread - * - * CASE 2: brutal death - * xbt_context_kill (from any context) - * set context->wannadie to 1 - * yields to the context - * the context is awaken in the middle of __yield. - * At the end of it, it checks that wannadie == 1, and call xbt_context_stop - * (same than first case afterward) - */ - - -/* Argument must be stopped first -- runs in maestro context */ -void -xbt_context_free(xbt_context_t context) -{ - (*(context->free))(context); -} - - -void -xbt_context_kill(xbt_context_t context) -{ - (*(context->kill))(context); -} - -/** - * \param context the context to start - * - * Calling this function prepares \a context to be run. It will - however run effectively only when calling #xbt_context_schedule - */ -void -xbt_context_start(xbt_context_t context) -{ - (*(context->start))(context); -} - -/** - * Calling this function makes the current context yield. The context - * that scheduled it returns from xbt_context_schedule as if nothing - * had happened. - * - * Only the processes can call this function, giving back the control - * to the maestro - */ -void -xbt_context_yield(void) -{ - (*(current_context->yield))(); -} - -/** - * \param context the winner - * - * Calling this function blocks the current context and schedule \a context. - * When \a context will call xbt_context_yield, it will return - * to this function as if nothing had happened. - * - * Only the maestro can call this function to run a given process. - */ -void -xbt_context_schedule(xbt_context_t context) -{ - (*(context->schedule))(context); -} - -void -xbt_context_stop(int exit_code) -{ - - (*(current_context->stop))(exit_code); -} - -int -xbt_context_select_factory(const char* name) -{ - /* if a factory is already instantiated (xbt_context_mod_init() was called) */ - if(NULL != context_factory) - { - /* if the desired factory is different of the current factory, call xbt_context_mod_exit() */ - if(strcmp(context_factory->name,name)) - xbt_context_mod_exit(); - else - /* the same context factory is requested return directly */ - return 0; - } - - /* get the desired factory */ - xbt_context_init_factory_by_name(&context_factory,name); - - /* maestro context specialisation */ - (*(context_factory->create_maestro_context))(&maestro_context); - - /* the current context is the context of the maestro */ - current_context = maestro_context; - - /* the current context doesn't want to die */ - current_context->iwannadie = 0; - - /* intantiation of the lists containing the contexts to destroy and the contexts in use */ - context_to_destroy = xbt_swag_new(xbt_swag_offset(*current_context, hookup)); - context_living = xbt_swag_new(xbt_swag_offset(*current_context, hookup)); - - /* insert the current context in the list of the contexts in use */ - xbt_swag_insert(current_context, context_living); - - return 0; -} - -void -xbt_context_init_factory_by_name(xbt_context_factory_t* factory, const char* name) -{ - if(!strcmp(name,"java")) - xbt_ctx_java_factory_init(factory); -#ifdef CONTEXT_THREADS - else if(!strcmp(name,"thread")) - xbt_ctx_thread_factory_init(factory); -#elif !defined(WIN32) - else if(!strcmp(name,"sysv")) - xbt_ctx_sysv_factory_init(factory); -#endif - else - THROW1(not_found_error, 0,"Factory '%s' does not exist",name); -} - -/** Garbage collection - * - * Should be called some time to time to free the memory allocated for contexts - * that have finished executing their main functions. - */ -void -xbt_context_empty_trash(void) -{ - xbt_context_t context = NULL; - - while((context = xbt_swag_extract(context_to_destroy))) - (*(context->free))(context); -} - - - +/* a fast and simple context switching library */ + +/* Copyright (c) 2004 Arnaud Legrand. */ +/* Copyright (c) 2004, 2005 Martin Quinson. */ +/* 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 "portable.h" +#include "xbt/log.h" +#include "xbt/swag.h" +#include "xbt_context_private.h" + +/* the context associated with the current process */ +xbt_context_t current_context = NULL; + +/* the context associated with the maestro */ +xbt_context_t maestro_context = NULL; + + +/* this list contains the contexts to destroy */ +xbt_swag_t context_to_destroy = NULL; + +/* this list contains the contexts in use */ +xbt_swag_t context_living = NULL; + +/* the context factory used to create the appropriate context + * each context implementation define its own context factory + * a context factory is responsable of the creation of the context + * associated with the maestro and of all the context based on + * the selected implementation. + * + * for example, the context switch based on java thread use the + * java implementation of the context and the java factory build + * the context depending of this implementation. + */ +static xbt_context_factory_t context_factory = NULL; + +/** + * This function is call by the xbt_init() function to initialize the context module. + */ +void xbt_context_mod_init(void) +{ + if (!context_factory) { + /* select context factory to use to create the context(depends of the macro definitions) */ + +#ifdef CONTEXT_THREADS + /* context switch based os thread */ + xbt_ctx_thread_factory_init(&context_factory); +#elif !defined(WIN32) + /* context switch based ucontext */ + xbt_ctx_sysv_factory_init(&context_factory); +#else + /* context switch is not allowed on Windows */ +#error ERROR [__FILE__, line __LINE__]: no context based implementation specified. +#endif + + /* maestro context specialisation (this create the maestro with the good implementation */ + (*(context_factory->create_maestro_context)) (&maestro_context); + + /* the current context is the context of the maestro */ + current_context = maestro_context; + + /* the current context doesn't want to die */ + current_context->iwannadie = 0; + + /* intantiation of the lists containing the contexts to destroy and the contexts in use */ + context_to_destroy = + xbt_swag_new(xbt_swag_offset(*current_context, hookup)); + context_living = xbt_swag_new(xbt_swag_offset(*current_context, hookup)); + + /* insert the current context in the list of the contexts in use */ + xbt_swag_insert(current_context, context_living); + + } +} + +/** + * This function is call by the xbt_exit() function to finalize the context module. + */ +void xbt_context_mod_exit(void) +{ + if (context_factory) { + xbt_context_t context = NULL; + xbt_pfn_context_factory_finalize_t finalize_factory; + + /* finalize the context factory */ + finalize_factory = context_factory->finalize; + + (*finalize_factory) (&context_factory); + + /* destroy all contexts in the list of contexts to destroy */ + xbt_context_empty_trash(); + + /* remove the context of the scheduler from the list of the contexts in use */ + xbt_swag_remove(maestro_context, context_living); + + /* + * kill all the contexts in use : + * the killed contexts are added in the list of the contexts to destroy + */ + while ((context = xbt_swag_extract(context_living))) + (*(context->kill)) (context); + + + /* destroy all contexts in the list of contexts to destroy */ + xbt_context_empty_trash(); + + free(maestro_context); + maestro_context = current_context = NULL; + + /* destroy the lists */ + xbt_swag_free(context_to_destroy); + xbt_swag_free(context_living); + } +} + +/*******************************/ +/* Object creation/destruction */ +/*******************************/ +/** + * \param code a main function + * \param startup_func a function to call when running the context for + * the first time and just before the main function \a code + * \param startup_arg the argument passed to the previous function (\a startup_func) + * \param cleanup_func a function to call when running the context, just after + the termination of the main function \a code + * \param cleanup_arg the argument passed to the previous function (\a cleanup_func) + * \param argc first argument of function \a code + * \param argv seconde argument of function \a code + */ +xbt_context_t +xbt_context_new(const char *name, + xbt_main_func_t code, + void_f_pvoid_t startup_func, + void *startup_arg, + void_f_pvoid_t cleanup_func, + void *cleanup_arg, int argc, char *argv[] + ) +{ + /* use the appropriate context factory to create the appropriate context */ + xbt_context_t context = + (*(context_factory->create_context)) (name, code, startup_func, + startup_arg, cleanup_func, + cleanup_arg, argc, argv); + + /* add the context in the list of the contexts in use */ + xbt_swag_insert(context, context_living); + + return context; +} + +/* Scenario for the end of a context: + * + * CASE 1: death after end of function + * __context_wrapper, called by os thread, calls xbt_context_stop after user code stops + * xbt_context_stop calls user cleanup_func if any (in context settings), + * add current to trashbin + * yields back to maestro (destroy os thread on need) + * From time to time, maestro calls xbt_context_empty_trash, + * which maps xbt_context_free on the content + * xbt_context_free frees some more memory, + * joins os thread + * + * CASE 2: brutal death + * xbt_context_kill (from any context) + * set context->wannadie to 1 + * yields to the context + * the context is awaken in the middle of __yield. + * At the end of it, it checks that wannadie == 1, and call xbt_context_stop + * (same than first case afterward) + */ + + +/* Argument must be stopped first -- runs in maestro context */ +void xbt_context_free(xbt_context_t context) +{ + (*(context->free)) (context); +} + + +void xbt_context_kill(xbt_context_t context) +{ + (*(context->kill)) (context); +} + +/** + * \param context the context to start + * + * Calling this function prepares \a context to be run. It will + however run effectively only when calling #xbt_context_schedule + */ +void xbt_context_start(xbt_context_t context) +{ + (*(context->start)) (context); +} + +/** + * Calling this function makes the current context yield. The context + * that scheduled it returns from xbt_context_schedule as if nothing + * had happened. + * + * Only the processes can call this function, giving back the control + * to the maestro + */ +void xbt_context_yield(void) +{ + (*(current_context->yield)) (); +} + +/** + * \param context the winner + * + * Calling this function blocks the current context and schedule \a context. + * When \a context will call xbt_context_yield, it will return + * to this function as if nothing had happened. + * + * Only the maestro can call this function to run a given process. + */ +void xbt_context_schedule(xbt_context_t context) +{ + (*(context->schedule)) (context); +} + +void xbt_context_stop(int exit_code) +{ + + (*(current_context->stop)) (exit_code); +} + +int xbt_context_select_factory(const char *name) +{ + /* if a factory is already instantiated (xbt_context_mod_init() was called) */ + if (NULL != context_factory) { + /* if the desired factory is different of the current factory, call xbt_context_mod_exit() */ + if (strcmp(context_factory->name, name)) + xbt_context_mod_exit(); + else + /* the same context factory is requested return directly */ + return 0; + } + + /* get the desired factory */ + xbt_context_init_factory_by_name(&context_factory, name); + + /* maestro context specialisation */ + (*(context_factory->create_maestro_context)) (&maestro_context); + + /* the current context is the context of the maestro */ + current_context = maestro_context; + + /* the current context doesn't want to die */ + current_context->iwannadie = 0; + + /* intantiation of the lists containing the contexts to destroy and the contexts in use */ + context_to_destroy = + xbt_swag_new(xbt_swag_offset(*current_context, hookup)); + context_living = xbt_swag_new(xbt_swag_offset(*current_context, hookup)); + + /* insert the current context in the list of the contexts in use */ + xbt_swag_insert(current_context, context_living); + + return 0; +} + +void +xbt_context_init_factory_by_name(xbt_context_factory_t * factory, + const char *name) +{ + if (!strcmp(name, "java")) + xbt_ctx_java_factory_init(factory); +#ifdef CONTEXT_THREADS + else if (!strcmp(name, "thread")) + xbt_ctx_thread_factory_init(factory); +#elif !defined(WIN32) + else if (!strcmp(name, "sysv")) + xbt_ctx_sysv_factory_init(factory); +#endif + else + THROW1(not_found_error, 0, "Factory '%s' does not exist", name); +} + +/** Garbage collection + * + * Should be called some time to time to free the memory allocated for contexts + * that have finished executing their main functions. + */ +void xbt_context_empty_trash(void) +{ + xbt_context_t context = NULL; + + while ((context = xbt_swag_extract(context_to_destroy))) + (*(context->free)) (context); +} diff --git a/src/xbt/xbt_context_java.c b/src/xbt/xbt_context_java.c index 156fba3c41..7089548102 100644 --- a/src/xbt/xbt_context_java.c +++ b/src/xbt/xbt_context_java.c @@ -1,270 +1,250 @@ - - -#include "xbt/function_types.h" -#include "xbt/ex_interface.h" -#include "xbt/xbt_context_private.h" -#include "xbt/xbt_context_java.h" - -XBT_LOG_NEW_DEFAULT_CATEGORY(jmsg,"MSG for Java(TM)"); - -/* callback: context fetching */ -static ex_ctx_t* -xbt_ctx_java_ex_ctx(void); - -/* callback: termination */ -static void -xbt_ctx_java_ex_terminate(xbt_ex_t *e); - -static xbt_context_t -xbt_ctx_java_factory_create_context(const char* name, xbt_main_func_t code, void_f_pvoid_t startup_func, void* startup_arg, void_f_pvoid_t cleanup_func, void* cleanup_arg, int argc, char** argv); - -static int -xbt_ctx_java_factory_create_maestro_context(xbt_context_t* maestro); - -static int -xbt_ctx_java_factory_finalize(xbt_context_factory_t* factory); - -static void -xbt_ctx_java_free(xbt_context_t context); - -static void -xbt_ctx_java_kill(xbt_context_t context); - -static void -xbt_ctx_java_schedule(xbt_context_t context); - -static void -xbt_ctx_java_yield(void); - -static void -xbt_ctx_java_start(xbt_context_t context); - -static void -xbt_ctx_java_stop(int exit_code); - -static void -xbt_ctx_java_swap(xbt_context_t context); - -static void -xbt_ctx_java_schedule(xbt_context_t context); - -static void -xbt_ctx_java_yield(void); - -static void -xbt_ctx_java_suspend(xbt_context_t context); - -static void -xbt_ctx_java_resume(xbt_context_t context); - - -/* callback: context fetching */ -static ex_ctx_t* -xbt_ctx_java_ex_ctx(void) -{ - return current_context->exception; -} - -/* callback: termination */ -static void -xbt_ctx_java_ex_terminate(xbt_ex_t *e) -{ - xbt_ex_display(e); - abort(); -} - -void -xbt_ctx_java_factory_init(xbt_context_factory_t* factory) -{ - /* context exception handlers */ - __xbt_ex_ctx = xbt_ctx_java_ex_ctx; - __xbt_ex_terminate = xbt_ctx_java_ex_terminate; - - /* instantiate the context factory */ - *factory = xbt_new0(s_xbt_context_factory_t,1); - - (*factory)->create_context = xbt_ctx_java_factory_create_context; - (*factory)->finalize = xbt_ctx_java_factory_finalize; - (*factory)->create_maestro_context = xbt_ctx_java_factory_create_maestro_context; - (*factory)->name = "ctx_java_factory"; -} - -static int -xbt_ctx_java_factory_create_maestro_context(xbt_context_t* maestro) -{ - xbt_ctx_java_t context = xbt_new0(s_xbt_ctx_java_t, 1); - - context->exception = xbt_new(ex_ctx_t,1); - XBT_CTX_INITIALIZE(context->exception); - - *maestro = (xbt_context_t)context; - - return 0; -} - -static int -xbt_ctx_java_factory_finalize(xbt_context_factory_t* factory) -{ - free(maestro_context->exception); - free(*factory); - *factory = NULL; - - return 0; -} - -static xbt_context_t -xbt_ctx_java_factory_create_context(const char* name, xbt_main_func_t code, void_f_pvoid_t startup_func, void* startup_arg, void_f_pvoid_t cleanup_func, void* cleanup_arg, int argc, char** argv) -{ - xbt_ctx_java_t context = xbt_new0(s_xbt_ctx_java_t,1); - - context->name = xbt_strdup(name); - - context->cleanup_func = cleanup_func; - context->cleanup_arg = cleanup_arg; - - context->exception = xbt_new(ex_ctx_t,1); - XBT_CTX_INITIALIZE(context->exception); - - context->free = xbt_ctx_java_free; - context->kill = xbt_ctx_java_kill; - context->schedule = xbt_ctx_java_schedule; - context->yield = xbt_ctx_java_yield; - context->start = xbt_ctx_java_start; - context->stop = xbt_ctx_java_stop; - context->jprocess = (jobject)startup_arg; - context->jenv = get_current_thread_env(); - - return (xbt_context_t)context; -} - -static void -xbt_ctx_java_free(xbt_context_t context) -{ - if(context) - { - xbt_ctx_java_t ctx_java = (xbt_ctx_java_t)context; - - free(ctx_java->name); - - if(ctx_java->jprocess) - { - jobject jprocess = ctx_java->jprocess; - ctx_java->jprocess = NULL; - - /* if the java process is alive join it */ - if(jprocess_is_alive(jprocess,get_current_thread_env())) - jprocess_join(jprocess,get_current_thread_env()); - } - - if(ctx_java->exception) - free(ctx_java->exception); - - free(context); - context = NULL; - } -} - -static void -xbt_ctx_java_kill(xbt_context_t context) -{ - context->iwannadie = 1; - xbt_ctx_java_swap(context); -} - -/** - * \param context the winner - * - * Calling this function blocks the current context and schedule \a context. - * When \a context will call xbt_context_yield, it will return - * to this function as if nothing had happened. - * - * Only the maestro can call this function to run a given process. - */ -static void -xbt_ctx_java_schedule(xbt_context_t context) -{ - xbt_assert0((current_context == maestro_context),"You are not supposed to run this function here!"); - xbt_ctx_java_swap(context); -} - -/** - * Calling this function makes the current context yield. The context - * that scheduled it returns from xbt_context_schedule as if nothing - * had happened. - * - * Only the processes can call this function, giving back the control - * to the maestro - */ -static void -xbt_ctx_java_yield(void) -{ - xbt_assert0((current_context != maestro_context),"You are not supposed to run this function here!"); - jprocess_unschedule(current_context); -} - -static void -xbt_ctx_java_start(xbt_context_t context) -{ - jprocess_start(((xbt_ctx_java_t)context)->jprocess,get_current_thread_env()); -} - -static void -xbt_ctx_java_stop(int exit_code) -{ - jobject jprocess = NULL; - xbt_ctx_java_t ctx_java; - - if(current_context->cleanup_func) - (*(current_context->cleanup_func))(current_context->cleanup_arg); - - xbt_swag_remove(current_context, context_living); - xbt_swag_insert(current_context, context_to_destroy); - - ctx_java = (xbt_ctx_java_t)current_context; - - if(ctx_java->iwannadie) - { - /* The maestro call xbt_context_stop() with an exit code set to one */ - if(ctx_java->jprocess) - { - /* if the java process is alive schedule it */ - if(jprocess_is_alive(ctx_java->jprocess,get_current_thread_env())) - { - jprocess_schedule(current_context); - jprocess = ctx_java->jprocess; - ctx_java->jprocess = NULL; - - /* interrupt the java process */ - jprocess_exit(jprocess,get_current_thread_env()); - - } - } - } - else - { - /* the java process exits */ - jprocess = ctx_java->jprocess; - ctx_java->jprocess = NULL; - } - - /* delete the global reference associated with the java process */ - jprocess_delete_global_ref(jprocess,get_current_thread_env()); -} - -static void -xbt_ctx_java_swap(xbt_context_t context) -{ - if(context) - { - xbt_context_t self = current_context; - - current_context = context; - - jprocess_schedule(context); - - current_context = self; - } - - if(current_context->iwannadie) - xbt_ctx_java_stop(1); -} + + +#include "xbt/function_types.h" +#include "xbt/ex_interface.h" +#include "xbt/xbt_context_private.h" +#include "xbt/xbt_context_java.h" + +XBT_LOG_NEW_DEFAULT_CATEGORY(jmsg, "MSG for Java(TM)"); + +/* callback: context fetching */ +static ex_ctx_t *xbt_ctx_java_ex_ctx(void); + +/* callback: termination */ +static void xbt_ctx_java_ex_terminate(xbt_ex_t * e); + +static xbt_context_t +xbt_ctx_java_factory_create_context(const char *name, xbt_main_func_t code, + void_f_pvoid_t startup_func, + void *startup_arg, + void_f_pvoid_t cleanup_func, + void *cleanup_arg, int argc, char **argv); + +static int +xbt_ctx_java_factory_create_maestro_context(xbt_context_t * maestro); + +static int xbt_ctx_java_factory_finalize(xbt_context_factory_t * factory); + +static void xbt_ctx_java_free(xbt_context_t context); + +static void xbt_ctx_java_kill(xbt_context_t context); + +static void xbt_ctx_java_schedule(xbt_context_t context); + +static void xbt_ctx_java_yield(void); + +static void xbt_ctx_java_start(xbt_context_t context); + +static void xbt_ctx_java_stop(int exit_code); + +static void xbt_ctx_java_swap(xbt_context_t context); + +static void xbt_ctx_java_schedule(xbt_context_t context); + +static void xbt_ctx_java_yield(void); + +static void xbt_ctx_java_suspend(xbt_context_t context); + +static void xbt_ctx_java_resume(xbt_context_t context); + + +/* callback: context fetching */ +static ex_ctx_t *xbt_ctx_java_ex_ctx(void) +{ + return current_context->exception; +} + +/* callback: termination */ +static void xbt_ctx_java_ex_terminate(xbt_ex_t * e) +{ + xbt_ex_display(e); + abort(); +} + +void xbt_ctx_java_factory_init(xbt_context_factory_t * factory) +{ + /* context exception handlers */ + __xbt_ex_ctx = xbt_ctx_java_ex_ctx; + __xbt_ex_terminate = xbt_ctx_java_ex_terminate; + + /* instantiate the context factory */ + *factory = xbt_new0(s_xbt_context_factory_t, 1); + + (*factory)->create_context = xbt_ctx_java_factory_create_context; + (*factory)->finalize = xbt_ctx_java_factory_finalize; + (*factory)->create_maestro_context = + xbt_ctx_java_factory_create_maestro_context; + (*factory)->name = "ctx_java_factory"; +} + +static int +xbt_ctx_java_factory_create_maestro_context(xbt_context_t * maestro) +{ + xbt_ctx_java_t context = xbt_new0(s_xbt_ctx_java_t, 1); + + context->exception = xbt_new(ex_ctx_t, 1); + XBT_CTX_INITIALIZE(context->exception); + + *maestro = (xbt_context_t) context; + + return 0; +} + +static int xbt_ctx_java_factory_finalize(xbt_context_factory_t * factory) +{ + free(maestro_context->exception); + free(*factory); + *factory = NULL; + + return 0; +} + +static xbt_context_t +xbt_ctx_java_factory_create_context(const char *name, xbt_main_func_t code, + void_f_pvoid_t startup_func, + void *startup_arg, + void_f_pvoid_t cleanup_func, + void *cleanup_arg, int argc, char **argv) +{ + xbt_ctx_java_t context = xbt_new0(s_xbt_ctx_java_t, 1); + + context->name = xbt_strdup(name); + + context->cleanup_func = cleanup_func; + context->cleanup_arg = cleanup_arg; + + context->exception = xbt_new(ex_ctx_t, 1); + XBT_CTX_INITIALIZE(context->exception); + + context->free = xbt_ctx_java_free; + context->kill = xbt_ctx_java_kill; + context->schedule = xbt_ctx_java_schedule; + context->yield = xbt_ctx_java_yield; + context->start = xbt_ctx_java_start; + context->stop = xbt_ctx_java_stop; + context->jprocess = (jobject) startup_arg; + context->jenv = get_current_thread_env(); + + return (xbt_context_t) context; +} + +static void xbt_ctx_java_free(xbt_context_t context) +{ + if (context) { + xbt_ctx_java_t ctx_java = (xbt_ctx_java_t) context; + + free(ctx_java->name); + + if (ctx_java->jprocess) { + jobject jprocess = ctx_java->jprocess; + + ctx_java->jprocess = NULL; + + /* if the java process is alive join it */ + if (jprocess_is_alive(jprocess, get_current_thread_env())) + jprocess_join(jprocess, get_current_thread_env()); + } + + if (ctx_java->exception) + free(ctx_java->exception); + + free(context); + context = NULL; + } +} + +static void xbt_ctx_java_kill(xbt_context_t context) +{ + context->iwannadie = 1; + xbt_ctx_java_swap(context); +} + +/** + * \param context the winner + * + * Calling this function blocks the current context and schedule \a context. + * When \a context will call xbt_context_yield, it will return + * to this function as if nothing had happened. + * + * Only the maestro can call this function to run a given process. + */ +static void xbt_ctx_java_schedule(xbt_context_t context) +{ + xbt_assert0((current_context == maestro_context), + "You are not supposed to run this function here!"); + xbt_ctx_java_swap(context); +} + +/** + * Calling this function makes the current context yield. The context + * that scheduled it returns from xbt_context_schedule as if nothing + * had happened. + * + * Only the processes can call this function, giving back the control + * to the maestro + */ +static void xbt_ctx_java_yield(void) +{ + xbt_assert0((current_context != maestro_context), + "You are not supposed to run this function here!"); + jprocess_unschedule(current_context); +} + +static void xbt_ctx_java_start(xbt_context_t context) +{ + jprocess_start(((xbt_ctx_java_t) context)->jprocess, + get_current_thread_env()); +} + +static void xbt_ctx_java_stop(int exit_code) +{ + jobject jprocess = NULL; + xbt_ctx_java_t ctx_java; + + if (current_context->cleanup_func) + (*(current_context->cleanup_func)) (current_context->cleanup_arg); + + xbt_swag_remove(current_context, context_living); + xbt_swag_insert(current_context, context_to_destroy); + + ctx_java = (xbt_ctx_java_t) current_context; + + if (ctx_java->iwannadie) { + /* The maestro call xbt_context_stop() with an exit code set to one */ + if (ctx_java->jprocess) { + /* if the java process is alive schedule it */ + if (jprocess_is_alive(ctx_java->jprocess, get_current_thread_env())) { + jprocess_schedule(current_context); + jprocess = ctx_java->jprocess; + ctx_java->jprocess = NULL; + + /* interrupt the java process */ + jprocess_exit(jprocess, get_current_thread_env()); + + } + } + } else { + /* the java process exits */ + jprocess = ctx_java->jprocess; + ctx_java->jprocess = NULL; + } + + /* delete the global reference associated with the java process */ + jprocess_delete_global_ref(jprocess, get_current_thread_env()); +} + +static void xbt_ctx_java_swap(xbt_context_t context) +{ + if (context) { + xbt_context_t self = current_context; + + current_context = context; + + jprocess_schedule(context); + + current_context = self; + } + + if (current_context->iwannadie) + xbt_ctx_java_stop(1); +} diff --git a/src/xbt/xbt_context_java.h b/src/xbt/xbt_context_java.h index 9760e0430b..7c7531549f 100644 --- a/src/xbt/xbt_context_java.h +++ b/src/xbt/xbt_context_java.h @@ -1,22 +1,20 @@ -#ifndef _XBT_CONTEXT_JAVA_H -#define _XBT_CONTEXT_JAVA_H - -#include "portable.h" -#include "xbt/misc.h" - -#include "xbt/xbt_context_private.h" -#include "java/jmsg.h" -#include "java/jmsg_process.h" - -SG_BEGIN_DECL() - -typedef struct s_xbt_ctx_java -{ - XBT_CTX_BASE_T; - jobject jprocess; /* the java process instance binded with the msg process structure */ - JNIEnv* jenv; /* jni interface pointer associated to this thread */ -}s_xbt_ctx_java_t,* xbt_ctx_java_t; - -SG_END_DECL() - -#endif /* !_XBT_CONTEXT_JAVA_H */ +#ifndef _XBT_CONTEXT_JAVA_H +#define _XBT_CONTEXT_JAVA_H + +#include "portable.h" +#include "xbt/misc.h" + +#include "xbt/xbt_context_private.h" +#include "java/jmsg.h" +#include "java/jmsg_process.h" + +SG_BEGIN_DECL() + + typedef struct s_xbt_ctx_java { + XBT_CTX_BASE_T; + jobject jprocess; /* the java process instance binded with the msg process structure */ + JNIEnv *jenv; /* jni interface pointer associated to this thread */ + } s_xbt_ctx_java_t, *xbt_ctx_java_t; + +SG_END_DECL() +#endif /* !_XBT_CONTEXT_JAVA_H */ diff --git a/src/xbt/xbt_context_private.h b/src/xbt/xbt_context_private.h index 54155e98f0..d6ba31ad50 100644 --- a/src/xbt/xbt_context_private.h +++ b/src/xbt/xbt_context_private.h @@ -1,108 +1,121 @@ -#ifndef _XBT_CONTEXT_PRIVATE_H -#define _XBT_CONTEXT_PRIVATE_H - -#include "xbt/sysdep.h" -#include "xbt/context.h" -#include "xbt/swag.h" - -SG_BEGIN_DECL() - -/* *********************** */ -/* Context type definition */ -/* *********************** */ - -/* the following function pointers describe the interface that all context concepts must implement */ -typedef void (*xbt_pfn_context_free_t)(xbt_context_t); /* pointer type to the function used to destroy the specified context */ -typedef void (*xbt_pfn_context_kill_t)(xbt_context_t); /* pointer type to the function used to kill the specified context */ -typedef void (*xbt_pfn_context_schedule_t)(xbt_context_t); /* pointer type to the function used to resume the specified context */ -typedef void (*xbt_pfn_context_yield_t)(void); /* pointer type to the function used to yield the specified context */ -typedef void (*xbt_pfn_context_start_t)(xbt_context_t); /* pointer type to the function used to start the specified context */ -typedef void (*xbt_pfn_context_stop_t)(int); /* pointer type to the function used to stop the current context */ - -/* each context type must contain this macro at its begining -- OOP in C :/ */ -#define XBT_CTX_BASE_T \ - s_xbt_swag_hookup_t hookup; \ - char *name; \ - void_f_pvoid_t cleanup_func; \ - void *cleanup_arg; \ - ex_ctx_t *exception; \ - int iwannadie; \ - xbt_main_func_t code; \ - int argc; \ - char **argv; \ - void_f_pvoid_t startup_func; \ - void *startup_arg; \ - xbt_pfn_context_free_t free; \ - xbt_pfn_context_kill_t kill; \ - xbt_pfn_context_schedule_t schedule; \ - xbt_pfn_context_yield_t yield; \ - xbt_pfn_context_start_t start; \ - xbt_pfn_context_stop_t stop - -/* all other context types derive from this structure */ -typedef struct s_xbt_context { - XBT_CTX_BASE_T; -} s_xbt_context_t; - -/* ****************** */ -/* Globals definition */ -/* ****************** */ - -/* Important guys */ -extern xbt_context_t current_context; -extern xbt_context_t maestro_context; -/* All dudes lists */ -extern xbt_swag_t context_living; -extern xbt_swag_t context_to_destroy; - -/* *********************** */ -/* factory type definition */ -/* *********************** */ -typedef struct s_xbt_context_factory * xbt_context_factory_t; - -/* this function describes the interface that all context factory must implement */ -typedef xbt_context_t (*xbt_pfn_context_factory_create_context_t)(const char*, xbt_main_func_t, void_f_pvoid_t, void*, void_f_pvoid_t, void*, int, char**); -typedef int (*xbt_pfn_context_factory_create_maestro_context_t)(xbt_context_t*); - -/* this function finalize the specified context factory */ -typedef int (*xbt_pfn_context_factory_finalize_t)(xbt_context_factory_t*); - -/* this interface is used by the xbt context module to create the appropriate concept */ -typedef struct s_xbt_context_factory { - xbt_pfn_context_factory_create_maestro_context_t create_maestro_context; /* create the context of the maestro */ - xbt_pfn_context_factory_create_context_t create_context; /* create a new context */ - xbt_pfn_context_factory_finalize_t finalize; /* finalize the context factory */ - const char* name; /* the name of the context factory */ - -} s_xbt_context_factory_t; - -/** - * This function select a context factory associated with the name specified by - * the parameter name. - * If successful the function returns 0. Otherwise the function returns the error - * code. - */ -int -xbt_context_select_factory(const char* name); - -/** - * This function initialize a context factory from the name specified by the parameter - * name. - * If the factory cannot be found, an exception is raised. - */ -void -xbt_context_init_factory_by_name(xbt_context_factory_t* factory, const char* name); - - -/* All factories init */ -void xbt_ctx_thread_factory_init(xbt_context_factory_t* factory); -void xbt_ctx_sysv_factory_init(xbt_context_factory_t* factory); -void xbt_ctx_java_factory_init(xbt_context_factory_t* factory); - - - - - -SG_END_DECL() - -#endif /* !_XBT_CONTEXT_PRIVATE_H */ +#ifndef _XBT_CONTEXT_PRIVATE_H +#define _XBT_CONTEXT_PRIVATE_H + +#include "xbt/sysdep.h" +#include "xbt/context.h" +#include "xbt/swag.h" + +SG_BEGIN_DECL() + +/* *********************** */ +/* Context type definition */ +/* *********************** */ +/* the following function pointers describe the interface that all context concepts must implement */ + typedef void (*xbt_pfn_context_free_t) (xbt_context_t); /* pointer type to the function used to destroy the specified context */ + typedef void (*xbt_pfn_context_kill_t) (xbt_context_t); /* pointer type to the function used to kill the specified context */ + typedef void (*xbt_pfn_context_schedule_t) (xbt_context_t); /* pointer type to the function used to resume the specified context */ + typedef void (*xbt_pfn_context_yield_t) (void); /* pointer type to the function used to yield the specified context */ + typedef void (*xbt_pfn_context_start_t) (xbt_context_t); /* pointer type to the function used to start the specified context */ + typedef void (*xbt_pfn_context_stop_t) (int); /* pointer type to the function used to stop the current context */ + +/* each context type must contain this macro at its begining -- OOP in C :/ */ +#define XBT_CTX_BASE_T \ + s_xbt_swag_hookup_t hookup; \ + char *name; \ + void_f_pvoid_t cleanup_func; \ + void *cleanup_arg; \ + ex_ctx_t *exception; \ + int iwannadie; \ + xbt_main_func_t code; \ + int argc; \ + char **argv; \ + void_f_pvoid_t startup_func; \ + void *startup_arg; \ + xbt_pfn_context_free_t free; \ + xbt_pfn_context_kill_t kill; \ + xbt_pfn_context_schedule_t schedule; \ + xbt_pfn_context_yield_t yield; \ + xbt_pfn_context_start_t start; \ + xbt_pfn_context_stop_t stop + +/* all other context types derive from this structure */ + typedef struct s_xbt_context { + XBT_CTX_BASE_T; + } s_xbt_context_t; + +/* ****************** */ +/* Globals definition */ +/* ****************** */ + +/* Important guys */ + extern xbt_context_t current_context; + extern xbt_context_t maestro_context; + +/* All dudes lists */ + extern xbt_swag_t context_living; + extern xbt_swag_t context_to_destroy; + +/* *********************** */ +/* factory type definition */ +/* *********************** */ + typedef struct s_xbt_context_factory *xbt_context_factory_t; + +/* this function describes the interface that all context factory must implement */ + typedef xbt_context_t(*xbt_pfn_context_factory_create_context_t) (const + char *, + xbt_main_func_t, + void_f_pvoid_t, + void *, + void_f_pvoid_t, + void *, + int, + char + **); + typedef + int (*xbt_pfn_context_factory_create_maestro_context_t) (xbt_context_t + *); + +/* this function finalize the specified context factory */ + typedef int (*xbt_pfn_context_factory_finalize_t) (xbt_context_factory_t + *); + +/* this interface is used by the xbt context module to create the appropriate concept */ + typedef struct s_xbt_context_factory { + xbt_pfn_context_factory_create_maestro_context_t create_maestro_context; /* create the context of the maestro */ + xbt_pfn_context_factory_create_context_t create_context; /* create a new context */ + xbt_pfn_context_factory_finalize_t finalize; /* finalize the context factory */ + const char *name; /* the name of the context factory */ + + } s_xbt_context_factory_t; + +/** + * This function select a context factory associated with the name specified by + * the parameter name. + * If successful the function returns 0. Otherwise the function returns the error + * code. + */ + int + xbt_context_select_factory(const char *name); + +/** + * This function initialize a context factory from the name specified by the parameter + * name. + * If the factory cannot be found, an exception is raised. + */ + void + + xbt_context_init_factory_by_name(xbt_context_factory_t * factory, + const char *name); + + +/* All factories init */ + void xbt_ctx_thread_factory_init(xbt_context_factory_t * factory); + void xbt_ctx_sysv_factory_init(xbt_context_factory_t * factory); + void xbt_ctx_java_factory_init(xbt_context_factory_t * factory); + + + + + +SG_END_DECL() +#endif /* !_XBT_CONTEXT_PRIVATE_H */ diff --git a/src/xbt/xbt_context_sysv.c b/src/xbt/xbt_context_sysv.c index 2a36b6e26d..bf0558853e 100644 --- a/src/xbt/xbt_context_sysv.c +++ b/src/xbt/xbt_context_sysv.c @@ -1,298 +1,282 @@ - -#include "xbt/ex_interface.h" -#include "xbt/xbt_context_private.h" - -#include "context_sysv_config.h" /* loads context system definitions */ -#include "portable.h" -#include /* context relative declarations */ -#define STACK_SIZE 128*1024 /* lower this if you want to reduce the memory consumption */ - -typedef struct s_xbt_ctx_sysv { - XBT_CTX_BASE_T; - ucontext_t uc; /* the thread that execute the code */ - char stack[STACK_SIZE]; /* the thread stack size */ - struct s_xbt_ctx_sysv* prev;/* the previous thread */ -} s_xbt_ctx_sysv_t,* xbt_ctx_sysv_t; - - -/* callback: context fetching */ -static ex_ctx_t* -xbt_jcontext_ex_ctx(void); - -/* callback: termination */ -static void -xbt_jcontext_ex_terminate(xbt_ex_t *e); - -static xbt_context_t -xbt_ctx_sysv_factory_create_context(const char* name, xbt_main_func_t code, void_f_pvoid_t startup_func, void* startup_arg, void_f_pvoid_t cleanup_func, void* cleanup_arg, int argc, char** argv); - -static int -xbt_ctx_sysv_factory_finalize(xbt_context_factory_t* factory); - -static int -xbt_ctx_sysv_factory_create_maestro_context(xbt_context_t* maestro); - -static void -xbt_ctx_sysv_free(xbt_context_t context); - -static void -xbt_ctx_sysv_kill(xbt_context_t context); - -static void -xbt_ctx_sysv_schedule(xbt_context_t context); - -static void -xbt_ctx_sysv_yield(void); - -static void -xbt_ctx_sysv_start(xbt_context_t context); - -static void -xbt_ctx_sysv_stop(int exit_code); - -static void -xbt_ctx_sysv_swap(xbt_context_t context); - -static void -xbt_ctx_sysv_schedule(xbt_context_t context); - -static void -xbt_ctx_sysv_yield(void); - -static void -xbt_ctx_sysv_suspend(xbt_context_t context); - -static void -xbt_ctx_sysv_resume(xbt_context_t context); - -static void xbt_ctx_sysv_wrapper(void); - -/* callback: context fetching */ -static ex_ctx_t* -xbt_ctx_sysv_ex_ctx(void) -{ - return current_context->exception; -} - -/* callback: termination */ -static void -xbt_ctx_sysv_ex_terminate(xbt_ex_t *e) -{ - xbt_ex_display(e); - abort(); -} - - -void -xbt_ctx_sysv_factory_init(xbt_context_factory_t* factory) -{ - /* context exception */ - *factory = xbt_new0(s_xbt_context_factory_t,1); - - (*factory)->create_context = xbt_ctx_sysv_factory_create_context; - (*factory)->finalize = xbt_ctx_sysv_factory_finalize; - (*factory)->create_maestro_context = xbt_ctx_sysv_factory_create_maestro_context; - (*factory)->name = "ctx_sysv_context_factory"; - - /* context exception handlers */ - __xbt_ex_ctx = xbt_ctx_sysv_ex_ctx; - __xbt_ex_terminate = xbt_ctx_sysv_ex_terminate; -} - -static int -xbt_ctx_sysv_factory_create_maestro_context(xbt_context_t* maestro) -{ - - xbt_ctx_sysv_t context = xbt_new0(s_xbt_ctx_sysv_t, 1); - - context->exception = xbt_new(ex_ctx_t,1); - XBT_CTX_INITIALIZE(context->exception); - - *maestro = (xbt_context_t)context; - - return 0; - -} - - -static int -xbt_ctx_sysv_factory_finalize(xbt_context_factory_t* factory) -{ - free(maestro_context->exception); - free(*factory); - *factory = NULL; - return 0; -} - -static xbt_context_t -xbt_ctx_sysv_factory_create_context(const char* name, xbt_main_func_t code, void_f_pvoid_t startup_func, void* startup_arg, void_f_pvoid_t cleanup_func, void* cleanup_arg, int argc, char** argv) -{ - xbt_ctx_sysv_t context = xbt_new0(s_xbt_ctx_sysv_t, 1); - - context->code = code; - context->name = xbt_strdup(name); - - xbt_assert2(getcontext(&(context->uc)) == 0,"Error in context saving: %d (%s)", errno, strerror(errno)); - context->uc.uc_link = NULL; - context->uc.uc_stack.ss_sp = pth_skaddr_makecontext(context->stack, STACK_SIZE); - context->uc.uc_stack.ss_size = pth_sksize_makecontext(context->stack, STACK_SIZE); - - context->exception = xbt_new(ex_ctx_t, 1); - XBT_CTX_INITIALIZE(context->exception); - context->iwannadie = 0; /* useless but makes valgrind happy */ - context->argc = argc; - context->argv = argv; - context->startup_func = startup_func; - context->startup_arg = startup_arg; - context->cleanup_func = cleanup_func; - context->cleanup_arg = cleanup_arg; - - - context->free = xbt_ctx_sysv_free; - context->kill = xbt_ctx_sysv_kill; - context->schedule = xbt_ctx_sysv_schedule; - context->yield = xbt_ctx_sysv_yield; - context->start = xbt_ctx_sysv_start; - context->stop = xbt_ctx_sysv_stop; - - return (xbt_context_t)context; -} - -static void -xbt_ctx_sysv_free(xbt_context_t context) -{ - if(context) - { - free(context->name); - - if(context->argv) - { - int i; - - for(i = 0; i < context->argc; i++) - if(context->argv[i]) - free(context->argv[i]); - - free(context->argv); - } - - if(context->exception) - free(context->exception); - - /* finally destroy the context */ - free(context); - } -} - -static void -xbt_ctx_sysv_kill(xbt_context_t context) -{ - context->iwannadie = 1; - xbt_ctx_sysv_swap(context); -} - -/** - * \param context the winner - * - * Calling this function blocks the current context and schedule \a context. - * When \a context will call xbt_context_yield, it will return - * to this function as if nothing had happened. - * - * Only the maestro can call this function to run a given process. - */ -static void -xbt_ctx_sysv_schedule(xbt_context_t context) -{ - xbt_assert0((current_context == maestro_context),"You are not supposed to run this function here!"); - xbt_ctx_sysv_swap(context); -} - -/** - * Calling this function makes the current context yield. The context - * that scheduled it returns from xbt_context_schedule as if nothing - * had happened. - * - * Only the processes can call this function, giving back the control - * to the maestro - */ -static void -xbt_ctx_sysv_yield(void) -{ - xbt_assert0((current_context != maestro_context),"You are not supposed to run this function here!"); - xbt_ctx_sysv_swap(current_context); -} - -static void -xbt_ctx_sysv_start(xbt_context_t context) -{ - makecontext(&(((xbt_ctx_sysv_t)context)->uc), xbt_ctx_sysv_wrapper, 0); -} - -static void -xbt_ctx_sysv_stop(int exit_code) -{ - if(current_context->cleanup_func) - ((*current_context->cleanup_func))(current_context->cleanup_arg); - - xbt_swag_remove(current_context, context_living); - xbt_swag_insert(current_context, context_to_destroy); - - xbt_ctx_sysv_swap(current_context); -} - -static void -xbt_ctx_sysv_swap(xbt_context_t context) -{ - xbt_assert0(current_context, "You have to call context_init() first."); - xbt_assert0(context, "Invalid argument"); - - if(((xbt_ctx_sysv_t)context)->prev == NULL) - xbt_ctx_sysv_resume(context); - else - xbt_ctx_sysv_suspend(context); - - if(current_context->iwannadie) - xbt_ctx_sysv_stop(1); -} - -static void -xbt_ctx_sysv_wrapper(void) -{ - if (current_context->startup_func) - (*current_context->startup_func)(current_context->startup_arg); - - xbt_ctx_sysv_stop((*(current_context->code))(current_context->argc, current_context->argv)); -} - -static void -xbt_ctx_sysv_suspend(xbt_context_t context) -{ - int rv; - - xbt_ctx_sysv_t prev_context = ((xbt_ctx_sysv_t)context)->prev; - - current_context = (xbt_context_t)(((xbt_ctx_sysv_t)context)->prev); - - ((xbt_ctx_sysv_t)context)->prev = NULL; - - rv = swapcontext(&(((xbt_ctx_sysv_t)context)->uc), &(prev_context->uc)); - - xbt_assert0((rv == 0), "Context swapping failure"); -} - -static void -xbt_ctx_sysv_resume(xbt_context_t context) -{ - int rv; - - ((xbt_ctx_sysv_t)context)->prev = (xbt_ctx_sysv_t)current_context; - - current_context = context; - - rv = swapcontext(&(((xbt_ctx_sysv_t)context)->prev->uc), &(((xbt_ctx_sysv_t)context)->uc)); - - xbt_assert0((rv == 0), "Context swapping failure"); -} - - - + +#include "xbt/ex_interface.h" +#include "xbt/xbt_context_private.h" + +#include "context_sysv_config.h" /* loads context system definitions */ +#include "portable.h" +#include /* context relative declarations */ +#define STACK_SIZE 128*1024 /* lower this if you want to reduce the memory consumption */ + +typedef struct s_xbt_ctx_sysv { + XBT_CTX_BASE_T; + ucontext_t uc; /* the thread that execute the code */ + char stack[STACK_SIZE]; /* the thread stack size */ + struct s_xbt_ctx_sysv *prev; /* the previous thread */ +} s_xbt_ctx_sysv_t, *xbt_ctx_sysv_t; + + +/* callback: context fetching */ +static ex_ctx_t *xbt_jcontext_ex_ctx(void); + +/* callback: termination */ +static void xbt_jcontext_ex_terminate(xbt_ex_t * e); + +static xbt_context_t +xbt_ctx_sysv_factory_create_context(const char *name, xbt_main_func_t code, + void_f_pvoid_t startup_func, + void *startup_arg, + void_f_pvoid_t cleanup_func, + void *cleanup_arg, int argc, char **argv); + +static int xbt_ctx_sysv_factory_finalize(xbt_context_factory_t * factory); + +static int +xbt_ctx_sysv_factory_create_maestro_context(xbt_context_t * maestro); + +static void xbt_ctx_sysv_free(xbt_context_t context); + +static void xbt_ctx_sysv_kill(xbt_context_t context); + +static void xbt_ctx_sysv_schedule(xbt_context_t context); + +static void xbt_ctx_sysv_yield(void); + +static void xbt_ctx_sysv_start(xbt_context_t context); + +static void xbt_ctx_sysv_stop(int exit_code); + +static void xbt_ctx_sysv_swap(xbt_context_t context); + +static void xbt_ctx_sysv_schedule(xbt_context_t context); + +static void xbt_ctx_sysv_yield(void); + +static void xbt_ctx_sysv_suspend(xbt_context_t context); + +static void xbt_ctx_sysv_resume(xbt_context_t context); + +static void xbt_ctx_sysv_wrapper(void); + +/* callback: context fetching */ +static ex_ctx_t *xbt_ctx_sysv_ex_ctx(void) +{ + return current_context->exception; +} + +/* callback: termination */ +static void xbt_ctx_sysv_ex_terminate(xbt_ex_t * e) +{ + xbt_ex_display(e); + abort(); +} + + +void xbt_ctx_sysv_factory_init(xbt_context_factory_t * factory) +{ + /* context exception */ + *factory = xbt_new0(s_xbt_context_factory_t, 1); + + (*factory)->create_context = xbt_ctx_sysv_factory_create_context; + (*factory)->finalize = xbt_ctx_sysv_factory_finalize; + (*factory)->create_maestro_context = + xbt_ctx_sysv_factory_create_maestro_context; + (*factory)->name = "ctx_sysv_context_factory"; + + /* context exception handlers */ + __xbt_ex_ctx = xbt_ctx_sysv_ex_ctx; + __xbt_ex_terminate = xbt_ctx_sysv_ex_terminate; +} + +static int +xbt_ctx_sysv_factory_create_maestro_context(xbt_context_t * maestro) +{ + + xbt_ctx_sysv_t context = xbt_new0(s_xbt_ctx_sysv_t, 1); + + context->exception = xbt_new(ex_ctx_t, 1); + XBT_CTX_INITIALIZE(context->exception); + + *maestro = (xbt_context_t) context; + + return 0; + +} + + +static int xbt_ctx_sysv_factory_finalize(xbt_context_factory_t * factory) +{ + free(maestro_context->exception); + free(*factory); + *factory = NULL; + return 0; +} + +static xbt_context_t +xbt_ctx_sysv_factory_create_context(const char *name, xbt_main_func_t code, + void_f_pvoid_t startup_func, + void *startup_arg, + void_f_pvoid_t cleanup_func, + void *cleanup_arg, int argc, char **argv) +{ + xbt_ctx_sysv_t context = xbt_new0(s_xbt_ctx_sysv_t, 1); + + context->code = code; + context->name = xbt_strdup(name); + + xbt_assert2(getcontext(&(context->uc)) == 0, + "Error in context saving: %d (%s)", errno, strerror(errno)); + context->uc.uc_link = NULL; + context->uc.uc_stack.ss_sp = + pth_skaddr_makecontext(context->stack, STACK_SIZE); + context->uc.uc_stack.ss_size = + pth_sksize_makecontext(context->stack, STACK_SIZE); + + context->exception = xbt_new(ex_ctx_t, 1); + XBT_CTX_INITIALIZE(context->exception); + context->iwannadie = 0; /* useless but makes valgrind happy */ + context->argc = argc; + context->argv = argv; + context->startup_func = startup_func; + context->startup_arg = startup_arg; + context->cleanup_func = cleanup_func; + context->cleanup_arg = cleanup_arg; + + + context->free = xbt_ctx_sysv_free; + context->kill = xbt_ctx_sysv_kill; + context->schedule = xbt_ctx_sysv_schedule; + context->yield = xbt_ctx_sysv_yield; + context->start = xbt_ctx_sysv_start; + context->stop = xbt_ctx_sysv_stop; + + return (xbt_context_t) context; +} + +static void xbt_ctx_sysv_free(xbt_context_t context) +{ + if (context) { + free(context->name); + + if (context->argv) { + int i; + + for (i = 0; i < context->argc; i++) + if (context->argv[i]) + free(context->argv[i]); + + free(context->argv); + } + + if (context->exception) + free(context->exception); + + /* finally destroy the context */ + free(context); + } +} + +static void xbt_ctx_sysv_kill(xbt_context_t context) +{ + context->iwannadie = 1; + xbt_ctx_sysv_swap(context); +} + +/** + * \param context the winner + * + * Calling this function blocks the current context and schedule \a context. + * When \a context will call xbt_context_yield, it will return + * to this function as if nothing had happened. + * + * Only the maestro can call this function to run a given process. + */ +static void xbt_ctx_sysv_schedule(xbt_context_t context) +{ + xbt_assert0((current_context == maestro_context), + "You are not supposed to run this function here!"); + xbt_ctx_sysv_swap(context); +} + +/** + * Calling this function makes the current context yield. The context + * that scheduled it returns from xbt_context_schedule as if nothing + * had happened. + * + * Only the processes can call this function, giving back the control + * to the maestro + */ +static void xbt_ctx_sysv_yield(void) +{ + xbt_assert0((current_context != maestro_context), + "You are not supposed to run this function here!"); + xbt_ctx_sysv_swap(current_context); +} + +static void xbt_ctx_sysv_start(xbt_context_t context) +{ + makecontext(&(((xbt_ctx_sysv_t) context)->uc), xbt_ctx_sysv_wrapper, 0); +} + +static void xbt_ctx_sysv_stop(int exit_code) +{ + if (current_context->cleanup_func) + ((*current_context->cleanup_func)) (current_context->cleanup_arg); + + xbt_swag_remove(current_context, context_living); + xbt_swag_insert(current_context, context_to_destroy); + + xbt_ctx_sysv_swap(current_context); +} + +static void xbt_ctx_sysv_swap(xbt_context_t context) +{ + xbt_assert0(current_context, "You have to call context_init() first."); + xbt_assert0(context, "Invalid argument"); + + if (((xbt_ctx_sysv_t) context)->prev == NULL) + xbt_ctx_sysv_resume(context); + else + xbt_ctx_sysv_suspend(context); + + if (current_context->iwannadie) + xbt_ctx_sysv_stop(1); +} + +static void xbt_ctx_sysv_wrapper(void) +{ + if (current_context->startup_func) + (*current_context->startup_func) (current_context->startup_arg); + + xbt_ctx_sysv_stop((*(current_context->code)) + (current_context->argc, current_context->argv)); +} + +static void xbt_ctx_sysv_suspend(xbt_context_t context) +{ + int rv; + + xbt_ctx_sysv_t prev_context = ((xbt_ctx_sysv_t) context)->prev; + + current_context = (xbt_context_t) (((xbt_ctx_sysv_t) context)->prev); + + ((xbt_ctx_sysv_t) context)->prev = NULL; + + rv = swapcontext(&(((xbt_ctx_sysv_t) context)->uc), &(prev_context->uc)); + + xbt_assert0((rv == 0), "Context swapping failure"); +} + +static void xbt_ctx_sysv_resume(xbt_context_t context) +{ + int rv; + + ((xbt_ctx_sysv_t) context)->prev = (xbt_ctx_sysv_t) current_context; + + current_context = context; + + rv = + swapcontext(&(((xbt_ctx_sysv_t) context)->prev->uc), + &(((xbt_ctx_sysv_t) context)->uc)); + + xbt_assert0((rv == 0), "Context swapping failure"); +} diff --git a/src/xbt/xbt_context_thread.c b/src/xbt/xbt_context_thread.c index ae325cf185..b4a2e8bac5 100644 --- a/src/xbt/xbt_context_thread.c +++ b/src/xbt/xbt_context_thread.c @@ -1,309 +1,291 @@ - -#include "xbt/function_types.h" -#include "xbt/xbt_context_private.h" - -#include "portable.h" /* loads context system definitions */ -#include "xbt/swag.h" -#include "xbt/xbt_os_thread.h" - - -typedef struct s_xbt_ctx_thread { - XBT_CTX_BASE_T; - xbt_os_thread_t thread; /* a plain dumb thread (portable to posix or windows) */ - xbt_os_sem_t begin; /* this semaphore is used to schedule/yield the process */ - xbt_os_sem_t end; /* this semaphore is used to schedule/unschedule the process */ -} s_xbt_ctx_thread_t,* xbt_ctx_thread_t; - -static xbt_context_t -xbt_ctx_thread_factory_create_context(const char* name, xbt_main_func_t code, void_f_pvoid_t startup_func, void* startup_arg, void_f_pvoid_t cleanup_func, void* cleanup_arg, int argc, char** argv); - - -static int -xbt_ctx_thread_factory_create_master_context(xbt_context_t* maestro); - -static int -xbt_ctx_thread_factory_finalize(xbt_context_factory_t* factory); - -static void -xbt_ctx_thread_free(xbt_context_t context); - -static void -xbt_ctx_thread_kill(xbt_context_t context); - -static void -xbt_ctx_thread_schedule(xbt_context_t context); - -static void -xbt_ctx_thread_yield(void); - -static void -xbt_ctx_thread_start(xbt_context_t context); - -static void -xbt_ctx_thread_stop(int exit_code); - -static void -xbt_ctx_thread_swap(xbt_context_t context); - -static void -xbt_ctx_thread_schedule(xbt_context_t context); - -static void -xbt_ctx_thread_yield(void); - -static void -xbt_ctx_thread_suspend(xbt_context_t context); - -static void -xbt_ctx_thread_resume(xbt_context_t context); - -static void* -xbt_ctx_thread_wrapper(void* param); - -void -xbt_ctx_thread_factory_init(xbt_context_factory_t* factory) -{ - *factory = xbt_new0(s_xbt_context_factory_t,1); - - (*factory)->create_context = xbt_ctx_thread_factory_create_context; - (*factory)->finalize = xbt_ctx_thread_factory_finalize; - (*factory)->create_maestro_context = xbt_ctx_thread_factory_create_master_context; - (*factory)->name = "ctx_thread_factory"; -} - -static int -xbt_ctx_thread_factory_create_master_context(xbt_context_t* maestro) -{ - *maestro = (xbt_context_t)xbt_new0(s_xbt_ctx_thread_t, 1); - return 0; -} - -static int -xbt_ctx_thread_factory_finalize(xbt_context_factory_t* factory) -{ - free(*factory); - *factory = NULL; - return 0; -} - -static xbt_context_t -xbt_ctx_thread_factory_create_context(const char* name, xbt_main_func_t code, void_f_pvoid_t startup_func, void* startup_arg, void_f_pvoid_t cleanup_func, void* cleanup_arg, int argc, char** argv) -{ - xbt_ctx_thread_t context = xbt_new0(s_xbt_ctx_thread_t, 1); - - context->code = code; - context->name = xbt_strdup(name); - context->begin = xbt_os_sem_init(0); - context->end = xbt_os_sem_init(0); - context->iwannadie = 0; /* useless but makes valgrind happy */ - context->argc = argc; - context->argv = argv; - context->startup_func = startup_func; - context->startup_arg = startup_arg; - context->cleanup_func = cleanup_func; - context->cleanup_arg = cleanup_arg; - - context->free = xbt_ctx_thread_free; - context->kill = xbt_ctx_thread_kill; - context->schedule = xbt_ctx_thread_schedule; - context->yield = xbt_ctx_thread_yield; - context->start = xbt_ctx_thread_start; - context->stop = xbt_ctx_thread_stop; - - return (xbt_context_t)context; -} - -static void -xbt_ctx_thread_free(xbt_context_t context) -{ - if(context) - { - xbt_ctx_thread_t ctx_thread = (xbt_ctx_thread_t)context; - - free(ctx_thread->name); - - if(ctx_thread->argv) - { - int i; - - for(i = 0; i < ctx_thread->argc; i++) - if(ctx_thread->argv[i]) - free(ctx_thread->argv[i]); - - free(ctx_thread->argv); - } - - /* wait about the thread terminason */ - xbt_os_thread_join(ctx_thread->thread, NULL); - - /* destroy the synchronisation objects */ - xbt_os_sem_destroy(ctx_thread->begin); - xbt_os_sem_destroy(ctx_thread->end); - - /* finally destroy the context */ - free(context); - } -} - -static void -xbt_ctx_thread_kill(xbt_context_t context) -{ - context->iwannadie = 1; - xbt_ctx_thread_swap(context); -} - -/** - * \param context the winner - * - * Calling this function blocks the current context and schedule \a context. - * When \a context will call xbt_context_yield, it will return - * to this function as if nothing had happened. - * - * Only the maestro can call this function to run a given process. - */ -static void -xbt_ctx_thread_schedule(xbt_context_t context) -{ - xbt_assert0((current_context == maestro_context),"You are not supposed to run this function here!"); - xbt_ctx_thread_swap(context); -} - -/** - * Calling this function makes the current context yield. The context - * that scheduled it returns from xbt_context_schedule as if nothing - * had happened. - * - * Only the processes can call this function, giving back the control - * to the maestro - */ -static void -xbt_ctx_thread_yield(void) -{ - xbt_assert0((current_context != maestro_context),"You are not supposed to run this function here!"); - xbt_ctx_thread_swap(current_context); -} - -static void -xbt_ctx_thread_start(xbt_context_t context) -{ - xbt_ctx_thread_t ctx_thread = (xbt_ctx_thread_t)context; - - /* create and start the process */ - ctx_thread->thread = xbt_os_thread_create(ctx_thread->name,xbt_ctx_thread_wrapper,ctx_thread); - - /* wait the starting of the newly created process */ - xbt_os_sem_acquire(ctx_thread->end); -} - -static void -xbt_ctx_thread_stop(int exit_code) -{ - if(current_context->cleanup_func) - ((*current_context->cleanup_func))(current_context->cleanup_arg); - - xbt_swag_remove(current_context, context_living); - xbt_swag_insert(current_context, context_to_destroy); - - /* signal to the maestro that it has finished */ - xbt_os_sem_release(((xbt_ctx_thread_t)current_context)->end); - - /* exit*/ - xbt_os_thread_exit(NULL); /* We should provide return value in case other wants it */ -} - -static void -xbt_ctx_thread_swap(xbt_context_t context) -{ - if((current_context != maestro_context) && !context->iwannadie) - { - /* (0) it's not the scheduler and the process doesn't want to die, it just wants to yield */ - - /* yield itself, resume the maestro */ - xbt_ctx_thread_suspend(context); - } - else - { - /* (1) the current process is the scheduler and the process doesn't want to die - * <-> the maestro wants to schedule the process - * -> the maestro schedules the process and waits - * - * (2) the current process is the scheduler and the process wants to die - * <-> the maestro wants to kill the process (has called the function xbt_context_kill()) - * -> the maestro schedule the process and waits (xbt_os_sem_acquire(context->end)) - * -> if the process stops (xbt_context_stop()) - * -> the process resumes the maestro (xbt_os_sem_release(current_context->end)) and exit (xbt_os_thread_exit()) - * -> else the process call xbt_context_yield() - * -> goto (3.1) - * - * (3) the current process is not the scheduler and the process wants to die - * -> (3.1) if the current process is the process who wants to die - * -> (resume not need) goto (4) - * -> (3.2) else the current process is not the process who wants to die - * <-> the current process wants to kill an other process - * -> the current process resumes the process to die and waits - * -> if the process to kill stops - * -> it resumes the process who kill it and exit - * -> else if the process to kill calls to xbt_context_yield() - * -> goto (3.1) - */ - /* schedule the process associated with this context */ - xbt_ctx_thread_resume(context); - - } - - /* (4) the current process wants to die */ - if(current_context->iwannadie) - xbt_ctx_thread_stop(1); -} - -static void* -xbt_ctx_thread_wrapper(void* param) -{ - xbt_ctx_thread_t context = (xbt_ctx_thread_t)param; - - /* 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 (context->startup_func) - (*(context->startup_func))(context->startup_arg); - - - xbt_ctx_thread_stop((context->code) (context->argc, context->argv)); - return NULL; -} - -static void -xbt_ctx_thread_suspend(xbt_context_t context) -{ - /* save the current context */ - xbt_context_t self = current_context; - - /* update the current context to this context */ - current_context = context; - - xbt_os_sem_release(((xbt_ctx_thread_t)context)->end); - xbt_os_sem_acquire(((xbt_ctx_thread_t)context)->begin); - - /* restore the current context to the previously saved context */ - current_context = self; -} - -static void -xbt_ctx_thread_resume(xbt_context_t context) -{ - /* save the current context */ - xbt_context_t self = current_context; - - /* update the current context */ - current_context = context; - - xbt_os_sem_release(((xbt_ctx_thread_t)context)->begin); - xbt_os_sem_acquire(((xbt_ctx_thread_t)context)->end); - - /* restore the current context to the previously saved context */ - current_context = self; -} - - - + +#include "xbt/function_types.h" +#include "xbt/xbt_context_private.h" + +#include "portable.h" /* loads context system definitions */ +#include "xbt/swag.h" +#include "xbt/xbt_os_thread.h" + + +typedef struct s_xbt_ctx_thread { + XBT_CTX_BASE_T; + xbt_os_thread_t thread; /* a plain dumb thread (portable to posix or windows) */ + xbt_os_sem_t begin; /* this semaphore is used to schedule/yield the process */ + xbt_os_sem_t end; /* this semaphore is used to schedule/unschedule the process */ +} s_xbt_ctx_thread_t, *xbt_ctx_thread_t; + +static xbt_context_t +xbt_ctx_thread_factory_create_context(const char *name, xbt_main_func_t code, + void_f_pvoid_t startup_func, + void *startup_arg, + void_f_pvoid_t cleanup_func, + void *cleanup_arg, int argc, + char **argv); + + +static int +xbt_ctx_thread_factory_create_master_context(xbt_context_t * maestro); + +static int xbt_ctx_thread_factory_finalize(xbt_context_factory_t * factory); + +static void xbt_ctx_thread_free(xbt_context_t context); + +static void xbt_ctx_thread_kill(xbt_context_t context); + +static void xbt_ctx_thread_schedule(xbt_context_t context); + +static void xbt_ctx_thread_yield(void); + +static void xbt_ctx_thread_start(xbt_context_t context); + +static void xbt_ctx_thread_stop(int exit_code); + +static void xbt_ctx_thread_swap(xbt_context_t context); + +static void xbt_ctx_thread_schedule(xbt_context_t context); + +static void xbt_ctx_thread_yield(void); + +static void xbt_ctx_thread_suspend(xbt_context_t context); + +static void xbt_ctx_thread_resume(xbt_context_t context); + +static void *xbt_ctx_thread_wrapper(void *param); + +void xbt_ctx_thread_factory_init(xbt_context_factory_t * factory) +{ + *factory = xbt_new0(s_xbt_context_factory_t, 1); + + (*factory)->create_context = xbt_ctx_thread_factory_create_context; + (*factory)->finalize = xbt_ctx_thread_factory_finalize; + (*factory)->create_maestro_context = + xbt_ctx_thread_factory_create_master_context; + (*factory)->name = "ctx_thread_factory"; +} + +static int +xbt_ctx_thread_factory_create_master_context(xbt_context_t * maestro) +{ + *maestro = (xbt_context_t) xbt_new0(s_xbt_ctx_thread_t, 1); + return 0; +} + +static int xbt_ctx_thread_factory_finalize(xbt_context_factory_t * factory) +{ + free(*factory); + *factory = NULL; + return 0; +} + +static xbt_context_t +xbt_ctx_thread_factory_create_context(const char *name, xbt_main_func_t code, + void_f_pvoid_t startup_func, + void *startup_arg, + void_f_pvoid_t cleanup_func, + void *cleanup_arg, int argc, + char **argv) +{ + xbt_ctx_thread_t context = xbt_new0(s_xbt_ctx_thread_t, 1); + + context->code = code; + context->name = xbt_strdup(name); + context->begin = xbt_os_sem_init(0); + context->end = xbt_os_sem_init(0); + context->iwannadie = 0; /* useless but makes valgrind happy */ + context->argc = argc; + context->argv = argv; + context->startup_func = startup_func; + context->startup_arg = startup_arg; + context->cleanup_func = cleanup_func; + context->cleanup_arg = cleanup_arg; + + context->free = xbt_ctx_thread_free; + context->kill = xbt_ctx_thread_kill; + context->schedule = xbt_ctx_thread_schedule; + context->yield = xbt_ctx_thread_yield; + context->start = xbt_ctx_thread_start; + context->stop = xbt_ctx_thread_stop; + + return (xbt_context_t) context; +} + +static void xbt_ctx_thread_free(xbt_context_t context) +{ + if (context) { + xbt_ctx_thread_t ctx_thread = (xbt_ctx_thread_t) context; + + free(ctx_thread->name); + + if (ctx_thread->argv) { + int i; + + for (i = 0; i < ctx_thread->argc; i++) + if (ctx_thread->argv[i]) + free(ctx_thread->argv[i]); + + free(ctx_thread->argv); + } + + /* wait about the thread terminason */ + xbt_os_thread_join(ctx_thread->thread, NULL); + + /* destroy the synchronisation objects */ + xbt_os_sem_destroy(ctx_thread->begin); + xbt_os_sem_destroy(ctx_thread->end); + + /* finally destroy the context */ + free(context); + } +} + +static void xbt_ctx_thread_kill(xbt_context_t context) +{ + context->iwannadie = 1; + xbt_ctx_thread_swap(context); +} + +/** + * \param context the winner + * + * Calling this function blocks the current context and schedule \a context. + * When \a context will call xbt_context_yield, it will return + * to this function as if nothing had happened. + * + * Only the maestro can call this function to run a given process. + */ +static void xbt_ctx_thread_schedule(xbt_context_t context) +{ + xbt_assert0((current_context == maestro_context), + "You are not supposed to run this function here!"); + xbt_ctx_thread_swap(context); +} + +/** + * Calling this function makes the current context yield. The context + * that scheduled it returns from xbt_context_schedule as if nothing + * had happened. + * + * Only the processes can call this function, giving back the control + * to the maestro + */ +static void xbt_ctx_thread_yield(void) +{ + xbt_assert0((current_context != maestro_context), + "You are not supposed to run this function here!"); + xbt_ctx_thread_swap(current_context); +} + +static void xbt_ctx_thread_start(xbt_context_t context) +{ + xbt_ctx_thread_t ctx_thread = (xbt_ctx_thread_t) context; + + /* create and start the process */ + ctx_thread->thread = + xbt_os_thread_create(ctx_thread->name, xbt_ctx_thread_wrapper, + ctx_thread); + + /* wait the starting of the newly created process */ + xbt_os_sem_acquire(ctx_thread->end); +} + +static void xbt_ctx_thread_stop(int exit_code) +{ + if (current_context->cleanup_func) + ((*current_context->cleanup_func)) (current_context->cleanup_arg); + + xbt_swag_remove(current_context, context_living); + xbt_swag_insert(current_context, context_to_destroy); + + /* signal to the maestro that it has finished */ + xbt_os_sem_release(((xbt_ctx_thread_t) current_context)->end); + + /* exit */ + xbt_os_thread_exit(NULL); /* We should provide return value in case other wants it */ +} + +static void xbt_ctx_thread_swap(xbt_context_t context) +{ + if ((current_context != maestro_context) && !context->iwannadie) { + /* (0) it's not the scheduler and the process doesn't want to die, it just wants to yield */ + + /* yield itself, resume the maestro */ + xbt_ctx_thread_suspend(context); + } else { + /* (1) the current process is the scheduler and the process doesn't want to die + * <-> the maestro wants to schedule the process + * -> the maestro schedules the process and waits + * + * (2) the current process is the scheduler and the process wants to die + * <-> the maestro wants to kill the process (has called the function xbt_context_kill()) + * -> the maestro schedule the process and waits (xbt_os_sem_acquire(context->end)) + * -> if the process stops (xbt_context_stop()) + * -> the process resumes the maestro (xbt_os_sem_release(current_context->end)) and exit (xbt_os_thread_exit()) + * -> else the process call xbt_context_yield() + * -> goto (3.1) + * + * (3) the current process is not the scheduler and the process wants to die + * -> (3.1) if the current process is the process who wants to die + * -> (resume not need) goto (4) + * -> (3.2) else the current process is not the process who wants to die + * <-> the current process wants to kill an other process + * -> the current process resumes the process to die and waits + * -> if the process to kill stops + * -> it resumes the process who kill it and exit + * -> else if the process to kill calls to xbt_context_yield() + * -> goto (3.1) + */ + /* schedule the process associated with this context */ + xbt_ctx_thread_resume(context); + + } + + /* (4) the current process wants to die */ + if (current_context->iwannadie) + xbt_ctx_thread_stop(1); +} + +static void *xbt_ctx_thread_wrapper(void *param) +{ + xbt_ctx_thread_t context = (xbt_ctx_thread_t) param; + + /* 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 (context->startup_func) + (*(context->startup_func)) (context->startup_arg); + + + xbt_ctx_thread_stop((context->code) (context->argc, context->argv)); + return NULL; +} + +static void xbt_ctx_thread_suspend(xbt_context_t context) +{ + /* save the current context */ + xbt_context_t self = current_context; + + /* update the current context to this context */ + current_context = context; + + xbt_os_sem_release(((xbt_ctx_thread_t) context)->end); + xbt_os_sem_acquire(((xbt_ctx_thread_t) context)->begin); + + /* restore the current context to the previously saved context */ + current_context = self; +} + +static void xbt_ctx_thread_resume(xbt_context_t context) +{ + /* save the current context */ + xbt_context_t self = current_context; + + /* update the current context */ + current_context = context; + + xbt_os_sem_release(((xbt_ctx_thread_t) context)->begin); + xbt_os_sem_acquire(((xbt_ctx_thread_t) context)->end); + + /* restore the current context to the previously saved context */ + current_context = self; +} -- 2.20.1