Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Keeping rewriting MSG
authoralegrand <alegrand@48e7efb5-ca39-0410-a469-dd3cf9ba447f>
Fri, 17 Dec 2004 05:46:56 +0000 (05:46 +0000)
committeralegrand <alegrand@48e7efb5-ca39-0410-a469-dd3cf9ba447f>
Fri, 17 Dec 2004 05:46:56 +0000 (05:46 +0000)
git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/simgrid/simgrid/trunk@677 48e7efb5-ca39-0410-a469-dd3cf9ba447f

src/msg/m_process.c [new file with mode: 0644]
src/msg/private.h

diff --git a/src/msg/m_process.c b/src/msg/m_process.c
new file mode 100644 (file)
index 0000000..d3e1dbd
--- /dev/null
@@ -0,0 +1,335 @@
+/*     $Id$     */
+
+/* Copyright (c) 2002,2003,2004 Arnaud Legrand. 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. */
+
+#include"private.h"
+#include"xbt/sysdep.h"
+#include "xbt/error.h"
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(m_process, msg,
+                               "Logging specific to MSG (process)");
+
+/******************************** Process ************************************/
+/** \ingroup m_process_management
+ * \brief Creates and runs a new #m_process_t.
+
+ * 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 code is a function describing the behavior of the agent. It
+   should then only use functions described in \ref
+   m_process_management (to create a new #m_process_t for example),
+   in \ref m_host_management (only the read-only functions i.e. whose
+   name contains the word get), in \ref m_task_management (to create
+   or destroy some #m_task_t for example) and in \ref
+   msg_gos_functions (to handle file transfers and task processing).
+ * \param data a pointer to any data 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.
+ * \see m_process_t
+ * \return The new corresponding object.
+ */
+m_process_t MSG_process_create(const char *name,
+                              m_process_code_t code, void *data,
+                              m_host_t host)
+{
+  simdata_process_t simdata = xbt_new0(s_simdata_process_t,1);
+  m_process_t process = xbt_new0(s_m_process_t,1);
+  m_process_t self = NULL;
+  static int PID = 1;
+
+  xbt_assert0(((code != NULL) && (host != NULL)), "Invalid parameters");
+  /* Simulator Data */
+
+  simdata->PID = PID++;
+  simdata->host = host;
+  simdata->waiting_task = NULL;
+  simdata->put_host = NULL;
+  simdata->put_channel = -1;
+  simdata->argc = -1;
+  simdata->argv = NULL;
+  simdata->context = xbt_context_new(code, simdata->argc, simdata->argv);
+
+  if((self=msg_global->current_process)) {
+    simdata->PPID = MSG_process_get_PID(self);
+  } else {
+    simdata->PPID = -1;
+  }
+  simdata->last_errno=MSG_OK;
+
+
+  /* Process structure */
+  process->name = xbt_strdup(name);
+  process->simdata = simdata;
+  process->data = data;
+
+  xbt_fifo_push(host->simdata->process_list, process);
+
+  /* /////////////// FIX du current_process !!! ////////////// */
+  self = msg_global->current_process;
+  xbt_context_start(process->simdata->context);
+  msg_global->current_process = self;
+  return process;
+}
+
+/** \ingroup m_process_management
+ * \brief Migrates an agent to another location.
+ *
+ * This functions checks whether \a process and \a host are valid pointers
+   and change the value of the #m_host_t on which \a process is running.
+ */
+MSG_error_t MSG_process_change_host(m_process_t process, m_host_t host)
+{
+  simdata_process_t simdata = NULL;
+
+  /* Sanity check */
+
+  xbt_assert0(((process) && (process->simdata)
+         && (host)), "Invalid parameters");
+  simdata = process->simdata;
+
+  xbt_fifo_remove(simdata->host->simdata->process_list,process);
+  simdata->host = host;
+  xbt_fifo_push(host->simdata->process_list,process);
+
+  return MSG_OK;
+}
+
+/** \ingroup m_process_management
+ * \brief Return the user data of a #m_process_t.
+ *
+ * This functions checks whether \a process is a valid pointer or not 
+   and return the user data associated to \a process if it is possible.
+ */
+void *MSG_process_get_data(m_process_t process)
+{
+  xbt_assert0((process != NULL), "Invalid parameters");
+
+  return (process->data);
+}
+
+/** \ingroup m_process_management
+ * \brief Set the user data of a #m_process_t.
+ *
+ * This functions checks whether \a process is a valid pointer or not 
+   and set the user data associated to \a process if it is possible.
+ */
+MSG_error_t MSG_process_set_data(m_process_t process,void *data)
+{
+  xbt_assert0((process != NULL), "Invalid parameters");
+  xbt_assert0((process->data == NULL), "Data already set");
+  
+  process->data = data;
+   
+  return MSG_OK;
+}
+
+/** \ingroup m_process_management
+ * \brief Return the location on which an agent is running.
+ *
+ * This functions checks whether \a process is a valid pointer or not 
+   and return the m_host_t corresponding to the location on which \a 
+   process is running.
+ */
+m_host_t MSG_process_get_host(m_process_t process)
+{
+  xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
+
+  return (((simdata_process_t) process->simdata)->host);
+}
+
+/** \ingroup m_process_management
+ *
+ * \brief Return a #m_process_t given its PID.
+ *
+ * This functions search in the list of all the created m_process_t for a m_process_t 
+   whose PID is equal to \a PID. If no host is found, \c NULL is returned. 
+   Note that the PID are uniq in the whole simulation, not only on a given host.
+ */
+m_process_t MSG_process_from_PID(int PID)
+{
+  xbt_fifo_item_t i = NULL;
+  m_process_t process = NULL;
+
+  xbt_fifo_foreach(msg_global->process_list,i,process,m_process_t) {
+    if(MSG_process_get_PID(process) == PID) return process;
+  }
+  return NULL;
+}
+
+/** \ingroup m_process_management
+ * \brief Returns the process ID of \a process.
+ *
+ * This functions checks whether \a process is a valid pointer or not 
+   and return its PID.
+ */
+int MSG_process_get_PID(m_process_t process)
+{
+  xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
+
+  return (((simdata_process_t) process->simdata)->PID);
+}
+
+
+/** \ingroup m_process_management
+ * \brief Returns the process ID of the parent of \a process.
+ *
+ * This functions checks whether \a process is a valid pointer or not 
+   and return its PID. Returns -1 if the agent has not been created by 
+   another agent.
+ */
+int MSG_process_get_PPID(m_process_t process)
+{
+  xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
+
+  return (((simdata_process_t) process->simdata)->PPID);
+}
+
+/** \ingroup m_process_management
+ * \brief Return the name of an agent.
+ *
+ * This functions checks whether \a process is a valid pointer or not 
+   and return its name.
+ */
+const char *MSG_process_get_name(m_process_t process)
+{
+  xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
+
+  return (process->name);
+}
+
+/** \ingroup m_process_management
+ * \brief Return the PID of the current agent.
+ *
+ * This functions returns the PID of the currently running #m_process_t.
+ */
+int MSG_process_self_PID(void)
+{
+  return (MSG_process_get_PID(MSG_process_self()));
+}
+
+/** \ingroup m_process_management
+ * \brief Return the PPID of the current agent.
+ *
+ * This functions returns the PID of the parent of the currently
+ * running #m_process_t.
+ */
+int MSG_process_self_PPID(void)
+{
+  return (MSG_process_get_PPID(MSG_process_self()));
+}
+
+/** \ingroup m_process_management
+ * \brief Return the current agent.
+ *
+ * This functions returns the currently running #m_process_t.
+ */
+m_process_t MSG_process_self(void)
+{
+  return msg_global->current_process;
+}
+
+/** \ingroup m_process_management
+ * \brief Suspend the process.
+ *
+ * This functions suspend the process by suspending the task on which
+ * it was waiting for the completion.
+ */
+MSG_error_t MSG_process_suspend(m_process_t process)
+{
+  simdata_process_t simdata = NULL;
+  simdata_task_t simdata_task = NULL;
+  int i;
+
+  xbt_assert0(((process) && (process->simdata)), "Invalid parameters");
+
+  if(process!=MSG_process_self()) {
+    simdata = process->simdata;
+    
+    xbt_assert0(simdata->waiting_task,"Process not waiting for anything else. Weird !");
+
+    simdata_task = simdata->waiting_task->simdata;
+
+    xbt_assert0(((simdata_task->compute)||(simdata_task->comm))&&
+               !((simdata_task->comm)&&(simdata_task->comm)),
+               "Got a problem in deciding which action to choose !");
+    if(simdata_task->compute) 
+      surf_workstation_resource->extension_public->suspend(simdata_task->compute);
+    else 
+      surf_workstation_resource->extension_public->suspend(simdata_task->comm);
+
+  } else {
+    m_task_t dummy = MSG_TASK_UNINITIALIZED;
+    dummy = MSG_task_create("suspended", 0.01, 0, NULL);
+
+    __MSG_task_execute(process,dummy);
+    surf_workstation_resource->extension_public->suspend(dummy->simdata->compute);
+    __MSG_wait_for_computation(process,dummy);
+
+    MSG_task_destroy(dummy);
+  }
+  return MSG_OK;
+}
+
+/** \ingroup m_process_management
+ * \brief Resume a suspended process.
+ *
+ * This functions resume a suspended process by resuming the task on
+ * which it was waiting for the completion.
+ */
+MSG_error_t MSG_process_resume(m_process_t process)
+{
+  simdata_process_t simdata = NULL;
+  simdata_task_t simdata_task = NULL;
+  int i;
+
+  xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
+  CHECK_HOST();
+
+  simdata = process->simdata;
+  if(!(simdata->waiting_task)) {
+    xbt_assert0(0,"Process not waiting for anything else. Weird !");
+    return MSG_WARNING;
+  }
+  simdata_task = simdata->waiting_task->simdata;
+
+  if(simdata_task->compute) 
+    surf_workstation_resource->extension_public->resume(simdata_task->compute);
+  else 
+    surf_workstation_resource->extension_public->resume(simdata_task->comm);
+
+  MSG_RETURN(MSG_OK);
+}
+
+/** \ingroup m_process_management
+ * \brief Returns true if the process is suspended .
+ *
+ * This checks whether a process is suspended or not by inspecting the
+ * task on which it was waiting for the completion.
+ */
+int MSG_process_isSuspended(m_process_t process)
+{
+  simdata_process_t simdata = NULL;
+  simdata_task_t simdata_task = NULL;
+  int i;
+  
+  xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
+
+  simdata = process->simdata;
+  if(!(simdata->waiting_task)) {
+    xbt_assert0(0,"Process not waiting for anything else. Weird !");
+    return 0;
+  }
+
+  simdata_task = simdata->waiting_task->simdata;
+
+  if(simdata_task->compute) 
+    return surf_workstation_resource->extension_public->is_suspended(simdata_task->compute);
+  else 
+    return surf_workstation_resource->extension_public->is_suspended(simdata_task->comm);
+}
index bc4a6db..ad8c31e 100644 (file)
@@ -49,7 +49,7 @@ typedef struct simdata_process {
   xbt_context_t context;               /* the context that executes the scheduler fonction */
   int PID;                     /* used for debugging purposes */
   int PPID;                    /* The parent PID */
-  m_task_t waiting_task;        /* used for debugging purposes */
+  m_task_t waiting_task;        
   m_host_t put_host;            /* used for debugging purposes */
   int put_channel;              /* used for debugging purposes */
   int argc;                     /* arguments number if any */
@@ -62,7 +62,7 @@ typedef struct MSG_Global {
   xbt_fifo_t host;
   xbt_fifo_t link;
   xbt_fifo_t process_to_run;
-  xbt_fifo_t process;
+  xbt_fifo_t process_list;
   int max_channel;
   m_process_t current_process;
   xbt_dict_t registered_functions;
@@ -72,16 +72,18 @@ extern MSG_Global_t msg_global;
 
 /*************************************************************/
 
-#define PROCESS_SET_ERRNO(val) (((simdata_process_t)(MSG_process_self()->simdata))->last_errno=val)
-#define PROCESS_GET_ERRNO() (((simdata_process_t)(MSG_process_self()->simdata))->last_errno)
+#define PROCESS_SET_ERRNO(val) (MSG_process_self()->simdata->last_errno=val)
+#define PROCESS_GET_ERRNO() (MSG_process_self()->simdata->last_errno)
 #define MSG_RETURN(val) do {PROCESS_SET_ERRNO(val);return(val);} while(0)
 /* #define CHECK_ERRNO()  ASSERT((PROCESS_GET_ERRNO()!=MSG_HOST_FAILURE),"Host failed, you cannot call this function.") */
 
-#define CHECK_HOST()  ASSERT((((simdata_host_t) MSG_host_self()->simdata)->state==HOST_ALIVE),"Host failed, you cannot call this function.")
+#define CHECK_HOST()  xbt_assert0((MSG_host_self()->simdata->state==HOST_ALIVE),"Host failed, you cannot call this function.")
 
 m_host_t __MSG_host_create(const char *name, void *workstation,
                           void *data);
 void __MSG_host_destroy(m_host_t host);
+void __MSG_task_execute(m_process_t process, m_task_t task);
+MSG_error_t __MSG_wait_for_computation(m_process_t process, m_task_t task);
 MSG_error_t __MSG_task_wait_event(m_process_t process, m_task_t task);
 
 #endif