Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Some polishing to the new context factory API to avoid accesing simix
authormquinson <mquinson@48e7efb5-ca39-0410-a469-dd3cf9ba447f>
Mon, 17 Aug 2009 09:24:20 +0000 (09:24 +0000)
committermquinson <mquinson@48e7efb5-ca39-0410-a469-dd3cf9ba447f>
Mon, 17 Aug 2009 09:24:20 +0000 (09:24 +0000)
data structures from the context implementations.

git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/simgrid/simgrid/trunk@6562 48e7efb5-ca39-0410-a469-dd3cf9ba447f

src/simix/private.h
src/simix/smx_context_sysv.c
src/simix/smx_context_thread.c
src/simix/smx_process.c

index 5a635c3..da4b964 100644 (file)
@@ -67,8 +67,6 @@ typedef struct s_smx_context *smx_context_t;
        char *name;              /**< @brief process name if any */
        smx_host_t smx_host;     /* the host on which the process is running */
        smx_context_t context;   /* the context that executes the scheduler function */
-       int argc;                /* arguments number if any */
-       char **argv;             /* arguments table if any */
        int blocked : 1;
        int suspended : 1;
        int iwannadie : 1;
@@ -76,8 +74,6 @@ typedef struct s_smx_context *smx_context_t;
        smx_cond_t cond;         /* cond on which the process is blocked  */
        xbt_dict_t properties;
        void *data;              /* kept for compatibility, it should be replaced with moddata */
-       void_f_pvoid_t cleanup_func;
-       void *cleanup_arg;
 
      } s_smx_process_t;
 /** @} */
@@ -165,6 +161,10 @@ void SIMIX_context_mod_exit(void);
   s_xbt_swag_hookup_t hookup; \
   ex_ctx_t *exception; \
   xbt_main_func_t code; \
