Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
make sure that MSG_task_execute() is not called by error on parallel tasks
[simgrid.git] / src / msg / gos.c
index 321bfef..54b4fa8 100644 (file)
@@ -1,8 +1,5 @@
-/*     $Id$      */
-
-/* Copyright (c) 2002-2007 Arnaud Legrand.                                  */
-/* Copyright (c) 2007 Bruno Donassolo.                                      */
-/* All rights reserved.                                                     */
+/* Copyright (c) 2004, 2005, 2006, 2007, 2008, 2009, 2010. The SimGrid Team.
+ * All rights reserved.                                                     */
 
 /* This program is free software; you can redistribute it and/or modify it
  * under the terms of the license (GNU LGPL) which comes with this package. */
@@ -44,12 +41,25 @@ MSG_error_t MSG_task_execute(m_task_t task)
   CHECK_HOST();
 
   simdata = task->simdata;
-  xbt_assert1((!simdata->compute)
-              && (task->simdata->refcount == 1),
+
+  xbt_assert0(simdata->host_nb==0, "This is a parallel task. Go to hell.");
+
+#ifdef HAVE_TRACING
+  TRACE_msg_task_execute_start (task);
+#endif
+
+
+  xbt_assert1((!simdata->compute) && (task->simdata->refcount == 1),
               "This task is executed somewhere else. Go fix your code! %d", task->simdata->refcount);
 
   DEBUG1("Computing on %s", MSG_process_self()->simdata->m_host->name);
 
+  if (simdata->computation_amount == 0) {
+#ifdef HAVE_TRACING
+    TRACE_msg_task_execute_end (task);
+#endif
+    return MSG_OK;
+  }
   simdata->refcount++;
   SIMIX_mutex_lock(simdata->mutex);
   simdata->compute =
@@ -76,18 +86,27 @@ MSG_error_t MSG_task_execute(m_task_t task)
     simdata->computation_amount = 0.0;
     simdata->comm = NULL;
     simdata->compute = NULL;
+#ifdef HAVE_TRACING
+    TRACE_msg_task_execute_end (task);
+#endif
     MSG_RETURN(MSG_OK);
   } else if (SIMIX_host_get_state(SIMIX_host_self()) == 0) {
     /* action ended, set comm and compute = NULL, the actions is already destroyed in the main function */
     SIMIX_action_destroy(task->simdata->compute);
     simdata->comm = NULL;
     simdata->compute = NULL;
+#ifdef HAVE_TRACING
+    TRACE_msg_task_execute_end (task);
+#endif
     MSG_RETURN(MSG_HOST_FAILURE);
   } else {
     /* action ended, set comm and compute = NULL, the actions is already destroyed in the main function */
     SIMIX_action_destroy(task->simdata->compute);
     simdata->comm = NULL;
     simdata->compute = NULL;
+#ifdef HAVE_TRACING
+    TRACE_msg_task_execute_end (task);
+#endif
     MSG_RETURN(MSG_TASK_CANCELLED);
   }
 }
@@ -228,6 +247,10 @@ MSG_error_t MSG_process_sleep(double nb_sec)
   smx_mutex_t mutex;
   smx_cond_t cond;
 
+#ifdef HAVE_TRACING
+  TRACE_msg_process_sleep_in (MSG_process_self());
+#endif
+
   /* create action to sleep */
   act_sleep =
     SIMIX_action_sleep(SIMIX_process_get_host(proc->simdata->s_process),
@@ -256,14 +279,23 @@ MSG_error_t MSG_process_sleep(double nb_sec)
   if (SIMIX_action_get_state(act_sleep) == SURF_ACTION_DONE) {
     if (SIMIX_host_get_state(SIMIX_host_self()) == SURF_RESOURCE_OFF) {
       SIMIX_action_destroy(act_sleep);
+#ifdef HAVE_TRACING
+      TRACE_msg_process_sleep_out (MSG_process_self());
+#endif
       MSG_RETURN(MSG_HOST_FAILURE);
     }
   } else {
     SIMIX_action_destroy(act_sleep);
+#ifdef HAVE_TRACING
+    TRACE_msg_process_sleep_out (MSG_process_self());
+#endif
     MSG_RETURN(MSG_HOST_FAILURE);
   }
 
   SIMIX_action_destroy(act_sleep);
+#ifdef HAVE_TRACING
+  TRACE_msg_process_sleep_out (MSG_process_self());
+#endif
   MSG_RETURN(MSG_OK);
 }
 
