Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
As in MSG where we need to know which action the process is waiting for, we need...
[simgrid.git] / src / simix / smx_process.c
index f90dcdb..30c76db 100644 (file)
@@ -21,7 +21,7 @@ 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);
 }
 
@@ -32,11 +32,16 @@ void SIMIX_process_cleanup(void *arg)
  * that have finished (or killed).
  */
 void SIMIX_process_empty_trash(void)
-{ 
+{
   smx_process_t process = NULL;
 
-  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;
     free(process);
@@ -46,13 +51,16 @@ void SIMIX_process_empty_trash(void)
 /**
  * \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 a dummy context for maestro */
   process->context = SIMIX_context_new(NULL, 0, NULL, NULL, NULL);
@@ -102,13 +110,15 @@ smx_process_t SIMIX_process_create(const char *name,
   process->mutex = NULL;
   process->cond = NULL;
   process->iwannadie = 0;
+  process->data = data;
 
   VERB1("Create context %s", process->name);
-  process->context = SIMIX_context_new(code, argc, argv, 
+  process->context = SIMIX_context_new(code, argc, argv,
                                        simix_global->cleanup_process_function,
                                        process);
-  
-  process->data = data;
+
+  process->exception = xbt_new(ex_ctx_t, 1);
+  XBT_CTX_INITIALIZE(process->exception);
 
   /* Add properties */
   process->properties = properties;
@@ -118,7 +128,7 @@ smx_process_t SIMIX_process_create(const char *name,
 
   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);
@@ -137,23 +147,37 @@ 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);
-
   process->iwannadie = 1;
 
-  /* If I'm killing myself then stop otherwise schedule the process to kill */
-  if (process == SIMIX_process_self())
+  /* 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()) {
+    /* 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
-    __SIMIX_process_schedule(process);
-  
+  } 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);
+    }
+  }
 }
 
 /**
@@ -272,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;
@@ -286,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);
@@ -338,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);
@@ -380,10 +407,11 @@ 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),
+  xbt_assert0((simix_global->current_process !=
+               simix_global->maestro_process),
               "You are not supposed to run this function here!");
 
   SIMIX_context_suspend(simix_global->current_process->context);
@@ -392,7 +420,7 @@ void __SIMIX_process_yield(void)
     SIMIX_context_stop(simix_global->current_process->context);
 }
 
-void __SIMIX_process_schedule(smx_process_t new_process)
+void SIMIX_process_schedule(smx_process_t new_process)
 {
   DEBUG1("Scheduling context: '%s'", new_process->name);
 
@@ -408,3 +436,16 @@ void __SIMIX_process_schedule(smx_process_t new_process)
   /* restore the current process to the previously saved process */
   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();
+}