Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
More informative error message
[simgrid.git] / src / simix / smx_process.c
index c62f822..b2ec5c1 100644 (file)
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_process, simix,
                                 "Logging specific to SIMIX (process)");
 
-/******************************** Process ************************************/
 /**
  * \brief Move a process to the list of process to destroy. *
  */
-
 void SIMIX_process_cleanup(void *arg)
 {
   xbt_swag_remove(arg, simix_global->process_to_run);
   xbt_swag_remove(arg, simix_global->process_list);
-  xbt_swag_remove(arg, ((smx_process_t)arg)->smx_host->process_list);
+  xbt_swag_remove(arg, ((smx_process_t) arg)->smx_host->process_list);
   xbt_swag_insert(arg, simix_global->process_to_destroy);
 }
 
@@ -34,41 +32,38 @@ void SIMIX_process_cleanup(void *arg)
  * that have finished (or killed).
  */
 void SIMIX_process_empty_trash(void)
-{ 
+{
   smx_process_t process = NULL;
-  int i;  
 
-  while ((process = xbt_swag_extract(simix_global->process_to_destroy))){
+  while ((process = xbt_swag_extract(simix_global->process_to_destroy))) {
+    SIMIX_context_free(process->context);
+
+    /* Free the exception allocated at creation time */
+    if (process->exception)
+      free(process->exception);
+
     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);
   }
 }
 
 /**
  * \brief Creates and runs the maestro process
- *
  */
-
-void __SIMIX_create_maestro_process()
+void SIMIX_create_maestro_process()
 {
   smx_process_t process = NULL;
   process = xbt_new0(s_smx_process_t, 1);
 
   /* Process data */
-  process->name = (char *)"";
+  process->name = (char *) "";
+
+  process->exception = xbt_new(ex_ctx_t, 1);
+  XBT_CTX_INITIALIZE(process->exception);
 
-  /*Create the right context type (FIXME: check the return value for success)*/
-  SIMIX_context_create_maestro(&process);
+  /* Create a dummy context for maestro */
+  process->context = SIMIX_context_new(NULL, 0, NULL, NULL, NULL);
 
   /* Set it as the maestro process */
   simix_global->maestro_process = process;
@@ -83,7 +78,7 @@ void __SIMIX_create_maestro_process()
  * A constructor for #m_process_t taking four arguments and returning the corresponding object. The structure (and the corresponding thread) is created, and put in the list of ready process.
  *
  * \param name a name for the object. It is for user-level information and can be NULL.
-* \param data a pointer to any data one may want to attach to the new object.  It is for user-level information and can be NULL. It can be retrieved with the function \ref MSG_process_get_data.
+ * \param data a pointer to any data one may want to attach to the new object.  It is for user-level information and can be NULL. It can be retrieved with the function \ref MSG_process_get_data.
  * \param host the location where the new agent is executed.
  * \param argc first argument passed to \a code
  * \param argv second argument passed to \a code
@@ -112,86 +107,34 @@ 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;
+  process->data = data;
 
-  /*Create the right context type (FIXME: check the return value for success)*/
-  SIMIX_context_new(&process, code);
+  VERB1("Create context %s", process->name);
+  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;
+  process->exception = xbt_new(ex_ctx_t, 1);
+  XBT_CTX_INITIALIZE(process->exception);
 
   /* Add properties */
   process->properties = properties;
 
   /* Add the process to it's host process list */
   xbt_swag_insert(process, host->process_list);
-  
-  SIMIX_context_start(process);
-   
-  /* Now insert it in the global process list and in the process to run list */
-  xbt_swag_insert(process, simix_global->process_list);
-  DEBUG2("Inserting %s(%s) in the to_run list", process->name, host->name);
-  xbt_swag_insert(process, simix_global->process_to_run);
-
-  return process;
-}
 
-/**
- * \brief Creates and runs a new #smx_process_t hosting a JAVA thread
- *
- * Warning: this should only be used in libsimgrid4java, since it create
- * a context with no code, which leads to segfaults in plain libsimgrid
- */
-void SIMIX_jprocess_create(const char *name, smx_host_t host,
-                           void *data,
-                           void *jprocess, void *jenv, smx_process_t * res)
-{
-  smx_process_t process = xbt_new0(s_smx_process_t, 1);
-  smx_process_t self = NULL;
-
-  /* HACK: We need this trick because when we xbt_context_new() do
-     syncronization stuff, the s_process field in the m_process needs
-     to have a valid value, and we call xbt_context_new() before
-     returning, of course, ie, before providing a right value to the
-     caller (Java_simgrid_msg_Msg_processCreate) have time to store it
-     in place. This way, we initialize the m_process->simdata->s_process
-     field ourself ASAP.
-
-     All this would be much simpler if the synchronization stuff would be done
-     in the JAVA world, I think.
-   */
-  *res = process;
-
-  DEBUG5("jprocess_create(name=%s,host=%p,data=%p,jproc=%p,jenv=%p)",
-         name, host, data, jprocess, jenv);
-  xbt_assert0(host, "Invalid parameters");
-
-  /* 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(&process, jprocess);
-  process->data = data;
-
-  /* Add the process to it's host process list */
-  xbt_swag_insert(&process, host->process_list);
-
-  /* fix current_process, about which xbt_context_start mocks around */
-  self = simix_global->current_process;
-  SIMIX_context_start(process);
-  simix_global->current_process = self;
+  DEBUG1("Start context '%s'", process->name);
+  SIMIX_context_start(process->context);
 
   /* Now insert it in the global process list and in the process to run list */
   xbt_swag_insert(process, simix_global->process_list);
   DEBUG2("Inserting %s(%s) in the to_run list", process->name, host->name);
   xbt_swag_insert(process, simix_global->process_to_run);
+
+  return process;
 }
 
 /** \brief Kill a SIMIX process
@@ -204,22 +147,36 @@ void SIMIX_process_kill(smx_process_t process)
 {
   DEBUG2("Killing process %s on %s", process->name, process->smx_host->name);
 
-  /* Cleanup if we were waiting for something */
-  if (process->mutex)
-    xbt_swag_remove(process, process->mutex->sleeping);
-
-  if (process->cond)
-    xbt_swag_remove(process, process->cond->sleeping);
-
-  DEBUG2("%p here! killing %p", simix_global->current_process, process);
-
-  /*FIXME: If we are killing the running process we might call stop directly */  
   process->iwannadie = 1;
-  __SIMIX_process_schedule(process);
 
+  /* If I'm killing myself then stop otherwise schedule the process to kill
+   * Two different behaviors, if I'm killing my self, remove from mutex and condition and stop. Otherwise, first we must schedule the process, wait its ending and after remove it from mutex and condition */
   if (process == SIMIX_process_self()) {
-    /* I just killed myself */
-    SIMIX_context_yield();
+    /* Cleanup if we were waiting for something */
+    if (process->mutex)
+      xbt_swag_remove(process, process->mutex->sleeping);
+
+    if (process->cond)
+      xbt_swag_remove(process, process->cond->sleeping);
+    if (process->waiting_action) {
+      SIMIX_unregister_action_to_condition(process->waiting_action, process->cond);
+      SIMIX_action_destroy(process->waiting_action);
+    }
+    SIMIX_context_stop(process->context);
+  } else {
+    DEBUG2("%p here! killing %p", simix_global->current_process, process);
+    SIMIX_process_schedule(process);
+    /* Cleanup if we were waiting for something */
+    if (process->mutex)
+      xbt_swag_remove(process, process->mutex->sleeping);
+
+    if (process->cond)
+      xbt_swag_remove(process, process->cond->sleeping);
+
+    if (process->waiting_action) {
+      SIMIX_unregister_action_to_condition(process->waiting_action, process->cond);
+      SIMIX_action_destroy(process->waiting_action);
+    }
   }
 }
 