@@ -376,6 +408,93 @@ MSG_task_receive_ext(m_task_t * task, const char *alias, double timeout,
                                   timeout);
 }
 
+msg_comm_t MSG_task_isend(m_task_t task, const char *alias) {
+  simdata_task_t t_simdata = NULL;
+  m_process_t process = MSG_process_self();
+  msg_mailbox_t mailbox = MSG_mailbox_get_by_alias(alias);
+
+  CHECK_HOST();
+
+  /* FIXME: these functions are not tracable */
+
+  /* Prepare the task to send */
+  t_simdata = task->simdata;
+  t_simdata->sender = process;
+  t_simdata->source = MSG_host_self();
+
+  xbt_assert0(t_simdata->refcount == 1,
+              "This task is still being used somewhere else. You cannot send it now. Go fix your code!");
+
+  t_simdata->refcount++;
+  msg_global->sent_msg++;
+
+  process->simdata->waiting_task = task;
+
+  /* Send it by calling SIMIX network layer */
+
+  /* Kept for semantical compatibility with older implementation */
+  if(mailbox->cond)
+    SIMIX_cond_signal(mailbox->cond);
+
+  return SIMIX_network_isend(mailbox->rdv, t_simdata->message_size, t_simdata->rate,
+      task, sizeof(void*), &t_simdata->comm);
+}
+
+msg_comm_t MSG_task_irecv(m_task_t * task, const char *alias) {
+  smx_comm_t comm;
+  smx_rdv_t rdv = MSG_mailbox_get_by_alias(alias)->rdv;
+  msg_mailbox_t mailbox=MSG_mailbox_get_by_alias(alias);
+  size_t size = sizeof(void*);
+
+  CHECK_HOST();
+
+  /* FIXME: these functions are not tracable */
+
+  memset(&comm,0,sizeof(comm));
+
+  /* Kept for compatibility with older implementation */
+  xbt_assert1(!MSG_mailbox_get_cond(mailbox),
+              "A process is already blocked on this channel %s",
+              MSG_mailbox_get_alias(mailbox));
+
+  /* Sanity check */
+  xbt_assert0(task, "Null pointer for the task storage");
+
+  if (*task)
+    CRITICAL0("MSG_task_get() was asked to write in a non empty task struct.");
+
+  /* Try to receive it by calling SIMIX network layer */
+  return SIMIX_network_irecv(rdv, task, &size);
+}
+int MSG_comm_test(msg_comm_t comm) {
+  return SIMIX_network_test(comm);
+}
+MSG_error_t MSG_comm_wait(msg_comm_t comm,double timeout) {
+  xbt_ex_t e;
+  MSG_error_t res = MSG_OK;
+  TRY {
+    SIMIX_network_wait(comm,timeout);
+    //  (*task)->simdata->refcount--;
+
+    /* FIXME: these functions are not tracable */
+  }  CATCH(e){
+      switch(e.category){
+        case host_error:
+          res = MSG_HOST_FAILURE;
+          break;
+        case network_error:
+          res = MSG_TRANSFER_FAILURE;
+          break;
+        case timeout_error:
+          res = MSG_TIMEOUT;
+          break;
+        default:
+          xbt_die(bprintf("Unhandled SIMIX network exception: %s",e.msg));
+      }
+      xbt_ex_free(e);
+    }
+  return res;
+}
 
 /** \ingroup msg_gos_functions
  * \brief Put a task on a channel of an host and waits for the end of the