+  int argc; \
+  char **argv; \
+  void_f_pvoid_t cleanup_func; \
+  void *cleanup_arg; \
 
 /* all other context types derive from this structure */
 typedef struct s_smx_context {
@@ -189,7 +189,8 @@ typedef struct s_smx_context {
  */
 
 /* function used to create a new context */
-typedef smx_context_t (*smx_pfn_context_factory_create_context_t) (xbt_main_func_t);
+typedef smx_context_t (*smx_pfn_context_factory_create_context_t) 
+                      (xbt_main_func_t, int, char**, void_f_pvoid_t, void*);
 
 /* function used to create the context for the maestro process */
 typedef smx_context_t (*smx_pfn_context_factory_create_maestro_context_t) (void);
@@ -204,7 +205,7 @@ typedef void (*smx_pfn_context_free_t) (smx_context_t);
 typedef void (*smx_pfn_context_start_t) (smx_context_t);
 
 /* function used to stop the current context */
-typedef void (*smx_pfn_context_stop_t) (int);
+typedef void (*smx_pfn_context_stop_t) (smx_context_t);
 
 /* function used to suspend the current context */
 typedef void (*smx_pfn_context_suspend_t) (smx_context_t context);
@@ -243,12 +244,29 @@ void SIMIX_ctx_sysv_factory_init(smx_context_factory_t * factory);
 
 void SIMIX_ctx_java_factory_init(smx_context_factory_t * factory);
 
-/* ******************************* */
-/* contexts manipulation functions */
-/* ******************************* */
+/* ****************************** */
+/* context manipulation functions */
+/* ****************************** */
+
+/* Scenario for the end of a context:
+ *
+ * CASE 1: death after end of the main function
+ *   the context_wrapper, called internally by the context module, calls 
+ *   SIMIX_context_stop after user code stops, smx_context_stop calls user 
+ *   cleanup_func if any (in context settings), add current process to trashbin
+ *   and yields back to maestro.
+ *   From time to time, maestro calls SIMIX_context_empty_trash, which destroy
+ *   all the process and context data structures, and frees the memory 
+ *
+ * CASE 2: brutal death
+ *   SIMIX_process_kill (from any process) set process->iwannadie = 1 and then
+ *   schedules the process. Then the process is awaken in the middle of the
+ *   SIMIX_process_yield function, and at the end of it, it checks that
+ *   iwannadie == 1, and call SIMIX_context_stop(same than first case afterward)
+ */
 
 /**
- * \param smx_process the simix maestro process that contains this context
+ * \brief creates the context for the maestro process
  */
 static inline smx_context_t SIMIX_context_create_maestro()
 {
@@ -256,63 +274,67 @@ static inline smx_context_t SIMIX_context_create_maestro()
 }
 
 /**
- * \param smx_process the simix process that contains this context
+ * \brief creates a new context for a user level process
  * \param code a main function
+ * \param argc the number of arguments of the main function
+ * \param argv the vector of arguments of the main function
+ * \param cleanup_func the function to call when the context stops
+ * \param cleanup_arg the argument of the cleanup_func function
  */
-static inline smx_context_t SIMIX_context_new(xbt_main_func_t code)
+static inline smx_context_t SIMIX_context_new(xbt_main_func_t code, int argc,
+                                              char** argv,
+                                              void_f_pvoid_t cleanup_func,
+                                              void* cleanup_arg)
 {
-    return (*(simix_global->context_factory->create_context)) (code);
+  return (*(simix_global->context_factory->create_context))
+           (code, argc, argv, cleanup_func, cleanup_arg);
 }
 
-/* Scenario for the end of a context:
- *
- * CASE 1: death after end of function
- *   __context_wrapper, called by os thread, calls smx_context_stop after user code stops
- *   smx_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 smx_context_empty_trash,
- *       which maps smx_context_free on the content
- *   smx_context_free frees some more memory,
- *                    joins os thread
- *
- * CASE 2: brutal death
- *   smx_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 smx_context_stop
- *   (same than first case afterward)
+/**
+ * \brief destroy a context 
+ * \param context the context to destroy
+ * Argument must be stopped first -- runs in maestro context
  */
-
-/* Argument must be stopped first -- runs in maestro context */
 static inline void SIMIX_context_free(smx_context_t context)
 {
   (*(simix_global->context_factory->free)) (context);
 }
 
 /**
+ * \brief prepares aa context to be run
  * \param context the context to start
- *
- * Calling this function prepares \a process to be run. It will
-   however run effectively only when calling #SIMIX_context_schedule
+ * It will however run effectively only when calling #SIMIX_process_schedule
  */
 static inline void SIMIX_context_start(smx_context_t context)
 {
   (*(simix_global->context_factory->start)) (context);
 }
 
-static inline void SIMIX_context_stop(int exit_code)
+/**
+ * \brief stops the execution of a context
+ * \param context to stop
+ */
+static inline void SIMIX_context_stop(smx_context_t context)
 {
-  (*(simix_global->context_factory->stop)) (exit_code);
+  (*(simix_global->context_factory->stop)) (context);
 }
 
+/**
+ \brief resumes the execution of a context
+ \param old_context the actual context from which is resuming
+ \param new_context the context to resume
+ */
 static inline void SIMIX_context_resume(smx_context_t old_context,
                                         smx_context_t new_context)
 {
   (*(simix_global->context_factory->resume)) (old_context, new_context);
 }
 
+/**
+ \brief suspends a context and return the control back to the one which
+        scheduled it
+ \param context the context to be suspended (it must be the running one)
+ */
 static inline void SIMIX_context_suspend(smx_context_t context)
 {
   (*(simix_global->context_factory->suspend)) (context);
index 50b5824..418dbdb 100644 (file)
@@ -9,11 +9,13 @@
 
 #include "xbt/ex_interface.h"
 #include "private.h"
-
-#include "context_sysv_config.h"        /* loads context system definitions                             */
+#include "context_sysv_config.h"        /* loads context system definitions */
 #include "portable.h"
-#include <ucontext.h>           /* context relative declarations                                */
-#define STACK_SIZE 128*1024     /* lower this if you want to reduce the memory consumption      */
+#include <ucontext.h>           /* context relative declarations */
+
+/* lower this if you want to reduce the memory consumption  */
+#define STACK_SIZE 128*1024
+
 #ifdef HAVE_VALGRIND_VALGRIND_H
 #  include <valgrind/valgrind.h>
 #endif /* HAVE_VALGRIND_VALGRIND_H */
@@ -37,7 +39,9 @@ static ex_ctx_t *xbt_jcontext_ex_ctx(void);
 /* callback: termination */
 static void xbt_jcontext_ex_terminate(xbt_ex_t *e);
 
-static smx_context_t smx_ctx_sysv_factory_create_context(xbt_main_func_t code);
+static smx_context_t 
+smx_ctx_sysv_factory_create_context(xbt_main_func_t code, int argc, char** argv, 
+                                    void_f_pvoid_t cleanup_func, void* cleanup_arg);
 
 static int smx_ctx_sysv_factory_finalize(smx_context_factory_t *factory);
 
@@ -47,18 +51,19 @@ static void smx_ctx_sysv_free(smx_context_t context);
 
 static void smx_ctx_sysv_start(smx_context_t context);
 
-static void smx_ctx_sysv_stop(int exit_code);
+static void smx_ctx_sysv_stop(smx_context_t context);
 
 static void smx_ctx_sysv_suspend(smx_context_t context);
 
-static void smx_ctx_sysv_resume(smx_context_t old_context,
-                                smx_context_t new_context);
+static void 
+  smx_ctx_sysv_resume(smx_context_t old_context, smx_context_t new_context);
 
 static void smx_ctx_sysv_wrapper(void);
 
 /* callback: context fetching */
 static ex_ctx_t *xbt_ctx_sysv_ex_ctx(void)
 {
+  /*FIXME: the factory should access simix level datastructures! */
   return simix_global->current_process->context->exception;
 }
 
@@ -106,7 +111,9 @@ static int smx_ctx_sysv_factory_finalize(smx_context_factory_t * factory)
   return 0;
 }
 
-static smx_context_t smx_ctx_sysv_factory_create_context(xbt_main_func_t code)
+static smx_context_t 
+smx_ctx_sysv_factory_create_context(xbt_main_func_t code, int argc, char** argv, 
+                                    void_f_pvoid_t cleanup_func, void* cleanup_arg)
 {
   smx_ctx_sysv_t context = xbt_new0(s_smx_ctx_sysv_t, 1);
 
@@ -128,12 +135,16 @@ static smx_context_t smx_ctx_sysv_factory_create_context(xbt_main_func_t code)
 
   context->exception = xbt_new(ex_ctx_t, 1);
   XBT_CTX_INITIALIZE(context->exception);
-  
+  context->argc = argc;
+  context->argv = argv;
+  context->cleanup_func = cleanup_func;
+  context->cleanup_arg = cleanup_arg;
   return (smx_context_t)context;
 }
 
 static void smx_ctx_sysv_free(smx_context_t pcontext)
 {
+  int i;
   smx_ctx_sysv_t context = (smx_ctx_sysv_t)pcontext;   
   if (context){
 
@@ -144,30 +155,50 @@ static void smx_ctx_sysv_free(smx_context_t pcontext)
     VALGRIND_STACK_DEREGISTER(((smx_ctx_sysv_t) context)->valgrind_stack_id);
 #endif /* HAVE_VALGRIND_VALGRIND_H */
 
+    /* free argv */
+    if (context->argv) {
+      for (i = 0; i < context->argc; i++)
+        if (context->argv[i])
+          free(context->argv[i]);
+
+      free(context->argv);
+    }
+    
     /* destroy the context */
     free(context);
   }
 }
 
 static void smx_ctx_sysv_start(smx_context_t context)
-{
+{  
   makecontext(&((smx_ctx_sysv_t)context)->uc, smx_ctx_sysv_wrapper, 0);
 }
 
-static void smx_ctx_sysv_stop(int exit_code)
+static void smx_ctx_sysv_stop(smx_context_t pcontext)
 {
-  if (simix_global->current_process->cleanup_func)
-    ((*simix_global->current_process->cleanup_func))
-      (simix_global->current_process->cleanup_arg);
+  smx_ctx_sysv_t context = (smx_ctx_sysv_t)pcontext;
+  
+  if (context->cleanup_func)
+    (*context->cleanup_func) (context->cleanup_arg);
 
-  smx_ctx_sysv_suspend(simix_global->current_process->context);
+  smx_ctx_sysv_suspend((smx_context_t)context);
 }
 
-static void smx_ctx_sysv_wrapper(void)
+static void smx_ctx_sysv_wrapper()
 {
-  smx_ctx_sysv_stop((*(simix_global->current_process->context->code))
-                        (simix_global->current_process->argc, 
-                         simix_global->current_process->argv));
+  /*FIXME: I would like to avoid accesing simix_global to get the current
+    context by passing it as an argument of the wrapper function. The problem
+    is that this function is called from smx_ctx_sysv_start, and uses
+    makecontext for calling it, and the stupid posix specification states that
+    all the arguments of the function should be int(32 bits), making it useless
+    in 64-bit architectures where pointers are 64 bit long.
+   */
+  smx_ctx_sysv_t context = 
+    (smx_ctx_sysv_t)simix_global->current_process->context;
+  
+  (context->code) (context->argc, context->argv);
+  
+  smx_ctx_sysv_stop((smx_context_t)context);
 }
 
 static void smx_ctx_sysv_suspend(smx_context_t context)
@@ -183,8 +214,8 @@ static void smx_ctx_sysv_suspend(smx_context_t context)
   xbt_assert0((rv == 0), "Context swapping failure");
 }
 
-static void smx_ctx_sysv_resume(smx_context_t old_context,
-                                smx_context_t new_context)
+static void 
+smx_ctx_sysv_resume(smx_context_t old_context, smx_context_t new_context)
 {
   int rv;
 
index 5647ffd..9bd06d6 100644 (file)
@@ -23,7 +23,9 @@ typedef struct s_smx_ctx_thread {
   xbt_os_sem_t end;             /* this semaphore is used to schedule/unschedule the process   */
 } s_smx_ctx_thread_t, *smx_ctx_thread_t;
 
-static smx_context_t smx_ctx_thread_factory_create_context(xbt_main_func_t code);
+static smx_context_t
+smx_ctx_thread_factory_create_context(xbt_main_func_t code, int argc, char** argv, 
+                                      void_f_pvoid_t cleanup_func, void* cleanup_arg);
 
 static smx_context_t smx_ctx_thread_factory_create_master_context(void);
 
@@ -33,12 +35,12 @@ static void smx_ctx_thread_free(smx_context_t context);
 
 static void smx_ctx_thread_start(smx_context_t context);
 
-static void smx_ctx_thread_stop(int exit_code);
+static void smx_ctx_thread_stop(smx_context_t context);
 
 static void smx_ctx_thread_suspend(smx_context_t context);
 
-static void smx_ctx_thread_resume(smx_context_t old_context,
-                                  smx_context_t new_context);
+static void 
+  smx_ctx_thread_resume(smx_context_t old_context, smx_context_t new_context);
 
 static void *smx_ctx_thread_wrapper(void *param);
 
@@ -69,11 +71,17 @@ static int smx_ctx_thread_factory_finalize(smx_context_factory_t * factory)
   return 0;
 }
 
-static smx_context_t smx_ctx_thread_factory_create_context(xbt_main_func_t code)
+static smx_context_t 
+smx_ctx_thread_factory_create_context(xbt_main_func_t code, int argc, char** argv, 
+                                      void_f_pvoid_t cleanup_func, void* cleanup_arg)
 {
   smx_ctx_thread_t context = xbt_new0(s_smx_ctx_thread_t, 1);
 
   context->code = code;
+  context->argc = argc;
+  context->argv = argv;
+  context->cleanup_func = cleanup_func;
+  context->cleanup_arg = cleanup_arg;
   context->begin = xbt_os_sem_init(0);
   context->end = xbt_os_sem_init(0);
 
@@ -82,18 +90,27 @@ static smx_context_t smx_ctx_thread_factory_create_context(xbt_main_func_t code)
 
 static void smx_ctx_thread_free(smx_context_t pcontext)
 {
+  int i;
   smx_ctx_thread_t context = (smx_ctx_thread_t)pcontext;
 
-  /* Check if this is the context of maestro (it doesn't has a real thread) */  
+  /* check if this is the context of maestro (it doesn't has a real thread) */  
   if (context->thread) {
     /* wait about the thread terminason */
     xbt_os_thread_join(context->thread, NULL);
-    free(context->thread);
     
     /* destroy the synchronisation objects */
     xbt_os_sem_destroy(context->begin);
     xbt_os_sem_destroy(context->end);
   }
+  
+  /* free argv */
+  if (context->argv) {
+    for (i = 0; i < context->argc; i++)
+      if (context->argv[i])
+        free(context->argv[i]);
+
+    free(context->argv);
+  }
     
   /* finally destroy the context */
   free(context);
@@ -105,7 +122,7 @@ static void smx_ctx_thread_start(smx_context_t context)
 
   /* create and start the process */
   /* NOTE: The first argument to xbt_os_thread_create used to be the process *
-   * name, but now the name is stored at simix level, so we pass a null      */
+   * name, but now the name is stored at SIMIX level, so we pass a null      */
   ctx_thread->thread =
     xbt_os_thread_create(NULL, smx_ctx_thread_wrapper, ctx_thread);
 
@@ -113,17 +130,21 @@ static void smx_ctx_thread_start(smx_context_t context)
   xbt_os_sem_acquire(ctx_thread->end);
 }
 
-static void smx_ctx_thread_stop(int exit_code)
+static void smx_ctx_thread_stop(smx_context_t pcontext)
 {
+
+  smx_ctx_thread_t context = (smx_ctx_thread_t)pcontext;
+  
   /* please no debug here: our procdata was already free'd */
-  if (simix_global->current_process->cleanup_func)
-    (*simix_global->current_process->cleanup_func) (simix_global->current_process->cleanup_arg);
+  if (context->cleanup_func)
+    (*context->cleanup_func) (context->cleanup_arg);
 
   /* signal to the maestro that it has finished */
-  xbt_os_sem_release(((smx_ctx_thread_t) simix_global->current_process->context)->end);
+  xbt_os_sem_release(((smx_ctx_thread_t) context)->end);
 
   /* exit */
-  xbt_os_thread_exit(NULL);     /* We should provide return value in case other wants it */
+  /* We should provide return value in case other wants it */
+  xbt_os_thread_exit(NULL);     
 }
 
 static void *smx_ctx_thread_wrapper(void *param)
@@ -134,8 +155,9 @@ static void *smx_ctx_thread_wrapper(void *param)
   xbt_os_sem_release(context->end);
   xbt_os_sem_acquire(context->begin);
 
-  smx_ctx_thread_stop((context->code) (simix_global->current_process->argc, 
-                                       simix_global->current_process->argv));
+  (context->code) (context->argc, context->argv);
+
+  smx_ctx_thread_stop((smx_context_t)context);
   return NULL;
 }
 
index 80fac61..e3cc9ce 100644 (file)
@@ -36,20 +36,11 @@ void SIMIX_process_cleanup(void *arg)
 void SIMIX_process_empty_trash(void)
 { 
   smx_process_t process = NULL;
-  int i;  
 
   while ((process = xbt_swag_extract(simix_global->process_to_destroy))){
+    SIMIX_context_free(process->context);
     free(process->name);
     process->name = NULL;
-  
-    if (process->argv) {
-      for (i = 0; i < process->argc; i++)
-        if (process->argv[i])
-          free(process->argv[i]);
-
-      free(process->argv);
-    }
-  
     free(process);
   }
 }
@@ -111,18 +102,16 @@ smx_process_t SIMIX_process_create(const char *name,
   /* Process data */
   process->name = xbt_strdup(name);
   process->smx_host = host;
-  process->argc = argc;
-  process->argv = argv;
   process->mutex = NULL;
   process->cond = NULL;
   process->iwannadie = 0;
 
   VERB1("Create context %s", process->name);
-  process->context = SIMIX_context_new(code);
+  process->context = SIMIX_context_new(code, argc, argv, 
+                                       simix_global->cleanup_process_function,
+                                       process);
 
   process->data = data;
-  process->cleanup_func = simix_global->cleanup_process_function;
-  process->cleanup_arg = process;
 
   /* Add properties */
   process->properties = properties;
@@ -174,11 +163,9 @@ void SIMIX_jprocess_create(const char *name, smx_host_t host,
   /* Process data */
   process->name = xbt_strdup(name);
   process->smx_host = host;
-  process->argc = 0;
-  process->argv = NULL;
   process->mutex = NULL;
   process->cond = NULL;
-  SIMIX_context_new(jprocess);
+  SIMIX_context_new(jprocess, 0, NULL, NULL, NULL);
   process->data = data;
 
   /* Add the process to it's host process list */
@@ -218,7 +205,7 @@ void SIMIX_process_kill(smx_process_t process)
 
   /* If I'm killing myself then stop otherwise schedule the process to kill */
   if (process == SIMIX_process_self())
-    SIMIX_context_stop(1);
+    SIMIX_context_stop(process->context);
   else
     __SIMIX_process_schedule(process);
   
@@ -457,7 +444,7 @@ void __SIMIX_process_yield(void)
   SIMIX_context_suspend(simix_global->current_process->context);
 
   if (simix_global->current_process->iwannadie)
-    SIMIX_context_stop(1);
+    SIMIX_context_stop(simix_global->current_process->context);
 }
 
 void __SIMIX_process_schedule(smx_process_t new_process)