Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
The file containing the new implementation of the switch context mechanism.
authorcherierm <cherierm@48e7efb5-ca39-0410-a469-dd3cf9ba447f>
Thu, 15 Nov 2007 18:23:30 +0000 (18:23 +0000)
committercherierm <cherierm@48e7efb5-ca39-0410-a469-dd3cf9ba447f>
Thu, 15 Nov 2007 18:23:30 +0000 (18:23 +0000)
git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/simgrid/simgrid/trunk@5043 48e7efb5-ca39-0410-a469-dd3cf9ba447f

include/xbt/xbt_context.h [new file with mode: 0644]
src/xbt/xbt_context.c [new file with mode: 0644]
src/xbt/xbt_context_factory.h [new file with mode: 0644]
src/xbt/xbt_context_private.h [new file with mode: 0644]
src/xbt/xbt_jcontext.c [new file with mode: 0644]
src/xbt/xbt_jcontext.h [new file with mode: 0644]
src/xbt/xbt_thread_context.c [new file with mode: 0644]
src/xbt/xbt_thread_context.h [new file with mode: 0644]
src/xbt/xbt_ucontext.c [new file with mode: 0644]
src/xbt/xbt_ucontext.h [new file with mode: 0644]

diff --git a/include/xbt/xbt_context.h b/include/xbt/xbt_context.h
new file mode 100644 (file)
index 0000000..9190d58
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef XBT_CONTEXT_H\r
+#define XBT_CONTEXT_H\r
+\r
+#include "xbt/misc.h"                          /* XBT_PUBLIC(), SG_BEGIN_DECL() and SG_END_DECL() definitions  */\r
+#include "xbt/function_types.h"                /* function pointer types declarations                                                  */      \r
+#include "xbt_modinter.h"                      /* xbt_context_init() and xbt_context_exit() declarations               */\r
+\r
+SG_BEGIN_DECL()\r
+\r
+typedef struct s_xbt_context* xbt_context_t;\r
+\r
+XBT_PUBLIC(xbt_context_t) \r
+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[]);\r
+\r
+XBT_PUBLIC(void) \r
+xbt_context_kill(xbt_context_t context);\r
+\r
+XBT_PUBLIC(void) \r
+xbt_context_start(xbt_context_t context);\r
+\r
+XBT_PUBLIC(void) \r
+xbt_context_yield(void);\r
+\r
+XBT_PUBLIC(void) \r
+xbt_context_schedule(xbt_context_t context);\r
+\r
+void \r
+xbt_context_empty_trash(void);\r
+\r
+void\r
+xbt_context_stop(int exit_code);\r
+\r
+void\r
+xbt_context_free(xbt_context_t context);\r
+\r
+\r
+SG_END_DECL()\r
+\r
+#endif /* !XBT_CONTEXT_H */\r
diff --git a/src/xbt/xbt_context.c b/src/xbt/xbt_context.c
new file mode 100644 (file)
index 0000000..418b125
--- /dev/null
@@ -0,0 +1,333 @@
+/* a fast and simple context switching library                              */\r
+\r
+/* Copyright (c) 2004 Arnaud Legrand.                                       */\r
+/* Copyright (c) 2004, 2005 Martin Quinson.                                 */\r
+/* All rights reserved.                                                     */\r
+\r
+/* This program is free software; you can redistribute it and/or modify it\r
+ * under the terms of the license (GNU LGPL) which comes with this package. */\r
+\r
+#include "portable.h"\r
+#include "xbt/log.h"\r
+#include "xbt/swag.h"\r
+#include "xbt_context_factory.h"\r
+\r
+/* the context associated with the current process                             */\r
+static xbt_context_t \r
+current_context = NULL;\r
+\r
+/* the context associated with the maestro                                             */\r
+static xbt_context_t \r
+maestro_context = NULL;\r
+\r
+\r
+/* this list contains the contexts to destroy                                  */\r
+static xbt_swag_t \r
+context_to_destroy = NULL;\r
+\r
+/* this list contains the contexts in use                                              */\r
+static xbt_swag_t \r
+context_living = NULL;\r
+\r
+/* the context factory used to create the appropriate context  \r
+ * each context implementation define its own context factory\r
+ * a context factory is responsable of the creation of the context\r
+ * associated with the maestro and of all the context based on\r
+ * the selected implementation.\r
+ *\r
+ * for example, the context switch based on java thread use the\r
+ * java implementation of the context and the java factory build\r
+ * the context depending of this implementation.\r
+ */\r
+static xbt_context_factory_t\r
+context_factory = NULL;\r
+\r
+/* java implementation of the context */\r
+#include "xbt_jcontext.c"\r
+\r
+#ifdef CONTEXT_THREADS\r
+/* use the native thread implementation of the context */\r
+#include "xbt_thread_context.c"\r
+#elif !defined(WIN32)\r
+/* use the ucontext    based context           */\r
+#  include "xbt_ucontext.c" \r
+#endif \r
+\r
+\r
+/**\r
+ * This function is call by the xbt_init() function to initialize the context module.\r
+ */\r
+void\r
+xbt_context_mod_init(void)\r
+{\r
+       if(!context_factory)\r
+       {\r
+               /* select context factory to use to create the context(depends of the macro definitions) */\r
+\r
+               #ifdef CONTEXT_THREADS\r
+                       /* context switch based os thread */\r
+                       xbt_thread_context_factory_init(&context_factory);\r
+               #elif !defined(WIN32)\r
+                       /* context switch based ucontext */\r
+                       xbt_ucontext_factory_init(&context_factory);\r
+               #else\r
+                       /* context switch is not allowed on Windows */\r
+                       #error ERROR [__FILE__, line __LINE__]: no context based implementation specified.\r
+               #endif\r
+               \r
+               /* maestro context specialisation (this create the maestro with the good implementation */\r
+               (*(context_factory->create_maestro_context))(&maestro_context);\r
+               \r
+               /* the current context is the context of the maestro */\r
+               current_context = maestro_context;\r
+               \r
+               /* the current context doesn't want to die */\r
+               current_context->iwannadie = 0;\r
+               \r
+               /* intantiation of the lists containing the contexts to destroy and the contexts in use */  \r
+               context_to_destroy = xbt_swag_new(xbt_swag_offset(*current_context, hookup));\r
+               context_living = xbt_swag_new(xbt_swag_offset(*current_context, hookup));\r
+               \r
+               /* insert the current context in the list of the contexts in use */\r
+               xbt_swag_insert(current_context, context_living);\r
+               \r
+       }                \r
+} \r
+\r
+/**\r
+ * This function is call by the xbt_exit() function to finalize the context module.\r
+ */\r
+void\r
+xbt_context_mod_exit(void)\r
+{\r
+       if(context_factory)\r
+       {\r
+               xbt_context_t context = NULL;\r
+               xbt_pfn_context_factory_finalize_t finalize_factory;\r
+               \r
+               /* finalize the context factory */\r
+               finalize_factory = context_factory->finalize;\r
+               \r
+               (*finalize_factory)(&context_factory);\r
+               \r
+               /* destroy all contexts in the list of contexts to destroy */\r
+               xbt_context_empty_trash();\r
+               \r
+               /* remove the context of the scheduler from the list of the contexts in use */\r
+               xbt_swag_remove(maestro_context, context_living);\r
+               \r
+               free(maestro_context);\r
+               maestro_context = current_context = NULL;\r
+               \r
+               /*  \r
+                * kill all the contexts in use :\r
+                * the killed contexts are added in the list of the contexts to destroy\r
+                */\r
+               while((context = xbt_swag_extract(context_living))) \r
+                               (*(context->kill))(context);    \r
+       \r
+               \r
+               /* destroy all contexts in the list of contexts to destroy */\r
+               xbt_context_empty_trash();\r
+               \r
+               /* destroy the lists */\r
+               xbt_swag_free(context_to_destroy);\r
+               xbt_swag_free(context_living);\r
+       }\r
+}\r
+\r
+/*******************************/\r
+/* Object creation/destruction */\r
+/*******************************/\r
+/** \r
+ * \param code a main function\r
+ * \param startup_func a function to call when running the context for\r
+ *      the first time and just before the main function \a code\r
+ * \param startup_arg the argument passed to the previous function (\a startup_func)\r
+ * \param cleanup_func a function to call when running the context, just after \r
+        the termination of the main function \a code\r
+ * \param cleanup_arg the argument passed to the previous function (\a cleanup_func)\r
+ * \param argc first argument of function \a code\r
+ * \param argv seconde argument of function \a code\r
+ */\r
+xbt_context_t\r
+xbt_context_new(const char *name,\r
+                xbt_main_func_t code,\r
+                void_f_pvoid_t startup_func,\r
+                void *startup_arg,\r
+                void_f_pvoid_t cleanup_func,\r
+                void *cleanup_arg, int argc, char *argv[]\r
+)\r
+{\r
+       /* use the appropriate context factory to create the appropriate context */\r
+       xbt_context_t context = (*(context_factory->create_context))(name, code, startup_func, startup_arg, cleanup_func, cleanup_arg, argc, argv);\r
+       \r
+       /* add the context in the list of the contexts in use */\r
+       xbt_swag_insert(context, context_living);\r
+\r
+       return context;\r
+}\r
+\r
+/* Scenario for the end of a context:\r
+ * \r
+ * CASE 1: death after end of function\r
+ *   __context_wrapper, called by os thread, calls xbt_context_stop after user code stops\r
+ *   xbt_context_stop calls user cleanup_func if any (in context settings),\r
+ *                    add current to trashbin\r
+ *                    yields back to maestro (destroy os thread on need)\r
+ *   From time to time, maestro calls xbt_context_empty_trash, \r
+ *       which maps xbt_context_free on the content\r
+ *   xbt_context_free frees some more memory, \r
+ *                    joins os thread\r
+ * \r
+ * CASE 2: brutal death\r
+ *   xbt_context_kill (from any context)\r
+ *                    set context->wannadie to 1\r
+ *                    yields to the context\r
+ *   the context is awaken in the middle of __yield. \r
+ *   At the end of it, it checks that wannadie == 1, and call xbt_context_stop\r
+ *   (same than first case afterward)\r
+ */\r
+\r
+\r
+/* Argument must be stopped first -- runs in maestro context */\r
+void\r
+xbt_context_free(xbt_context_t context)\r
+{\r
+       (*(context->free))(context);    \r
+}\r
+\r
+\r
+void\r
+xbt_context_kill(xbt_context_t context)\r
+{\r
+       (*(context->kill))(context);    \r
+}\r
+\r
+/** \r
+ * \param context the context to start\r
+ * \r
+ * Calling this function prepares \a context to be run. It will \r
+   however run effectively only when calling #xbt_context_schedule\r
+ */\r
+void\r
+xbt_context_start(xbt_context_t context)\r
+{\r
+       (*(context->start))(context);\r
+}\r
+\r
+/** \r
+ * Calling this function makes the current context yield. The context\r
+ * that scheduled it returns from xbt_context_schedule as if nothing\r
+ * had happened.\r
+ * \r
+ * Only the processes can call this function, giving back the control\r
+ * to the maestro\r
+ */\r
+void\r
+xbt_context_yield(void)\r
+{\r
+       (*(current_context->yield))();  \r
+}\r
+\r
+/** \r
+ * \param context the winner\r
+ *\r
+ * Calling this function blocks the current context and schedule \a context.  \r
+ * When \a context will call xbt_context_yield, it will return\r
+ * to this function as if nothing had happened.\r
+ * \r
+ * Only the maestro can call this function to run a given process.\r
+ */\r
+void\r
+xbt_context_schedule(xbt_context_t context)\r
+{\r
+       (*(context->schedule))(context);        \r
+}\r
+\r
+void\r
+xbt_context_stop(int exit_code)\r
+{\r
+\r
+       (*(current_context->stop))(exit_code);\r
+}\r
+\r
+int\r
+xbt_context_select_factory(const char* name)\r
+{\r
+       /* if a factory is already instantiated (xbt_context_mod_init() was called) */\r
+       if(NULL != context_factory)\r
+       {\r
+               /* if the desired factory is different of the current factory, call xbt_context_mod_exit() */\r
+               if(strcmp(context_factory->name,name))\r
+               {\r
+                       xbt_context_mod_exit();\r
+                               \r
+               }\r
+               else\r
+               {\r
+                       /* the same context factory is requested return directly */\r
+                       return 0;\r
+               }\r
+       }\r
+       \r
+       /* get the desired factory */\r
+       xbt_context_init_factory_by_name(&context_factory,name);\r
+       \r
+       /* maestro context specialisation */\r
+       (*(context_factory->create_maestro_context))(&maestro_context);\r
+       \r
+       /* the current context is the context of the maestro */\r
+       current_context = maestro_context;\r
+       \r
+       /* the current context doesn't want to die */\r
+       current_context->iwannadie = 0;\r
+       \r
+       /* intantiation of the lists containing the contexts to destroy and the contexts in use */  \r
+       context_to_destroy = xbt_swag_new(xbt_swag_offset(*current_context, hookup));\r
+       context_living = xbt_swag_new(xbt_swag_offset(*current_context, hookup));\r
+       \r
+       /* insert the current context in the list of the contexts in use */\r
+       xbt_swag_insert(current_context, context_living);       \r
+       \r
+       return 0;       \r
+}\r
+\r
+int\r
+xbt_context_init_factory_by_name(xbt_context_factory_t* factory, const char* name)\r
+{\r
+       if(!strcmp(name,"jcontext_factory"))\r
+       {\r
+               return xbt_jcontext_factory_init(factory);      \r
+       }\r
+       #ifdef CONTEXT_THREADS\r
+       else if(!strcmp(name,"thread_context_factory")) \r
+       {\r
+               return xbt_thread_context_factory_init(factory);        \r
+       }\r
+       #elif !defined(WIN32)\r
+       else if(!strcmp(name,"ucontext_context_factory"))       \r
+       {\r
+               return xbt_ucontext_factory_init(factory);      \r
+       }\r
+       #endif\r
+       \r
+       return EINVAL;\r
+}\r
+\r
+/** Garbage collection\r
+ *\r
+ * Should be called some time to time to free the memory allocated for contexts\r
+ * that have finished executing their main functions.\r
+ */\r
+void \r
+xbt_context_empty_trash(void)\r
+{\r
+       xbt_context_t context = NULL;\r
+       \r
+       while((context = xbt_swag_extract(context_to_destroy)))\r
+               (*(context->free))(context);\r
+}\r
+\r
+\r
+\r
diff --git a/src/xbt/xbt_context_factory.h b/src/xbt/xbt_context_factory.h
new file mode 100644 (file)
index 0000000..b6f1a99
--- /dev/null
@@ -0,0 +1,56 @@
+#ifndef _XBT_CONTEXT_FACTORY_H \r
+#define _XBT_CONTEXT_FACTORY_H\r
+\r
+#include "portable.h"\r
+#include "xbt/function_types.h"\r
+#include "xbt_context_private.h"\r
+\r
+SG_BEGIN_DECL()\r
+\r
+/* forward declaration */\r
+struct s_xbt_context_factory;\r
+\r
+/* this function describes the interface that all context factory must implement */\r
+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**);\r
+typedef int (*xbt_pfn_context_factory_create_maestro_context_t)(xbt_context_t*);\r
+\r
+/* this function finalize the specified context factory */\r
+typedef int (*xbt_pfn_context_factory_finalize_t)(struct s_xbt_context_factory**);\r
+\r
+/* this interface is used by the xbt context module to create the appropriate concept */\r
+typedef struct s_xbt_context_factory\r
+{\r
+       xbt_pfn_context_factory_create_maestro_context_t create_maestro_context;        /* create the context of the maestro    */\r
+       xbt_pfn_context_factory_create_context_t create_context;                                        /* create a new context                                 */\r
+       xbt_pfn_context_factory_finalize_t finalize;                                                            /* finalize the context factory                 */\r
+       const char* name;                                                                                                                       /* the name of the context factory              */\r
+       \r
+}s_xbt_context_factory_t;\r
+\r
+#ifndef _XBT_CONTEXT_FACTORY_T_DEFINED\r
+typedef struct s_xbt_context_factory* xbt_context_factory_t;\r
+#define _XBT_CONTEXT_FACTORY_T_DEFINED\r
+#endif /* !_XBT_CONTEXT_FACTORY_T_DEFINED */\r
+\r
+/**\r
+ * This function select a context factory associated with the name specified by\r
+ * the parameter name.\r
+ * If successful the function returns 0. Otherwise the function returns the error\r
+ * code.\r
+ */\r
+int\r
+xbt_context_select_factory(const char* name);\r
+\r
+/**\r
+ * This function initialize a context factory from the name specified by the parameter\r
+ * name.\r
+ * If successful the factory specified by the parameter factory is initialized and the\r
+ * function returns 0. Otherwise the function returns the error code.\r
+ */\r
+int\r
+xbt_context_init_factory_by_name(xbt_context_factory_t* factory, const char* name);\r
+\r
+\r
+SG_END_DECL()\r
+\r
+#endif /* !_XBT_CONTEXT_FACTORY_H */\r
diff --git a/src/xbt/xbt_context_private.h b/src/xbt/xbt_context_private.h
new file mode 100644 (file)
index 0000000..5e061e4
--- /dev/null
@@ -0,0 +1,57 @@
+#ifndef _XBT_CONTEXT_PRIVATE_H\r
+#define _XBT_CONTEXT_PRIVATE_H\r
+\r
+#include "xbt/sysdep.h"\r
+#include "xbt/xbt_context.h"\r
+\r
+SG_BEGIN_DECL()\r
+\r
+/* the following function pointers describe the interface that all context concepts must implement */\r
+\r
+typedef void (*xbt_pfn_context_free_t)(xbt_context_t);         /* pointer type to the function used to destroy the specified context   */\r
+typedef void (*xbt_pfn_context_kill_t)(xbt_context_t);         /* pointer type to the function used to kill the specified context              */\r
+typedef void (*xbt_pfn_context_schedule_t)(xbt_context_t);     /* pointer type to the function used to resume the specified context    */\r
+typedef void (*xbt_pfn_context_yield_t)(void);                         /* pointer type to the function used to yield the specified context             */\r
+typedef void (*xbt_pfn_context_start_t)(xbt_context_t);                /* pointer type to the function used to start the specified context             */\r
+typedef void (*xbt_pfn_context_stop_t)(int);                           /* pointer type to the function used to stop the current context                */\r
+\r
+/* each context concept must use this macro in its declaration */\r
+#define XBT_CTX_BASE_T \\r
+       s_xbt_swag_hookup_t hookup; \\r
+       char *name; \\r
+       void_f_pvoid_t cleanup_func; \\r
+       void *cleanup_arg; \\r
+       ex_ctx_t *exception; \\r
+       int iwannadie; \\r
+       xbt_main_func_t code; \\r
+       int argc; \\r
+       char **argv; \\r
+       void_f_pvoid_t startup_func; \\r
+       void *startup_arg; \\r
+       xbt_pfn_context_free_t free; \\r
+       xbt_pfn_context_kill_t kill; \\r
+       xbt_pfn_context_schedule_t schedule; \\r
+       xbt_pfn_context_yield_t yield; \\r
+       xbt_pfn_context_start_t start; \\r
+       xbt_pfn_context_stop_t stop                             \r
+\r
+/* all other contexts derive from this structure */\r
+typedef struct s_xbt_context\r
+{\r
+       XBT_CTX_BASE_T;\r
+}s_xbt_context_t;\r
+\r
+SG_END_DECL()\r
+       \r
+\r
+#ifdef CONTEXT_THREADS\r
+#include "xbt_thread_context.h"        /* thread based context declarations            */\r
+#elif !defined(WIN32)\r
+#include "xbt_ucontext.h"              /* ucontext based context declarations          */\r
+#else\r
+#error ERROR [__FILE__, line __LINE__]: no context based implementation specified.\r
+#endif\r
+\r
+#include "xbt_jcontext.h"              /* java thread based context declarations       */      \r
+\r
+#endif /* !_XBT_CONTEXT_PRIVATE_H */\r
diff --git a/src/xbt/xbt_jcontext.c b/src/xbt/xbt_jcontext.c
new file mode 100644 (file)
index 0000000..b6e92d7
--- /dev/null
@@ -0,0 +1,279 @@
+\r
+\r
+#include "xbt/function_types.h"\r
+#include "xbt/ex_interface.h"\r
+\r
+XBT_LOG_NEW_DEFAULT_CATEGORY(jmsg,"MSG for Java(TM)");\r
+\r
+#include "java/jmsg.c"\r
+#include "java/jmsg_channel.c"\r
+#include "java/jmsg_host.c"\r
+#include "java/jmsg_parallel_task.c"\r
+#include "java/jmsg_task.c"\r
+#include "java/jxbt_utilities.c"\r
+#include "java/jmsg_process.c"\r
+\r
+\r
+/* callback: context fetching */\r
+static ex_ctx_t*\r
+xbt_jcontext_ex_ctx(void);\r
+\r
+/* callback: termination */\r
+static void \r
+xbt_jcontext_ex_terminate(xbt_ex_t *e);\r
+\r
+static xbt_context_t \r
+xbt_jcontext_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);\r
+\r
+static int \r
+xbt_jcontext_factory_create_maestro_context(xbt_context_t* maestro);\r
+\r
+static int\r
+xbt_jcontext_factory_finalize(xbt_context_factory_t* factory);\r
+\r
+static void \r
+xbt_jcontext_free(xbt_context_t context);\r
+\r
+static void \r
+xbt_jcontext_kill(xbt_context_t context);\r
+\r
+static void \r
+xbt_jcontext_schedule(xbt_context_t context);\r
+\r
+static void \r
+xbt_jcontext_yield(void);\r
+\r
+static void \r
+xbt_jcontext_start(xbt_context_t context);\r
+\r
+static void \r
+xbt_jcontext_stop(int exit_code);\r
+\r
+static void \r
+xbt_jcontext_swap(xbt_context_t context);\r
+\r
+static void\r
+xbt_jcontext_schedule(xbt_context_t context);\r
+\r
+static void\r
+xbt_jcontext_yield(void);\r
+\r
+static void\r
+xbt_jcontext_suspend(xbt_context_t context);\r
+\r
+static void\r
+xbt_jcontext_resume(xbt_context_t context);\r
+\r
+\r
+/* callback: context fetching */\r
+static ex_ctx_t*\r
+xbt_jcontext_ex_ctx(void) \r
+{\r
+       return current_context->exception;\r
+}\r
+\r
+/* callback: termination */\r
+static void \r
+xbt_jcontext_ex_terminate(xbt_ex_t *e) \r
+{\r
+       xbt_ex_display(e);\r
+       abort();\r
+}\r
+\r
+int\r
+xbt_jcontext_factory_init(xbt_context_factory_t* factory)\r
+{\r
+       /* context exception handlers */\r
+    __xbt_ex_ctx       = xbt_jcontext_ex_ctx;\r
+    __xbt_ex_terminate = xbt_jcontext_ex_terminate;    \r
+    \r
+    /* instantiate the context factory */\r
+       *factory = xbt_new0(s_xbt_context_factory_t,1);\r
+       \r
+       (*factory)->create_context = xbt_jcontext_factory_create_context;\r
+       (*factory)->finalize = xbt_jcontext_factory_finalize;\r
+       (*factory)->create_maestro_context = xbt_jcontext_factory_create_maestro_context;\r
+       (*factory)->name = "jcontext_factory";\r
+       \r
+       return 0;\r
+}\r
+\r
+static int \r
+xbt_jcontext_factory_create_maestro_context(xbt_context_t* maestro)\r
+{\r
+       xbt_jcontext_t context = xbt_new0(s_xbt_jcontext_t, 1);\r
+       \r
+       context->exception = xbt_new(ex_ctx_t,1);\r
+    XBT_CTX_INITIALIZE(context->exception);\r
+    \r
+    *maestro = (xbt_context_t)context;\r
+    \r
+    return 0;\r
+}\r
+\r
+static int\r
+xbt_jcontext_factory_finalize(xbt_context_factory_t* factory)\r
+{\r
+       free(maestro_context->exception);\r
+       free(*factory);\r
+       *factory = NULL;\r
+\r
+       return 0;\r
+}\r
+\r
+static xbt_context_t \r
+xbt_jcontext_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)\r
+{\r
+       xbt_jcontext_t context = xbt_new0(s_xbt_jcontext_t,1);\r
+\r
+       context->name = xbt_strdup(name);\r
+\r
+       context->cleanup_func = cleanup_func;\r
+       context->cleanup_arg = cleanup_arg;\r
+\r
+       context->exception = xbt_new(ex_ctx_t,1);\r
+       XBT_CTX_INITIALIZE(context->exception);\r
+\r
+       context->free = xbt_jcontext_free;                      \r
+       context->kill = xbt_jcontext_kill;                      \r
+       context->schedule = xbt_jcontext_schedule;\r
+       context->yield = xbt_jcontext_yield;                    \r
+       context->start = xbt_jcontext_start;                    \r
+       context->stop = xbt_jcontext_stop;      \r
+       context->jprocess = (jobject)startup_arg;\r
+       context->jenv = get_current_thread_env();\r
+\r
+       return (xbt_context_t)context;\r
+}\r
+\r
+static void \r
+xbt_jcontext_free(xbt_context_t context)\r
+{\r
+       if(context) \r
+       {\r
+               xbt_jcontext_t jcontext = (xbt_jcontext_t)context;\r
+               \r
+               free(jcontext->name);\r
+               \r
+               if(jcontext->jprocess) \r
+               {\r
+                       jobject jprocess = jcontext->jprocess;\r
+                       jcontext->jprocess = NULL;\r
+\r
+                       /* if the java process is alive join it */\r
+                       if(jprocess_is_alive(jprocess,get_current_thread_env())) \r
+                               jprocess_join(jprocess,get_current_thread_env());\r
+               }\r
+\r
+               if(jcontext->exception) \r
+                       free(jcontext->exception);\r
+\r
+               free(context);\r
+               context = NULL;\r
+       }\r
+}\r
+\r
+static void \r
+xbt_jcontext_kill(xbt_context_t context)\r
+{\r
+       context->iwannadie = 1;\r
+       xbt_jcontext_swap(context);\r
+}\r
+\r
+/** \r
+ * \param context the winner\r
+ *\r
+ * Calling this function blocks the current context and schedule \a context.  \r
+ * When \a context will call xbt_context_yield, it will return\r
+ * to this function as if nothing had happened.\r
+ * \r
+ * Only the maestro can call this function to run a given process.\r
+ */\r
+static void \r
+xbt_jcontext_schedule(xbt_context_t context)\r
+{\r
+       xbt_assert0((current_context == maestro_context),"You are not supposed to run this function here!");\r
+       xbt_jcontext_swap(context);\r
+}\r
+\r
+/** \r
+ * Calling this function makes the current context yield. The context\r
+ * that scheduled it returns from xbt_context_schedule as if nothing\r
+ * had happened.\r
+ * \r
+ * Only the processes can call this function, giving back the control\r
+ * to the maestro\r
+ */\r
+static void \r
+xbt_jcontext_yield(void)\r
+{\r
+       xbt_assert0((current_context != maestro_context),"You are not supposed to run this function here!");\r
+       jprocess_unschedule(current_context);\r
+}\r
+\r
+static void \r
+xbt_jcontext_start(xbt_context_t context)\r
+{\r
+       jprocess_start(((xbt_jcontext_t)context)->jprocess,get_current_thread_env());\r
+}\r
+\r
+static void \r
+xbt_jcontext_stop(int exit_code)\r
+{\r
+       jobject jprocess = NULL;\r
+       xbt_jcontext_t jcontext;\r
+\r
+       if(current_context->cleanup_func)\r
+               (*(current_context->cleanup_func))(current_context->cleanup_arg);\r
+\r
+       xbt_swag_remove(current_context, context_living);\r
+       xbt_swag_insert(current_context, context_to_destroy);\r
+       \r
+       jcontext = (xbt_jcontext_t)current_context;\r
+       \r
+       if(jcontext->iwannadie)\r
+       {\r
+               /* The maestro call xbt_context_stop() with an exit code set to one */\r
+               if(jcontext->jprocess) \r
+               {\r
+                       /* if the java process is alive schedule it */\r
+                       if(jprocess_is_alive(jcontext->jprocess,get_current_thread_env())) \r
+                       {\r
+                               jprocess_schedule(current_context);\r
+                               jprocess = jcontext->jprocess;\r
+                               jcontext->jprocess = NULL;\r
+                               \r
+                               /* interrupt the java process */\r
+                               jprocess_exit(jprocess,get_current_thread_env());\r
+\r
+                       }\r
+               }\r
+       }\r
+       else\r
+       {\r
+               /* the java process exits */\r
+               jprocess = jcontext->jprocess;\r
+               jcontext->jprocess = NULL;\r
+       }\r
+\r
+       /* delete the global reference associated with the java process */\r
+       jprocess_delete_global_ref(jprocess,get_current_thread_env());  \r
+}\r
+\r
+static void \r
+xbt_jcontext_swap(xbt_context_t context)\r
+{\r
+       if(context) \r
+       {\r
+               xbt_context_t self = current_context;\r
+               \r
+               current_context = context;\r
+               \r
+               jprocess_schedule(context);\r
+               \r
+               current_context = self;\r
+       }\r
+       \r
+       if(current_context->iwannadie)\r
+               xbt_jcontext_stop(1);\r
+}\r
diff --git a/src/xbt/xbt_jcontext.h b/src/xbt/xbt_jcontext.h
new file mode 100644 (file)
index 0000000..f3c1042
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef _XBT_JCONTEXT_H\r
+#define _XBT_JCONTEXT_H\r
+\r
+#include <jni.h>                                       /* use java native interface to bind the msg structures to the java instances                           */      \r
+#include "portable.h"\r
+#include "xbt/misc.h"\r
+\r
+#ifndef _XBT_CONTEXT_PRIVATE_H\r
+#include "xbt_context_private.h"\r
+#endif /* _XBT_CONTEXT_PRIVATE_H */\r
+\r
+SG_BEGIN_DECL()\r
+\r
+#ifndef _XBT_CONTEXT_FACTORY_T_DEFINED\r
+typedef struct s_xbt_context_factory* xbt_context_factory_t;\r
+#define _XBT_CONTEXT_FACTORY_T_DEFINED\r
+#endif /* !_XBT_CONTEXT_FACTORY_T_DEFINED */\r
+\r
+typedef struct s_xbt_jcontext\r
+{\r
+       XBT_CTX_BASE_T;\r
+       jobject jprocess;                               /* the java process instance binded with the msg process structure                                                      */\r
+       JNIEnv* jenv;                                   /* jni interface pointer associated to this thread                                                                                      */\r
+}s_xbt_jcontext_t,* xbt_jcontext_t;\r
+\r
+int\r
+xbt_jcontext_factory_init(xbt_context_factory_t* factory);\r
+\r
+\r
+SG_END_DECL()\r
+\r
+\r
+\r
+\r
+#endif /* !_XBT_JCONTEXT_H */\r
diff --git a/src/xbt/xbt_thread_context.c b/src/xbt/xbt_thread_context.c
new file mode 100644 (file)
index 0000000..fb8307b
--- /dev/null
@@ -0,0 +1,298 @@
+\r
+#include "xbt/function_types.h"\r
+\r
+static xbt_context_t \r
+xbt_thread_context_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);\r
+\r
+\r
+static int\r
+xbt_thread_context_factory_create_master_context(xbt_context_t* maestro);\r
+\r
+static int\r
+xbt_thread_context_factory_finalize(xbt_context_factory_t* factory);\r
+\r
+static void \r
+xbt_thread_context_free(xbt_context_t context);\r
+\r
+static void \r
+xbt_thread_context_kill(xbt_context_t context);\r
+\r
+static void \r
+xbt_thread_context_schedule(xbt_context_t context);\r
+\r
+static void \r
+xbt_thread_context_yield(void);\r
+\r
+static void \r
+xbt_thread_context_start(xbt_context_t context);\r
+\r
+static void \r
+xbt_thread_context_stop(int exit_code);\r
+\r
+static void \r
+xbt_thread_context_swap(xbt_context_t context);\r
+\r
+static void\r
+xbt_thread_context_schedule(xbt_context_t context);\r
+\r
+static void\r
+xbt_thread_context_yield(void);\r
+\r
+static void\r
+xbt_thread_context_suspend(xbt_context_t context);\r
+\r
+static void\r
+xbt_thread_context_resume(xbt_context_t context);\r
+\r
+static void* \r
+xbt_thread_context_wrapper(void* param);\r
+\r
+int\r
+xbt_thread_context_factory_init(xbt_context_factory_t* factory)\r
+{\r
+       *factory = xbt_new0(s_xbt_context_factory_t,1);\r
+       \r
+       (*factory)->create_context = xbt_thread_context_factory_create_context;\r
+       (*factory)->finalize = xbt_thread_context_factory_finalize;\r
+       (*factory)->create_maestro_context = xbt_thread_context_factory_create_master_context;\r
+       (*factory)->name = "thread_context_factory";\r
+\r
+       return 0;\r
+}\r
+\r
+static int\r
+xbt_thread_context_factory_create_master_context(xbt_context_t* maestro)\r
+{\r
+       *maestro = (xbt_context_t)xbt_new0(s_xbt_thread_context_t, 1);\r
+    return 0;\r
+}\r
+\r
+static int\r
+xbt_thread_context_factory_finalize(xbt_context_factory_t* factory)\r
+{\r
+       free(*factory);\r
+       *factory = NULL;\r
+       return 0;\r
+}\r
+\r
+static xbt_context_t \r
+xbt_thread_context_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)\r
+{\r
+       xbt_thread_context_t context = xbt_new0(s_xbt_thread_context_t, 1);\r
+       \r
+       context->code = code;\r
+       context->name = xbt_strdup(name);\r
+       context->begin = xbt_os_sem_init(0);\r
+       context->end = xbt_os_sem_init(0);\r
+       context->iwannadie = 0;           /* useless but makes valgrind happy */\r
+       context->argc = argc;\r
+       context->argv = argv;\r
+       context->startup_func = startup_func;\r
+       context->startup_arg = startup_arg;\r
+       context->cleanup_func = cleanup_func;\r
+       context->cleanup_arg = cleanup_arg;\r
+       \r
+       context->free = xbt_thread_context_free;                        \r
+       context->kill = xbt_thread_context_kill;                        \r
+       context->schedule = xbt_thread_context_schedule;\r
+       context->yield = xbt_thread_context_yield;                      \r
+       context->start = xbt_thread_context_start;                      \r
+       context->stop = xbt_thread_context_stop;                        \r
+       \r
+       return (xbt_context_t)context;\r
+}\r
+\r
+static void \r
+xbt_thread_context_free(xbt_context_t context)\r
+{\r
+       if(context)\r
+       {\r
+               xbt_thread_context_t thread_context = (xbt_thread_context_t)context;\r
+               \r
+               free(thread_context->name);\r
+               \r
+               if(thread_context->argv)\r
+               {\r
+                       int i;\r
+                       \r
+                       for(i = 0; i < thread_context->argc; i++)\r
+                               if(thread_context->argv[i])\r
+                                       free(thread_context->argv[i]);\r
+                                       \r
+                       free(thread_context->argv);\r
+               }\r
+               \r
+               /* wait about the thread terminason */\r
+               xbt_os_thread_join(thread_context->thread, NULL);\r
+               \r
+               /* destroy the synchronisation objects */\r
+               xbt_os_sem_destroy(thread_context->begin);\r
+               xbt_os_sem_destroy(thread_context->end);\r
+               \r
+               /* finally destroy the context */\r
+               free(context);\r
+       }\r
+}\r
+\r
+static void \r
+xbt_thread_context_kill(xbt_context_t context)\r
+{\r
+       context->iwannadie = 1;\r
+       xbt_thread_context_swap(context);\r
+}\r
+\r
+/** \r
+ * \param context the winner\r
+ *\r
+ * Calling this function blocks the current context and schedule \a context.  \r
+ * When \a context will call xbt_context_yield, it will return\r
+ * to this function as if nothing had happened.\r
+ * \r
+ * Only the maestro can call this function to run a given process.\r
+ */\r
+static void \r
+xbt_thread_context_schedule(xbt_context_t context)\r
+{\r
+       xbt_assert0((current_context == maestro_context),"You are not supposed to run this function here!");\r
+       xbt_thread_context_swap(context);\r
+}\r
+\r
+/** \r
+ * Calling this function makes the current context yield. The context\r
+ * that scheduled it returns from xbt_context_schedule as if nothing\r
+ * had happened.\r
+ * \r
+ * Only the processes can call this function, giving back the control\r
+ * to the maestro\r
+ */\r
+static void \r
+xbt_thread_context_yield(void)\r
+{\r
+       xbt_assert0((current_context != maestro_context),"You are not supposed to run this function here!");\r
+       xbt_thread_context_swap(current_context);\r
+}\r
+\r
+static void \r
+xbt_thread_context_start(xbt_context_t context)\r
+{\r
+       xbt_thread_context_t thread_context = (xbt_thread_context_t)context;\r
+       \r
+       /* create and start the process */\r
+       thread_context->thread = xbt_os_thread_create(thread_context->name,xbt_thread_context_wrapper,thread_context);\r
+       \r
+       /* wait the starting of the newly created process */\r
+       xbt_os_sem_acquire(thread_context->end);\r
+}\r
+\r
+static void \r
+xbt_thread_context_stop(int exit_code)\r
+{\r
+       if(current_context->cleanup_func) \r
+               ((*current_context->cleanup_func))(current_context->cleanup_arg);\r
+       \r
+       xbt_swag_remove(current_context, context_living);\r
+       xbt_swag_insert(current_context, context_to_destroy);   \r
+\r
+       /* signal to the maestro that it has finished */\r
+       xbt_os_sem_release(((xbt_thread_context_t)current_context)->end);\r
+       \r
+       /* exit*/\r
+       xbt_os_thread_exit(NULL);       /* We should provide return value in case other wants it */\r
+}\r
+\r
+static void \r
+xbt_thread_context_swap(xbt_context_t context)\r
+{\r
+       if((current_context != maestro_context) && !context->iwannadie)\r
+       {\r
+               /* (0) it's not the scheduler and the process doesn't want to die, it just wants to yield */\r
+               \r
+               /* yield itself, resume the maestro */\r
+               xbt_thread_context_suspend(context);\r
+       }\r
+       else\r
+       {\r
+               /* (1) the current process is the scheduler and the process doesn't want to die\r
+                *      <-> the maestro wants to schedule the process\r
+                *              -> the maestro schedules the process and waits\r
+                *\r
+                * (2) the current process is the scheduler and the process wants to die\r
+                *      <-> the maestro wants to kill the process (has called the function xbt_context_kill())\r
+                *              -> the maestro schedule the process and waits (xbt_os_sem_acquire(context->end))\r
+                *              -> if the process stops (xbt_context_stop())\r
+                *                      -> the process resumes the maestro (xbt_os_sem_release(current_context->end)) and exit (xbt_os_thread_exit())\r
+                *              -> else the process call xbt_context_yield()\r
+                *                      -> goto (3.1)\r
+                *\r
+                * (3) the current process is not the scheduler and the process wants to die\r
+                *              -> (3.1) if the current process is the process who wants to die\r
+                *                      -> (resume not need) goto (4)\r
+                *              -> (3.2) else the current process is not the process who wants to die\r
+                *                      <-> the current process wants to kill an other process\r
+                *                              -> the current process resumes the process to die and waits\r
+                *                              -> if the process to kill stops\r
+                *                                      -> it resumes the process who kill it and exit\r
+                *                              -> else if the process to kill calls to xbt_context_yield()\r
+                *                                      -> goto (3.1)\r
+                */\r
+               /* schedule the process associated with this context */\r
+               xbt_thread_context_resume(context);\r
+       \r
+       }\r
+       \r
+       /* (4) the current process wants to die */\r
+       if(current_context->iwannadie)\r
+               xbt_thread_context_stop(1);\r
+}\r
+\r
+static void* \r
+xbt_thread_context_wrapper(void* param)\r
+{\r
+       xbt_thread_context_t context = (xbt_thread_context_t)param;\r
+       \r
+       /* signal its starting to the maestro and wait to start its job*/\r
+       xbt_os_sem_release(context->end);               \r
+       xbt_os_sem_acquire(context->begin);\r
+       \r
+       if (context->startup_func)\r
+               (*(context->startup_func))(context->startup_arg);\r
+       \r
+       \r
+       xbt_thread_context_stop((context->code) (context->argc, context->argv));\r
+       return NULL;\r
+}\r
+\r
+static void\r
+xbt_thread_context_suspend(xbt_context_t context)\r
+{\r
+       /* save the current context */\r
+       xbt_context_t self = current_context;\r
+       \r
+       /* update the current context to this context */\r
+       current_context = context;\r
+       \r
+       xbt_os_sem_release(((xbt_thread_context_t)context)->end);       \r
+       xbt_os_sem_acquire(((xbt_thread_context_t)context)->begin);\r
+       \r
+       /* restore the current context to the previously saved context */\r
+       current_context = self;         \r
+}\r
+\r
+static void\r
+xbt_thread_context_resume(xbt_context_t context)\r
+{\r
+       /* save the current context */\r
+       xbt_context_t self = current_context;\r
+       \r
+       /* update the current context */\r
+       current_context = context;\r
+       \r
+       xbt_os_sem_release(((xbt_thread_context_t)context)->begin);             \r
+       xbt_os_sem_acquire(((xbt_thread_context_t)context)->end);\r
+       \r
+       /* restore the current context to the previously saved context */\r
+       current_context = self;\r
+}\r
+\r
+\r
+\r
diff --git a/src/xbt/xbt_thread_context.h b/src/xbt/xbt_thread_context.h
new file mode 100644 (file)
index 0000000..fa08f17
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef _XBT_THREAD_CONTEXT_H\r
+#define _XBT_THREAD_CONTEXT_H\r
+\r
+#include "portable.h"                  /* loads context system definitions                                                                                                                     */\r
+#include "xbt/xbt_os_thread.h"         /* declaration of the xbt native semaphore and native thread                                                            */\r
+#include "xbt/swag.h"\r
+\r
+\r
+#ifndef _XBT_CONTEXT_PRIVATE_H\r
+/*#include "xbt_context_private.h"*/\r
+#endif /* _XBT_CONTEXT_PRIVATE_H */\r
+\r
+SG_BEGIN_DECL()\r
+\r
+#ifndef _XBT_CONTEXT_FACTORY_T_DEFINED\r
+typedef struct s_xbt_context_factory* xbt_context_factory_t;\r
+#define _XBT_CONTEXT_FACTORY_T_DEFINED\r
+#endif /* !_XBT_CONTEXT_FACTORY_T_DEFINED */\r
+\r
+\r
+typedef struct s_xbt_thread_context\r
+{\r
+       XBT_CTX_BASE_T;\r
+       xbt_os_thread_t thread;                 /* a plain dumb thread (portable to posix or windows)                                                                           */\r
+       xbt_os_sem_t begin;                             /* this semaphore is used to schedule/yield the process                                                                         */\r
+       xbt_os_sem_t end;                               /* this semaphore is used to schedule/unschedule the process                                                            */\r
+}s_xbt_thread_context_t,* xbt_thread_context_t;\r
+\r
+int\r
+xbt_thread_context_factory_init(xbt_context_factory_t* factory);\r
+\r
+SG_END_DECL()\r
+\r
+#endif /* !_XBT_THREAD_CONTEXT_H */\r
diff --git a/src/xbt/xbt_ucontext.c b/src/xbt/xbt_ucontext.c
new file mode 100644 (file)
index 0000000..bdfa830
--- /dev/null
@@ -0,0 +1,288 @@
+\r
+#include "ucontext_stack.h"\r
+\r
+/* callback: context fetching */\r
+static ex_ctx_t*\r
+xbt_jcontext_ex_ctx(void);\r
+\r
+/* callback: termination */\r
+static void \r
+xbt_jcontext_ex_terminate(xbt_ex_t *e);\r
+\r
+static xbt_context_t \r
+xbt_ucontext_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);\r
+\r
+static int\r
+xbt_ucontext_factory_finalize(xbt_context_factory_t* factory);\r
+\r
+static int \r
+xbt_ucontext_factory_create_maestro_context(xbt_context_t* maestro);\r
+\r
+static void \r
+xbt_ucontext_free(xbt_context_t context);\r
+\r
+static void \r
+xbt_ucontext_kill(xbt_context_t context);\r
+\r
+static void \r
+xbt_ucontext_schedule(xbt_context_t context);\r
+\r
+static void \r
+xbt_ucontext_yield(void);\r
+\r
+static void \r
+xbt_ucontext_start(xbt_context_t context);\r
+\r
+static void \r
+xbt_ucontext_stop(int exit_code);\r
+\r
+static void \r
+xbt_ucontext_swap(xbt_context_t context);\r
+\r
+static void\r
+xbt_ucontext_schedule(xbt_context_t context);\r
+\r
+static void\r
+xbt_ucontext_yield(void);\r
+\r
+static void\r
+xbt_ucontext_suspend(xbt_context_t context);\r
+\r
+static void\r
+xbt_ucontext_resume(xbt_context_t context);\r
+\r
+static void* \r
+xbt_ucontext_wrapper(void* param);\r
+\r
+/* callback: context fetching */\r
+static ex_ctx_t*\r
+xbt_ucontext_ex_ctx(void) \r
+{\r
+       return current_context->exception;\r
+}\r
+\r
+/* callback: termination */\r
+static void \r
+xbt_ucontext_ex_terminate(xbt_ex_t *e) \r
+{\r
+       xbt_ex_display(e);\r
+       abort();\r
+}\r
+\r
+\r
+int\r
+xbt_ucontext_factory_init(xbt_context_factory_t* factory)\r
+{\r
+       /* context exception */\r
+       *factory = xbt_new0(s_xbt_context_factory_t,1);\r
+       \r
+       (*factory)->create_context = xbt_ucontext_factory_create_context;\r
+       (*factory)->finalize = xbt_ucontext_factory_finalize;\r
+       (*factory)->create_maestro_context = xbt_ucontext_factory_create_maestro_context;\r
+       (*factory)->name = "ucontext_context_factory";\r
+       \r
+       /* context exception handlers */\r
+       __xbt_ex_ctx       = xbt_ucontext_ex_ctx;\r
+    __xbt_ex_terminate = xbt_ucontext_ex_terminate;    \r
+    \r
+       return 0;\r
+}\r
+\r
+static int \r
+xbt_ucontext_factory_create_maestro_context(xbt_context_t* maestro)\r
+{\r
+               \r
+       xbt_ucontext_t context = xbt_new0(s_xbt_ucontext_t, 1);\r
+       \r
+       context->exception = xbt_new(ex_ctx_t,1);\r
+    XBT_CTX_INITIALIZE(context->exception);\r
+    \r
+    *maestro = (xbt_context_t)context;\r
+    \r
+    return 0;\r
+    \r
+}\r
+\r
+\r
+static int\r
+xbt_ucontext_factory_finalize(xbt_context_factory_t* factory)\r
+{\r
+       free(maestro_context->exception);\r
+       free(*factory);\r
+       *factory = NULL;\r
+       return 0;\r
+}\r
+\r
+static xbt_context_t \r
+xbt_ucontext_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)\r
+{\r
+       xbt_ucontext_t context = xbt_new0(s_xbt_ucontext_t, 1);\r
+       \r
+       context->code = code;\r
+       context->name = xbt_strdup(name);\r
+       \r
+       xbt_assert2(getcontext(&(context->uc)) == 0,"Error in context saving: %d (%s)", errno, strerror(errno));\r
+       context->uc.uc_link = NULL;\r
+       context->uc.uc_stack.ss_sp = pth_skaddr_makecontext(context->stack, STACK_SIZE);\r
+       context->uc.uc_stack.ss_size = pth_sksize_makecontext(context->stack, STACK_SIZE);\r
+       \r
+       context->exception = xbt_new(ex_ctx_t, 1);\r
+       XBT_CTX_INITIALIZE(context->exception);\r
+       context->iwannadie = 0;           /* useless but makes valgrind happy */\r
+       context->argc = argc;\r
+       context->argv = argv;\r
+       context->startup_func = startup_func;\r
+       context->startup_arg = startup_arg;\r
+       context->cleanup_func = cleanup_func;\r
+       context->cleanup_arg = cleanup_arg;\r
+       \r
+       \r
+       context->free = xbt_ucontext_free;                      \r
+       context->kill = xbt_ucontext_kill;                      \r
+       context->schedule = xbt_ucontext_schedule;\r
+       context->yield = xbt_ucontext_yield;                    \r
+       context->start = xbt_ucontext_start;                    \r
+       context->stop = xbt_ucontext_stop;                      \r
+       \r
+       return (xbt_context_t)context;\r
+}\r
+\r
+static void \r
+xbt_ucontext_free(xbt_context_t context)\r
+{\r
+       if(context)\r
+       {\r
+               free(context->name);\r
+               \r
+               if(context->argv)\r
+               {\r
+                       int i;\r
+                       \r
+                       for(i = 0; i < context->argc; i++)\r
+                               if(context->argv[i])\r
+                                       free(context->argv[i]);\r
+                                       \r
+                       free(context->argv);\r
+               }\r
+               \r
+               if(context->exception) \r
+                       free(context->exception);\r
+               \r
+               /* finally destroy the context */\r
+               free(context);\r
+       }\r
+}\r
+\r
+static void \r
+xbt_ucontext_kill(xbt_context_t context)\r
+{\r
+       context->iwannadie = 1;\r
+       xbt_ucontext_swap(context);\r
+}\r
+\r
+/** \r
+ * \param context the winner\r
+ *\r
+ * Calling this function blocks the current context and schedule \a context.  \r
+ * When \a context will call xbt_context_yield, it will return\r
+ * to this function as if nothing had happened.\r
+ * \r
+ * Only the maestro can call this function to run a given process.\r
+ */\r
+static void \r
+xbt_ucontext_schedule(xbt_context_t context)\r
+{\r
+       xbt_assert0((current_context == maestro_context),"You are not supposed to run this function here!");\r
+       xbt_ucontext_swap(context);\r
+}\r
+\r
+/** \r
+ * Calling this function makes the current context yield. The context\r
+ * that scheduled it returns from xbt_context_schedule as if nothing\r
+ * had happened.\r
+ * \r
+ * Only the processes can call this function, giving back the control\r
+ * to the maestro\r
+ */\r
+static void \r
+xbt_ucontext_yield(void)\r
+{\r
+       xbt_assert0((current_context != maestro_context),"You are not supposed to run this function here!");\r
+       xbt_ucontext_swap(current_context);\r
+}\r
+\r
+static void \r
+xbt_ucontext_start(xbt_context_t context)\r
+{\r
+       makecontext(&(((xbt_ucontext_t)context)->uc), (void (*)(void)) xbt_ucontext_wrapper, 1, context);\r
+}\r
+\r
+static void \r
+xbt_ucontext_stop(int exit_code)\r
+{\r
+       if(current_context->cleanup_func) \r
+               ((*current_context->cleanup_func))(current_context->cleanup_arg);\r
+       \r
+       xbt_swag_remove(current_context, context_living);\r
+       xbt_swag_insert(current_context, context_to_destroy);   \r
+       \r
+       xbt_ucontext_swap(current_context);\r
+}\r
+\r
+static void \r
+xbt_ucontext_swap(xbt_context_t context)\r
+{\r
+       xbt_assert0(current_context, "You have to call context_init() first.");\r
+       xbt_assert0(context, "Invalid argument");\r
+       \r
+       if(((xbt_ucontext_t)context)->prev == NULL) \r
+               xbt_ucontext_resume(context);\r
+       else \r
+               xbt_ucontext_suspend(context);\r
+       \r
+       if(current_context->iwannadie)\r
+               xbt_ucontext_stop(1);\r
+}\r
+\r
+static void* \r
+xbt_ucontext_wrapper(void* param)\r
+{\r
+       if (current_context->startup_func)\r
+               (*current_context->startup_func)(current_context->startup_arg);\r
+       \r
+       xbt_ucontext_stop((*(current_context->code))(current_context->argc, current_context->argv));\r
+       return NULL;\r
+}\r
+\r
+static void\r
+xbt_ucontext_suspend(xbt_context_t context)\r
+{\r
+       int rv;\r
+       \r
+       xbt_ucontext_t prev_context = ((xbt_ucontext_t)context)->prev;\r
+       \r
+       current_context = (xbt_context_t)(((xbt_ucontext_t)context)->prev);\r
+       \r
+       ((xbt_ucontext_t)context)->prev = NULL;\r
+       \r
+       rv = swapcontext(&(((xbt_ucontext_t)context)->uc), &(prev_context->uc));\r
+               \r
+       xbt_assert0((rv == 0), "Context swapping failure");\r
+}\r
+\r
+static void\r
+xbt_ucontext_resume(xbt_context_t context)\r
+{\r
+       int rv;\r
+       \r
+       ((xbt_ucontext_t)context)->prev = (xbt_ucontext_t)current_context;\r
+       \r
+       current_context = context;\r
+       \r
+       rv = swapcontext(&(((xbt_ucontext_t)context)->prev->uc), &(((xbt_ucontext_t)context)->uc));\r
+               \r
+       xbt_assert0((rv == 0), "Context swapping failure");\r
+}\r
+\r
+\r
+\r
diff --git a/src/xbt/xbt_ucontext.h b/src/xbt/xbt_ucontext.h
new file mode 100644 (file)
index 0000000..b2ce72f
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef _XBT_UCONTEXT_H\r
+#define _XBT_UCONTEXT_H\r
+\r
+#include "ucontext_stack.h"            /* loads context system definitions                                                                                                                     */\r
+#include <ucontext.h>                  /* context relative declarations                                                                                                                        */                              \r
+#define STACK_SIZE 128*1024            /* lower this if you want to reduce the memory consumption                                                                      */\r
+\r
+#ifndef _XBT_CONTEXT_FACTORY_T_DEFINED\r
+typedef struct s_xbt_context_factory* xbt_context_factory_t;\r
+#define _XBT_CONTEXT_FACTORY_T_DEFINED\r
+#endif /* !_XBT_CONTEXT_FACTORY_T_DEFINED */\r
+\r
+typedef struct s_xbt_ucontext\r
+{\r
+       XBT_CTX_BASE_T;\r
+       ucontext_t uc;                                  /* the thread that execute the code                                                                                                                     */\r
+       char stack[STACK_SIZE];                 /* the thread stack size                                                                                                                                        */\r
+       struct s_xbt_ucontext* prev;            /* the previous thread                                                                                                                                  */\r
+}s_xbt_ucontext_t,* xbt_ucontext_t;\r
+\r
+\r
+int\r
+xbt_ucontext_factory_init(xbt_context_factory_t* factory);\r
+\r
+SG_END_DECL()\r
+\r
+#endif /* !_XBT_UCONTEXT_H */\r