Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Compilation with warning flags
[simgrid.git] / src / simix / smx_process.c
index 7c7dbb6..a25b215 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007, 2008, 2009, 2010. The SimGrid Team.
+/* Copyright (c) 2007-2012. The SimGrid Team.
  * All rights reserved.                                                     */
 
 /* This program is free software; you can redistribute it and/or modify it
@@ -144,6 +144,30 @@ void SIMIX_create_maestro_process()
   simix_global->maestro_process = maestro;
   return;
 }
+/**
+ * \brief Stops a process.
+ *
+ * Stops the process, execute all the registered on_exit functions,
+ * register it to the list of the process to restart if needed
+ * and stops its context.
+ */
+void SIMIX_process_stop(smx_process_t arg) {
+  /* execute the on_exit functions */
+  SIMIX_process_on_exit_runall(arg);
+  /* Add the process to the list of process to restart, only if
+   * the host is down
+   */
+  if (arg->auto_restart && !SIMIX_host_get_state(arg->smx_host)) {
+    SIMIX_host_add_auto_restart_process(arg->smx_host,arg->name,arg->code, arg->data,
+                                        arg->smx_host->name,
+                                        arg->kill_time,
+                                        arg->argc,arg->argv,arg->properties,
+                                        arg->auto_restart);
+  }
+  XBT_DEBUG("Process %s (%s) is dead",arg->name,arg->smx_host->name);
+  /* stop the context */
+  SIMIX_context_stop(arg->context);
+}
 
 /**
  * \brief Same as SIMIX_process_create() but with only one argument (used by timers).
@@ -162,7 +186,8 @@ smx_process_t SIMIX_process_create_from_wrapper(smx_process_arg_t args) {
       args->kill_time,
       args->argc,
       args->argv,
-      args->properties);
+      args->properties,
+      args->auto_restart);
   xbt_free(args);
   return process;
 }
@@ -183,7 +208,8 @@ void SIMIX_process_create(smx_process_t *process,
                           const char *hostname,
                           double kill_time,
                           int argc, char **argv,
-                          xbt_dict_t properties) {
+                          xbt_dict_t properties,
+                          int auto_restart) {
 
   *process = NULL;
   smx_host_t host = SIMIX_host_get_by_name(hostname);
@@ -198,7 +224,6 @@ void SIMIX_process_create(smx_process_t *process,
     *process = xbt_new0(s_smx_process_t, 1);
 
     xbt_assert(((code != NULL) && (host != NULL)), "Invalid parameters");
-
     /* Process data */
     (*process)->pid = simix_process_maxpid++;
     (*process)->name = xbt_strdup(name);