@@ -339,7 +296,7 @@ void SIMIX_process_suspend(smx_process_t process)
       process->suspended = 1;
       c = process->cond;
       xbt_fifo_foreach(c->actions, i, act, smx_action_t) {
-        surf_workstation_model->suspend(act->surf_action);
+        surf_workstation_model->suspend(act->surf_action);
       }
     } else {
       process->suspended = 1;
@@ -353,9 +310,11 @@ void SIMIX_process_suspend(smx_process_t process)
 
     cond = SIMIX_cond_init();
     dummy = SIMIX_action_execute(SIMIX_process_get_host(process), name, 0);
+    SIMIX_process_self()->waiting_action = dummy;
     surf_workstation_model->suspend(dummy->surf_action);
     SIMIX_register_action_to_condition(dummy, cond);
     __SIMIX_cond_wait(cond);
+    SIMIX_process_self()->waiting_action = NULL;
     SIMIX_unregister_action_to_condition(dummy, cond);
     SIMIX_action_destroy(dummy);
     SIMIX_cond_destroy(cond);
@@ -405,7 +364,8 @@ void SIMIX_process_resume(smx_process_t process)
  *
  * This function changes the value of the host on which \a process is running.
  */
-void SIMIX_process_change_host(smx_process_t process, char *source, char *dest)
+void SIMIX_process_change_host(smx_process_t process, char *source,
+                               char *dest)
 {
   xbt_assert0((process != NULL), "Invalid parameters");
   smx_host_t h1 = SIMIX_host_get_by_name(source);
@@ -447,31 +407,45 @@ int SIMIX_process_count()
  * Only the processes can call this function, giving back the control
  * to the maestro
  */
-void __SIMIX_process_yield(void)
+void SIMIX_process_yield(void)
 {
   DEBUG1("Yield process '%s'", simix_global->current_process->name);
-  xbt_assert0((simix_global->current_process != simix_global->maestro_process),
-              "You are not supposed to run this function here!");
+  xbt_assert0((simix_global->current_process !=
+               simix_global->maestro_process),
+              "You are not supposed to run this function in maestro context!");
 
-  SIMIX_context_yield();
+  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 process)
+void SIMIX_process_schedule(smx_process_t new_process)
 {
-  DEBUG1("Scheduling context: '%s'", process->name);
+  DEBUG1("Scheduling context: '%s'", new_process->name);
 
   /* save the current process */
-  smx_process_t self = simix_global->current_process;
+  smx_process_t old_process = simix_global->current_process;
 
   /* update the current process */
-  simix_global->current_process = process;
+  simix_global->current_process = new_process;
 
   /* schedule the context */
-  SIMIX_context_schedule(process);
+  SIMIX_context_resume(old_process->context, new_process->context);
 
   /* restore the current process to the previously saved process */
-  simix_global->current_process = self;
+  simix_global->current_process = old_process;
+}
+
+/* callback: context fetching */
+ex_ctx_t *SIMIX_process_get_exception(void)
+{
+  return simix_global->current_process->exception;
+}
+
+/* callback: termination */
+void SIMIX_process_exception_terminate(xbt_ex_t * e)
+{
+  xbt_ex_display(e);
+  abort();
 }