@@ -206,6 +231,13 @@ void SIMIX_process_create(smx_process_t *process,
     (*process)->data = data;
     (*process)->comms = xbt_fifo_new();
     (*process)->simcall.issuer = *process;
+    /* Process data for auto-restart */
+    (*process)->auto_restart = auto_restart;
+    (*process)->code = code;
+    (*process)->argc = argc;
+    (*process)->argv = argv;
+    (*process)->kill_time = kill_time;
+
 
     XBT_VERB("Create context %s", (*process)->name);
     (*process)->context = SIMIX_context_new(code, argc, argv,
@@ -263,8 +295,9 @@ void SIMIX_process_runall(void)
  * or directly for SIMIX internal purposes.
  *
  * \param process poor victim
+ * \param issuer the process which has sent the PROCESS_KILL. Important to not schedule twice the same process.
  */
-void SIMIX_process_kill(smx_process_t process) {
+void SIMIX_process_kill(smx_process_t process, smx_process_t issuer) {
 
   XBT_DEBUG("Killing process %s on %s", process->name, process->smx_host->name);
 
@@ -288,22 +321,32 @@ void SIMIX_process_kill(smx_process_t process) {
         SIMIX_comm_destroy(process->waiting_action);
         break;
 
-      case SIMIX_ACTION_SLEEP:
-  SIMIX_process_sleep_destroy(process->waiting_action);
-  break;
+        case SIMIX_ACTION_SLEEP:
+          SIMIX_process_sleep_destroy(process->waiting_action);
+          break;
 
-      case SIMIX_ACTION_SYNCHRO:
-  SIMIX_synchro_stop_waiting(process, &process->simcall);
-  SIMIX_synchro_destroy(process->waiting_action);
-  break;
+        case SIMIX_ACTION_SYNCHRO:
+          SIMIX_synchro_stop_waiting(process, &process->simcall);
+          SIMIX_synchro_destroy(process->waiting_action);
+          break;
+
+        case SIMIX_ACTION_IO:
+          SIMIX_io_destroy(process->waiting_action);
+          break;
+
+        /* **************************************/
+        /* TUTORIAL: New API                    */
+        case SIMIX_ACTION_NEW_API:
+          SIMIX_new_api_destroy(process->waiting_action);
+          break;
+        /* **************************************/
 
-      case SIMIX_ACTION_IO:
-        SIMIX_io_destroy(process->waiting_action);
-        break;
     }
   }
-  if(!xbt_dynar_member(simix_global->process_to_run, &(process)))
+  if(!xbt_dynar_member(simix_global->process_to_run, &(process)) && process != issuer) {
     xbt_dynar_push_as(simix_global->process_to_run, smx_process_t, process);
+  }
+
 }
 
 /**
@@ -316,7 +359,7 @@ void SIMIX_process_killall(smx_process_t issuer)
 
   while ((p = xbt_swag_extract(simix_global->process_list))) {
     if (p != issuer) {
-      SIMIX_process_kill(p);
+      SIMIX_process_kill(p,issuer);
     }
   }
 
@@ -652,7 +695,7 @@ void SIMIX_process_yield(smx_process_t self)
 
   if (self->context->iwannadie){
     XBT_DEBUG("I wanna die!");
-    SIMIX_context_stop(self->context);
+    SIMIX_process_stop(self);
   }
 
   if(self->suspended) {
@@ -678,7 +721,7 @@ xbt_running_ctx_t *SIMIX_process_get_running_context(void)
 void SIMIX_process_exception_terminate(xbt_ex_t * e)
 {
   xbt_ex_display(e);
-  abort();
+  xbt_abort();
 }
 
 smx_context_t SIMIX_process_get_context(smx_process_t p) {
@@ -739,3 +782,64 @@ void SIMIX_process_on_exit(smx_process_t process, int_f_pvoid_t fun, void *data)
 
   xbt_dynar_push_as(process->on_exit,s_smx_process_exit_fun_t,exit_fun);
 }
+/**
+ * \brief Sets the auto-restart status of the process.
+ * If set to 1, the process will be automatically restarted when its host
+ * comes back.
+ */
+void SIMIX_process_auto_restart_set(smx_process_t process, int auto_restart) {
+  process->auto_restart = auto_restart;
+}
+/**
+ * \brief Restart a process.
+ * Restart a process, starting it again from the beginning.
+ */
+smx_process_t SIMIX_process_restart(smx_process_t process, smx_process_t issuer) {
+  XBT_DEBUG("Restarting process %s on %s", process->name, process->smx_host->name);
+  //retrieve the arguments of the old process
+  //FIXME: Factorise this with SIMIX_host_add_auto_restart_process ?
+  s_smx_process_arg_t arg;
+  arg.code = process->code;
+  arg.hostname = process->smx_host->name;
+  arg.kill_time = process->kill_time;
+  arg.argc = process->argc;
+  arg.data = process->data;
+  int i;
+  arg.argv = xbt_new(char*,process->argc + 1);
+  for (i = 0; i < arg.argc; i++) {
+    arg.argv[i] = xbt_strdup(process->argv[i]);
+  }
+  arg.argv[process->argc] = NULL;
+  arg.properties = NULL;
+  arg.auto_restart = process->auto_restart;
+  //kill the old process
+  SIMIX_process_kill(process,issuer);
+  //start the new process
+  smx_process_t new_process;
+  if (simix_global->create_process_function) {
+    simix_global->create_process_function(&new_process,
+                                          arg.argv[0],
+                                          arg.code,
+                                          arg.data,
+                                          arg.hostname,
+                                          arg.kill_time,
+                                          arg.argc,
+                                          arg.argv,
+                                          arg.properties,
+                                          arg.auto_restart);
+  }
+  else {
+    simcall_process_create(&new_process,
+                                          arg.argv[0],
+                                          arg.code,
+                                          arg.data,
+                                          arg.hostname,
+                                          arg.kill_time,
+                                          arg.argc,
+                                          arg.argv,
+                                          arg.properties,
+                                          arg.auto_restart);
+
+  }
+  return new_process;
+}