Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
merge back the master trunk into the smpi branch
authorMartin Quinson <martin.quinson@loria.fr>
Mon, 26 Dec 2011 18:03:09 +0000 (19:03 +0100)
committerMartin Quinson <martin.quinson@loria.fr>
Mon, 26 Dec 2011 18:03:09 +0000 (19:03 +0100)
1  2 
include/simix/simix.h
src/msg/msg_gos.c
src/simix/smx_network.c
src/smpi/smpi_bench.c
src/smpi/smpi_f77.c
src/smpi/smpi_global.c
src/surf/network.c

diff --combined include/simix/simix.h
@@@ -63,8 -63,8 +63,8 @@@ XBT_PUBLIC(void*) SIMIX_host_self_get_d
  XBT_PUBLIC(int) SIMIX_process_count(void);
  XBT_INLINE XBT_PUBLIC(smx_process_t) SIMIX_process_self(void);
  XBT_PUBLIC(const char*) SIMIX_process_self_get_name(void);
- XBT_PUBLIC(void) SIMIX_process_self_set_data(void *data);
- XBT_PUBLIC(void*) SIMIX_process_self_get_data(void);
+ XBT_PUBLIC(void) SIMIX_process_self_set_data(smx_process_t self, void *data);
+ XBT_PUBLIC(void*) SIMIX_process_self_get_data(smx_process_t self);
  XBT_PUBLIC(smx_context_t) SIMIX_process_get_context(smx_process_t);
  XBT_PUBLIC(void) SIMIX_process_set_context(smx_process_t p,smx_context_t c);
  
@@@ -72,8 -72,6 +72,8 @@@
  XBT_PUBLIC(void) SIMIX_comm_set_copy_data_callback(void (*callback) (smx_action_t, size_t));
  XBT_PUBLIC(void) SIMIX_comm_copy_pointer_callback(smx_action_t comm, size_t buff_size);
  XBT_PUBLIC(void) SIMIX_comm_copy_buffer_callback(smx_action_t comm, size_t buff_size);
 +XBT_PUBLIC(void) smpi_comm_copy_data_callback(smx_action_t comm, size_t buff_size);
 +
  XBT_PUBLIC(smx_action_t) SIMIX_comm_get_send_match(smx_rdv_t rdv, int (*match_fun)(void*, void*), void* data);
  XBT_PUBLIC(int) SIMIX_comm_has_send_match(smx_rdv_t rdv, int (*match_fun)(void*, void*), void* data);
  XBT_PUBLIC(int) SIMIX_comm_has_recv_match(smx_rdv_t rdv, int (*match_fun)(void*, void*), void* data);
diff --combined src/msg/msg_gos.c
@@@ -1,29 -1,18 +1,18 @@@
- /* Copyright (c) 2004, 2005, 2006, 2007, 2008, 2009, 2010. The SimGrid Team.
-  * All rights reserved.                                                     */
+ /* Copyright (c) 2004-2011. 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. */
  
- #include "private.h"
- #include "xbt/sysdep.h"
+ #include "msg_private.h"
+ #include "msg_mailbox.h"
  #include "mc/mc.h"
  #include "xbt/log.h"
- #include "mailbox.h"
+ #include "xbt/sysdep.h"
  
  
  XBT_LOG_NEW_DEFAULT_SUBCATEGORY(msg_gos, msg,
                                  "Logging specific to MSG (gos)");
  
- /** \ingroup msg_gos_functions
-  *
-  * \brief Return the last value returned by a MSG function (except
-  * MSG_get_errno...).
-  */
- MSG_error_t MSG_get_errno(void)
- {
-   return PROCESS_GET_ERRNO();
- }
  /** \ingroup msg_gos_functions
   * \brief Executes a task and waits for its termination.
   *
@@@ -31,8 -20,8 +20,8 @@@
   * takes only one parameter.
   * \param task a #m_task_t to execute on the location on which the
   agent is running.
-  * \return #MSG_FATAL if \a task is not properly initialized and
-  * #MSG_OK otherwise.
+  * \return #MSG_OK if the task was successfully completed, #MSG_TASK_CANCELED
+  * or #MSG_HOST_FAILURE otherwise
   */
  MSG_error_t MSG_task_execute(m_task_t task)
  {
  #endif
      return MSG_OK;
    }
+   m_process_t self = SIMIX_process_self();
+   p_simdata = SIMIX_process_self_get_data(self);
    simdata->isused=1;
    simdata->compute =
-       SIMIX_req_host_execute(task->name, SIMIX_host_self(),
+       SIMIX_req_host_execute(task->name, p_simdata->m_host->simdata->smx_host,
                             simdata->computation_amount,
                             simdata->priority);
  #ifdef HAVE_TRACING
    SIMIX_req_set_category(simdata->compute, task->category);
  #endif
  
-   p_simdata = SIMIX_process_self_get_data();
    p_simdata->waiting_action = simdata->compute;
    comp_state = SIMIX_req_host_execution_wait(simdata->compute);
    p_simdata->waiting_action = NULL;
  #ifdef HAVE_TRACING
      TRACE_msg_task_execute_end(task);
  #endif
-     MSG_RETURN(MSG_TASK_CANCELLED);
+     MSG_RETURN(MSG_TASK_CANCELED);
    }
  }
  
@@@ -171,7 -162,7 +162,7 @@@ MSG_error_t MSG_parallel_task_execute(m
    CHECK_HOST();
  
    simdata = task->simdata;
-   p_simdata = SIMIX_process_self_get_data();
+   p_simdata = SIMIX_process_self_get_data(SIMIX_process_self());
  
    xbt_assert((!simdata->compute)
                && (task->simdata->isused == 0),
      /* action ended, set comm and compute = NULL, the actions is already destroyed in the main function */
      simdata->comm = NULL;
      simdata->compute = NULL;
-     MSG_RETURN(MSG_TASK_CANCELLED);
+     MSG_RETURN(MSG_TASK_CANCELED);
    }
  }
  
@@@ -269,8 -260,7 +260,7 @@@ MSG_error_t MSG_process_sleep(double nb
   listening. This value has to be >=0 and < than the maximal
   number of channels fixed with MSG_set_channel_number().
   * \param host the host that is to be watched.
-  * \return #MSG_FATAL if \a task is equal to \c NULL, #MSG_WARNING
-  if \a *task is not equal to \c NULL, and #MSG_OK otherwise.
+  * \return a #MSG_error_t indicating whether the operation was successful (#MSG_OK), or why it failed otherwise.
   */
  MSG_error_t
  MSG_task_get_from_host(m_task_t * task, m_channel_t channel, m_host_t host)
   * \param channel the channel on which the agent should be
   listening. This value has to be >=0 and < than the maximal
   number of channels fixed with MSG_set_channel_number().
-  * \return #MSG_FATAL if \a task is equal to \c NULL, #MSG_WARNING
-  * if \a *task is not equal to \c NULL, and #MSG_OK otherwise.
+  * \return a #MSG_error_t indicating whether the operation was successful (#MSG_OK), or why it failed otherwise.
   */
  MSG_error_t MSG_task_get(m_task_t * task, m_channel_t channel)
  {
   up. In such a case, #MSG_TRANSFER_FAILURE will be returned, \a task
   will not be modified and will still be
   equal to \c NULL when returning.
-  * \return #MSG_FATAL if \a task is equal to \c NULL, #MSG_WARNING
-  if \a *task is not equal to \c NULL, and #MSG_OK otherwise.
+  * \return a #MSG_error_t indicating whether the operation was successful (#MSG_OK), or why it failed otherwise.
   */
  MSG_error_t
  MSG_task_get_with_timeout(m_task_t * task, m_channel_t channel,
@@@ -385,6 -373,7 +373,7 @@@ msg_comm_t MSG_task_isend(m_task_t task
  {
    return MSG_task_isend_with_matching(task,alias,NULL,NULL);
  }
  /** \ingroup msg_gos_functions
   * \brief Sends a task on a mailbox, with support for matching requests
   *
@@@ -412,7 -401,7 +401,7 @@@ XBT_INLINE msg_comm_t MSG_task_isend_wi
    /* Prepare the task to send */
    t_simdata = task->simdata;
    t_simdata->sender = process;
-   t_simdata->source = MSG_host_self();
+   t_simdata->source = ((simdata_process_t) SIMIX_process_self_get_data(process))->m_host;
  
    xbt_assert(t_simdata->isused == 0,
                "This task is still being used somewhere else. You cannot send it now. Go fix your code!");
   * \brief Sends a task on a mailbox.
   *
   * This is a non blocking detached send function.
-  * Think of it as a best effort send. The communication
-  * object will be destroyed by the receiver (if any).
+  * Think of it as a best effort send. Keep in mind that the third parameter
+  * is only called if the communication fails. If the communication does work,
+  * it is responsibility of the receiver code to free anything related to
+  * the task, as usual. More details on this can be obtained on
+  * <a href="http://lists.gforge.inria.fr/pipermail/simgrid-user/2011-November/002649.html">this thread</a>
+  * in the SimGrid-user mailing list archive.
   *
   * \param task a #m_task_t to send on another location.
   * \param alias name of the mailbox to sent the task to
@@@ -463,7 -456,7 +456,7 @@@ void MSG_task_dsend(m_task_t task, cons
    /* Prepare the task to send */
    t_simdata = task->simdata;
    t_simdata->sender = process;
-   t_simdata->source = MSG_host_self();
+   t_simdata->source = ((simdata_process_t) SIMIX_process_self_get_data(process))->m_host;
  
    xbt_assert(t_simdata->isused == 0,
                "This task is still being used somewhere else. You cannot send it now. Go fix your code!");
    msg_global->sent_msg++;
  
    /* Send it by calling SIMIX network layer */
-   SIMIX_req_comm_isend(mailbox, t_simdata->message_size,
+   smx_action_t comm = SIMIX_req_comm_isend(mailbox, t_simdata->message_size,
                         t_simdata->rate, task, sizeof(void *), NULL, cleanup, 1);
+   t_simdata->comm = comm;
  }
  
  /** \ingroup msg_gos_functions
@@@ -499,7 -493,7 +493,7 @@@ msg_comm_t MSG_task_irecv(m_task_t *tas
  
    if (*task)
      XBT_CRITICAL
 -        ("MSG_task_get() was asked to write in a non empty task struct.");
 +        ("MSG_task_irecv() was asked to write in a non empty task struct.");
  
    /* Try to receive it by calling SIMIX network layer */
    msg_comm_t comm = xbt_new0(s_msg_comm_t, 1);
@@@ -525,6 -519,11 +519,11 @@@ int MSG_comm_test(msg_comm_t comm
    int finished = 0;
    TRY {
      finished = SIMIX_req_comm_test(comm->s_comm);
+     if (finished && comm->task_received != NULL) {
+       /* I am the receiver */
+       (*comm->task_received)->simdata->isused = 0;
+     }
    }
    CATCH(e) {
      switch (e.category) {
@@@ -606,6 -605,11 +605,11 @@@ int MSG_comm_testany(xbt_dynar_t comms
      comm = xbt_dynar_get_as(comms, finished_index, msg_comm_t);
      /* the communication is finished */
      comm->status = status;
+     if (status == MSG_OK && comm->task_received != NULL) {
+       /* I am the receiver */
+       (*comm->task_received)->simdata->isused = 0;
+     }
    }
  
    return finished_index;
@@@ -623,9 -627,7 +627,7 @@@ void MSG_comm_destroy(msg_comm_t comm
      (*comm->task_received)->simdata->isused = 0;
    }
  
-   /* FIXME auto-destroy comms from SIMIX to avoid this request */
-   /*SIMIX_req_comm_destroy(comm->s_comm);*/
-   free(comm);
+   xbt_free(comm);
  }
  
  /** \ingroup msg_gos_functions
@@@ -780,11 -782,10 +782,10 @@@ m_task_t MSG_comm_get_task(msg_comm_t c
   * \param channel the channel on which the agent should put this
   task. This value has to be >=0 and < than the maximal number of
   channels fixed with MSG_set_channel_number().
-  * \return #MSG_FATAL if \a task is not properly initialized and
-  * #MSG_OK otherwise. Returns #MSG_HOST_FAILURE if the host on which
-  * this function was called was shut down. Returns
+  * \return #MSG_HOST_FAILURE if the host on which
+  * this function was called was shut down,
   * #MSG_TRANSFER_FAILURE if the transfer could not be properly done
-  * (network failure, dest failure)
+  * (network failure, dest failure) or #MSG_OK if it succeeded.
   */
  MSG_error_t MSG_task_put(m_task_t task, m_host_t dest, m_channel_t channel)
  {
@@@ -828,11 -829,10 +829,10 @@@ MSG_task_put_bounded(m_task_t task, m_h
   * \param timeout the maximum time to wait for a task before giving
   up. In such a case, #MSG_TRANSFER_FAILURE will be returned, \a task
   will not be modified
-  * \return #MSG_FATAL if \a task is not properly initialized and
- #MSG_OK otherwise. Returns #MSG_HOST_FAILURE if the host on which
- this function was called was shut down. Returns
+  * \return #MSG_HOST_FAILURE if the host on which
+ this function was called was shut down,
  #MSG_TRANSFER_FAILURE if the transfer could not be properly done
- (network failure, dest failure, timeout...)
+ (network failure, dest failure, timeout...) or #MSG_OK if the communication succeeded.
   */
  MSG_error_t
  MSG_task_put_with_timeout(m_task_t task, m_host_t dest,
@@@ -977,3 -977,15 +977,15 @@@ int MSG_task_listen_from(const char *al
  
    return MSG_process_get_PID(task->simdata->sender);
  }
+ #ifdef MSG_USE_DEPRECATED
+ /** \ingroup msg_gos_functions
+  *
+  * \brief Return the last value returned by a MSG function (except
+  * MSG_get_errno...).
+  */
+ MSG_error_t MSG_get_errno(void)
+ {
+   return PROCESS_GET_ERRNO();
+ }
+ #endif
diff --combined src/simix/smx_network.c
@@@ -26,7 -26,7 +26,7 @@@ static void SIMIX_rdv_free(void *data)
  
  void SIMIX_network_init(void)
  {
-   rdv_points = xbt_dict_new();
+   rdv_points = xbt_dict_new_homogeneous(SIMIX_rdv_free);
  }
  
  void SIMIX_network_exit(void)
@@@ -49,7 -49,7 +49,7 @@@ smx_rdv_t SIMIX_rdv_create(const char *
      rdv->comm_fifo = xbt_fifo_new();
  
      if (rdv->name)
-       xbt_dict_set(rdv_points, rdv->name, rdv, SIMIX_rdv_free);
+       xbt_dict_set(rdv_points, rdv->name, rdv, NULL);
    }
    return rdv;
  }
@@@ -63,8 -63,7 +63,7 @@@ void SIMIX_rdv_destroy(smx_rdv_t rdv
  void SIMIX_rdv_free(void *data)
  {
    smx_rdv_t rdv = (smx_rdv_t) data;
-   if (rdv->name)
-     xbt_free(rdv->name);
+   xbt_free(rdv->name);
    xbt_fifo_free(rdv->comm_fifo);
    xbt_free(rdv);  
  }
@@@ -135,7 -134,7 +134,7 @@@ smx_action_t SIMIX_rdv_get_request(smx_
    xbt_fifo_item_t item;
    void* req_data = NULL;
  
-   xbt_fifo_foreach(rdv->comm_fifo, item, action, smx_action_t){
+   xbt_fifo_foreach(rdv->comm_fifo, item, action, smx_action_t) {
      if (action->comm.type == SIMIX_COMM_SEND) {
        req_data = action->comm.src_data;
      } else if (action->comm.type == SIMIX_COMM_RECEIVE) {
@@@ -188,7 -187,7 +187,7 @@@ int SIMIX_comm_has_recv_match(smx_rdv_
    smx_action_t action;
    xbt_fifo_item_t item;
  
-   xbt_fifo_foreach(rdv->comm_fifo, item, action, smx_action_t){
+   xbt_fifo_foreach(rdv->comm_fifo, item, action, smx_action_t) {
      if (action->comm.type == SIMIX_COMM_RECEIVE
          && (!match_fun || match_fun(data, action->comm.dst_data))) {
        XBT_DEBUG("Found a matching communication action %p", action);
@@@ -214,6 -213,7 +213,7 @@@ smx_action_t SIMIX_comm_new(e_smx_comm_
  
    /* alloc structures */
    act = xbt_mallocator_get(simix_global->action_mallocator);
    act->type = SIMIX_ACTION_COMMUNICATE;
    act->state = SIMIX_WAITING;
  
   */
  void SIMIX_comm_destroy(smx_action_t action)
  {
-   XBT_DEBUG("Destroy action %p (refcount:%d)", action, action->comm.refcount);
+   XBT_DEBUG("Destroy action %p (refcount: %d), state: %d",
+       action, action->comm.refcount, action->state);
  
 -  xbt_assert(action->comm.refcount > 0,
 -      "The refcount of comm %p is already 0 before decreasing it. "
 -      "That's a bug!", action);
 -
 +  if (action->comm.refcount <= 0) {
 +      xbt_backtrace_display_current();
 +    xbt_die("the refcount of comm %p is already 0 before decreasing it. "
 +            "That's a bug!", action);
 +  }
    action->comm.refcount--;
    if (action->comm.refcount > 0)
      return;
@@@ -312,9 -311,10 +312,10 @@@ smx_action_t SIMIX_comm_isend(smx_proce
      action->state = SIMIX_READY;
      action->comm.type = SIMIX_COMM_READY;
    }
+   xbt_fifo_push(src_proc->comms, action);
  
-   /* If the communication action is detached then decrease the refcount
-    * by one, so it will be eliminated by the receivers destroy call */
+   /* if the communication action is detached then decrease the refcount
+    * by one, so it will be eliminated by the receiver's destroy call */
    if (detached) {
      action->comm.detached = 1;
      action->comm.refcount--;
    }
  
    SIMIX_comm_start(action);
 -  return action;
 +  return (detached ? NULL : action);
  }
  
  smx_action_t SIMIX_comm_irecv(smx_process_t dst_proc, smx_rdv_t rdv,
      action->state = SIMIX_READY;
      action->comm.type = SIMIX_COMM_READY;
    }
+   xbt_fifo_push(dst_proc->comms, action);
  
    /* Setup communication request */
    action->comm.dst_proc = dst_proc;
@@@ -515,6 -516,7 +517,7 @@@ XBT_INLINE void SIMIX_comm_start(smx_ac
  {
    /* If both the sender and the receiver are already there, start the communication */
    if (action->state == SIMIX_READY) {
      smx_host_t sender = action->comm.src_proc->smx_host;
      smx_host_t receiver = action->comm.dst_proc->smx_host;
  
    }
  }
  
+ /**
+  * \brief Answers the SIMIX requests associated to a communication action.
+  * \param action a finished communication action
+  */
  void SIMIX_comm_finish(smx_action_t action)
  {
-   unsigned int destroy_count = 0;
+   volatile unsigned int destroy_count = 0;
    smx_req_t req;
  
    while ((req = xbt_fifo_shift(action->request_list))) {
        case SIMIX_LINK_FAILURE:
          TRY {
          XBT_DEBUG("Link failure in action %p between '%s' and '%s': posting an exception to the issuer: %s (%p)",
-             action, action->comm.src_proc->smx_host->name, action->comm.dst_proc->smx_host->name,
+             action,
+             action->comm.src_proc ? action->comm.src_proc->smx_host->name : NULL,
+             action->comm.dst_proc ? action->comm.dst_proc->smx_host->name : NULL,
              req->issuer->name, req->issuer);
            THROWF(network_error, 0, "Link failure");
          }
          }
          break;
  
+       case SIMIX_CANCELED:
+         TRY {
+           if (req->issuer == action->comm.dst_proc) {
+             THROWF(cancel_error, 0, "Communication canceled by the sender");
+           }
+           else {
+             THROWF(cancel_error, 0, "Communication canceled by the receiver");
+           }
+         }
+         CATCH(req->issuer->running_ctx->exception) {
+           req->issuer->doexception = 1;
+         }
+         break;
        default:
-         THROW_IMPOSSIBLE;
+         xbt_die("Unexpected action state in SIMIX_comm_finish: %d", action->state);
      }
  
      /* if there is an exception during a waitany or a testany, indicate the position of the failed communication */
      }
  
      req->issuer->waiting_action = NULL;
+     xbt_fifo_remove(req->issuer->comms, action);
      SIMIX_request_answer(req);
      destroy_count++;
    }
      SIMIX_comm_destroy(action);
  }
  
+ /**
+  * \brief This function is called when a Surf communication action is finished.
+  * \param action the corresponding Simix communication
+  */
  void SIMIX_post_comm(smx_action_t action)
  {
    /* Update action state */
    else
      action->state = SIMIX_DONE;
  
-   XBT_DEBUG("SIMIX_post_comm: action state = %d", action->state);
+   XBT_DEBUG("SIMIX_post_comm: comm %p, state %d, src_proc %p, dst_proc %p, detached: %d",
+       action, action->state, action->comm.src_proc, action->comm.dst_proc, action->comm.detached);
  
-   /* After this point the surf actions associated with the simix communicate
-      action are no longer needed, thus we delete them. */
+   /* destroy the surf actions associated with the Simix communication */
    SIMIX_comm_destroy_internal_actions(action);
  
-   /* If there are requests associated with the action, then answer them */
-   if (xbt_fifo_size(action->request_list))
+   /* remove the communication action from the list of pending communications
+    * of both processes (if they still exist) */
+   if (action->comm.src_proc) {
+     xbt_fifo_remove(action->comm.src_proc->comms, action);
+   }
+   if (action->comm.dst_proc) {
+     xbt_fifo_remove(action->comm.dst_proc->comms, action);
+   }
+   /* if there are requests associated with the action, then answer them */
+   if (xbt_fifo_size(action->request_list)) {
      SIMIX_comm_finish(action);
+   }
  }
  
  void SIMIX_comm_cancel(smx_action_t action)
  {
-   /* If the action is a waiting state means that it is still in a rdv */
+   /* if the action is a waiting state means that it is still in a rdv */
    /* so remove from it and delete it */
    if (action->state == SIMIX_WAITING) {
      SIMIX_rdv_remove(action->comm.rdv, action);
-     action->state = SIMIX_FAILED;
-   } else {
-     /* When running the MC there are no surf actions */
-     if(!MC_IS_ENABLED)
-       surf_workstation_model->action_cancel(action->comm.surf_comm);
+     action->state = SIMIX_CANCELED;
+   }
+   else if (!MC_IS_ENABLED /* when running the MC there are no surf actions */
+       && (action->state == SIMIX_READY || action->state == SIMIX_RUNNING)) {
+     surf_workstation_model->action_cancel(action->comm.surf_comm);
    }
  }
  
@@@ -823,13 -861,6 +862,13 @@@ void SIMIX_comm_copy_buffer_callback(sm
    memcpy(comm->comm.dst_buff, comm->comm.src_buff, buff_size);
  }
  
 +void smpi_comm_copy_data_callback(smx_action_t comm, size_t buff_size)
 +{
 +  memcpy(comm->comm.dst_buff, comm->comm.src_buff, buff_size);
 +  if (comm->comm.detached) // if this is a detached send, the source buffer was duplicated by SMPI sender to make the original buffer available to the application ASAP
 +        free(comm->comm.src_buff);
 +}
 +
  /**
   *  \brief Copy the communication data from the sender's buffer to the receiver's one
   *  \param comm The communication
@@@ -854,8 -885,10 +893,15 @@@ void SIMIX_comm_copy_data(smx_action_t 
    if (comm->comm.dst_buff_size)
      *comm->comm.dst_buff_size = buff_size;
  
++<<<<<<< HEAD
 +  if (buff_size > 0)
 +    (*SIMIX_comm_copy_data_callback) (comm, buff_size);
++=======
+   if (buff_size == 0)
+     return;
+   SIMIX_comm_copy_data_callback(comm, buff_size);
++>>>>>>> master
  
    /* Set the copied flag so we copy data only once */
    /* (this function might be called from both communication ends) */
diff --combined src/smpi/smpi_bench.c
  /* 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 <math.h> // sqrt
  #include "private.h"
  #include "xbt/dict.h"
  #include "xbt/sysdep.h"
  #include "xbt/ex.h"
  #include "surf/surf.h"
  
 +#include <sys/mman.h>
 +#include <sys/stat.h>
 +#include <sys/types.h>
 +#include <errno.h>
 +#include <fcntl.h>
 +#include <unistd.h>
 +#include <string.h>
 +#include <stdio.h>
 +
  XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_bench, smpi,
                                  "Logging specific to SMPI (benchmarking)");
  
 -xbt_dict_t allocs = NULL;       /* Allocated on first use */
 -xbt_dict_t samples = NULL;      /* Allocated on first use */
 -xbt_dict_t calls = NULL;        /* Allocated on first use */
 +/* Shared allocations are handled through shared memory segments.
 + * Associated data and metadata are used as follows:
 + *
 + *                                                                    mmap #1
 + *    `allocs' dict                                                     ---- -.
 + *    ----------      shared_data_t               shared_metadata_t   / |  |  |
 + * .->| <name> | ---> -------------------- <--.   -----------------   | |  |  |
 + * |  ----------      | fd of <name>     |    |   | size of mmap  | --| |  |  |
 + * |                  | count (2)        |    |-- | data          |   \ |  |  |
 + * `----------------- | <name>           |    |   -----------------     ----  |
 + *                    --------------------    |   ^                           |
 + *                                            |   |                           |
 + *                                            |   |   `allocs_metadata' dict  |
 + *                                            |   |   ----------------------  |
 + *                                            |   `-- | <addr of mmap #1>  |<-'
 + *                                            |   .-- | <addr of mmap #2>  |<-.
 + *                                            |   |   ----------------------  |
 + *                                            |   |                           |
 + *                                            |   |                           |
 + *                                            |   |                           |
 + *                                            |   |                   mmap #2 |
 + *                                            |   v                     ---- -'
 + *                                            |   shared_metadata_t   / |  |
 + *                                            |   -----------------   | |  |
 + *                                            |   | size of mmap  | --| |  |
 + *                                            `-- | data          |   | |  |
 + *                                                -----------------   | |  |
 + *                                                                    \ |  |
 + *                                                                      ----
 + */
 +
 +#define PTR_STRLEN (2 + 2 * sizeof(void*) + 1)
 +
 +xbt_dict_t allocs = NULL;          /* Allocated on first use */
 +xbt_dict_t allocs_metadata = NULL; /* Allocated on first use */
 +xbt_dict_t samples = NULL;         /* Allocated on first use */
 +xbt_dict_t calls = NULL;           /* Allocated on first use */
 +__thread int smpi_current_rank = 0;      /* Updated after each MPI call */
  
  typedef struct {
 +  int fd;
    int count;
 -  char data[];
 +  char* loc;
  } shared_data_t;
  
 +typedef struct  {
 +  size_t size;
 +  shared_data_t* data;
 +} shared_metadata_t;
 +
 +static size_t shm_size(int fd) {
 +  struct stat st;
 +
 +  if(fstat(fd, &st) < 0) {
 +    xbt_die("Could not stat fd %d: %s", fd, strerror(errno));
 +  }
 +  return (size_t)st.st_size;
 +}
 +
 +static void* shm_map(int fd, size_t size, shared_data_t* data) {
 +  void* mem;
 +  char loc[PTR_STRLEN];
 +  shared_metadata_t* meta;
 +
 +  if(size > shm_size(fd)) {
 +    if(ftruncate(fd, (off_t)size) < 0) {
 +      xbt_die("Could not truncate fd %d to %zu: %s", fd, size, strerror(errno));
 +    }
 +  }
 +  mem = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
 +  if(mem == MAP_FAILED) {
 +    xbt_die("Could not map fd %d: %s", fd, strerror(errno));
 +  }
 +  if(!allocs_metadata) {
 +    allocs_metadata = xbt_dict_new();
 +  }
 +  snprintf(loc, PTR_STRLEN, "%p", mem);
 +  meta = xbt_new(shared_metadata_t, 1);
 +  meta->size = size;
 +  meta->data = data;
 +  xbt_dict_set(allocs_metadata, loc, meta, &free);
 +  XBT_DEBUG("MMAP %zu to %p", size, mem);
 +  return mem;
 +}
 +
  typedef struct {
    int count;
    double sum;
  
  void smpi_bench_destroy(void)
  {
-   if (allocs) {
-     xbt_dict_free(&allocs);
-   }
-   if (samples) {
-     xbt_dict_free(&samples);
-   }
-   if(calls) {
-     xbt_dict_free(&calls);
-   }
+   xbt_dict_free(&allocs);
+   xbt_dict_free(&samples);
+   xbt_dict_free(&calls);
  }
  
  static void smpi_execute_flops(double flops)
  
  static void smpi_execute(double duration)
  {
+   /* FIXME: a global variable would be less expensive to consult than a call to xbt_cfg_get_double() right on the critical path */
    if (duration >= xbt_cfg_get_double(_surf_cfg_set, "smpi/cpu_threshold")) {
      XBT_DEBUG("Sleep for %f to handle real computation time", duration);
      smpi_execute_flops(duration *
  void smpi_bench_begin(void)
  {
    xbt_os_timer_start(smpi_process_timer());
 +  smpi_current_rank = smpi_process_index();
  }
  
  void smpi_bench_end(void)
  
  unsigned int smpi_sleep(unsigned int secs)
  {
 +  smpi_bench_end();
    smpi_execute((double) secs);
 +  smpi_bench_begin();
    return secs;
  }
  
  int smpi_gettimeofday(struct timeval *tv, struct timezone *tz)
  {
 -  double now = SIMIX_get_clock();
 -
 +  double now;
 +  smpi_bench_end();
 +  now = SIMIX_get_clock();
    if (tv) {
 -    tv->tv_sec = (time_t) now;
 -    tv->tv_usec = (suseconds_t) (now * 1e6);
 +    tv->tv_sec = (time_t)now;
 +    tv->tv_usec = (suseconds_t)((now - tv->tv_sec) * 1e6);
    }
 +  smpi_bench_begin();
    return 0;
  }
  
@@@ -206,7 -112,7 +202,7 @@@ int smpi_sample_1(int global, const cha
  
    smpi_bench_end();     /* Take time from previous MPI call into account */
    if (!samples) {
-     samples = xbt_dict_new();
+     samples = xbt_dict_new_homogeneous(free);
    }
    data = xbt_dict_get_or_null(samples, loc);
    if (!data) {
      data->iters = iters;
      data->threshold = threshold;
      data->started = 0;
-     xbt_dict_set(samples, loc, data, &free);
+     xbt_dict_set(samples, loc, data, NULL);
      return 0;
    }
    free(loc);
@@@ -281,83 -187,41 +277,83 @@@ void smpi_sample_flops(double flops
  
  void *smpi_shared_malloc(size_t size, const char *file, int line)
  {
 -  char *loc = bprintf("%s:%d:%zu", file, line, size);
 +  char *loc = bprintf("%zu_%s_%d", (size_t)getpid(), file, line);
 +  size_t len = strlen(loc);
 +  size_t i;
 +  int fd;
 +  void* mem;
    shared_data_t *data;
  
 +  for(i = 0; i < len; i++) {
 +    /* Make the 'loc' ID be a flat filename */
 +    if(loc[i] == '/') {
 +      loc[i] = '_';
 +    }
 +  }
    if (!allocs) {
-     allocs = xbt_dict_new();
+     allocs = xbt_dict_new_homogeneous(free);
    }
    data = xbt_dict_get_or_null(allocs, loc);
 -  if (!data) {
 -    data = (shared_data_t *) xbt_malloc0(sizeof(int) + size);
 +  if(!data) {
 +    fd = shm_open(loc, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
 +    if(fd < 0) {
 +      switch(errno) {
 +        case EEXIST:
 +          xbt_die("Please cleanup /dev/shm/%s", loc);
 +        default:
 +          xbt_die("An unhandled error occured while opening %s: %s", loc, strerror(errno));
 +      }
 +    }
 +    data = xbt_new(shared_data_t, 1);
 +    data->fd = fd;
      data->count = 1;
-     xbt_dict_set(allocs, loc, data, &free);
 +    data->loc = loc;
 +    mem = shm_map(fd, size, data);
 +    if(shm_unlink(loc) < 0) {
 +      XBT_WARN("Could not early unlink %s: %s", loc, strerror(errno));
 +    }
+     xbt_dict_set(allocs, loc, data, NULL);
 +    XBT_DEBUG("Mapping %s at %p through %d", loc, mem, fd);
    } else {
 +    mem = shm_map(data->fd, size, data);
      data->count++;
    }
 -  free(loc);
 -  return data->data;
 +  XBT_DEBUG("Malloc %zu in %p (metadata at %p)", size, mem, data);
 +  return mem;
  }
  
  void smpi_shared_free(void *ptr)
  {
 -  shared_data_t *data = (shared_data_t *) ((int *) ptr - 1);
 -  char *loc;
 +  char loc[PTR_STRLEN];
 +  shared_metadata_t* meta;
 +  shared_data_t* data;
  
    if (!allocs) {
      XBT_WARN("Cannot free: nothing was allocated");
      return;
    }
 -  loc = xbt_dict_get_key(allocs, data);
 -  if (!loc) {
 +  if(!allocs_metadata) {
 +    XBT_WARN("Cannot free: no metadata was allocated");
 +  }
 +  snprintf(loc, PTR_STRLEN, "%p", ptr);
 +  meta = (shared_metadata_t*)xbt_dict_get_or_null(allocs_metadata, loc);
 +  if (!meta) {
      XBT_WARN("Cannot free: %p was not shared-allocated by SMPI", ptr);
      return;
    }
 +  data = meta->data;
 +  if(!data) {
 +    XBT_WARN("Cannot free: something is broken in the metadata link");
 +    return;
 +  }
 +  if(munmap(ptr, meta->size) < 0) {
 +    XBT_WARN("Unmapping of fd %d failed: %s", data->fd, strerror(errno));
 +  }
    data->count--;
    if (data->count <= 0) {
 -    xbt_dict_remove(allocs, loc);
 +    close(data->fd);
 +    xbt_dict_remove(allocs, data->loc);
 +    free(data->loc);
    }
  }
  
@@@ -367,7 -231,7 +363,7 @@@ int smpi_shared_known_call(const char* 
     int known;
  
     if(!calls) {
-       calls = xbt_dict_new();
+       calls = xbt_dict_new_homogeneous(NULL);
     }
     TRY {
        xbt_dict_get(calls, loc); /* Succeed or throw */
@@@ -390,7 -254,7 +386,7 @@@ void* smpi_shared_get_call(const char* 
     void* data;
  
     if(!calls) {
-       calls = xbt_dict_new();
+       calls = xbt_dict_new_homogeneous(NULL);
     }
     data = xbt_dict_get(calls, loc);
     free(loc);
@@@ -401,7 -265,7 +397,7 @@@ void* smpi_shared_set_call(const char* 
     char* loc = bprintf("%s:%s", func, input);
  
     if(!calls) {
-       calls = xbt_dict_new();
+       calls = xbt_dict_new_homogeneous(NULL);
     }
     xbt_dict_set(calls, loc, data, NULL);
     free(loc);
diff --combined src/smpi/smpi_f77.c
@@@ -28,7 -28,7 +28,7 @@@ static int new_comm(MPI_Comm comm) 
  static MPI_Comm get_comm(int comm) {
    if(comm == -2) {
      return MPI_COMM_SELF;
 -  } else if(comm >= 0) {
 +  } else if(comm_lookup && comm >= 0 && comm < (int)xbt_dynar_length(comm_lookup)) {
      return *(MPI_Comm*)xbt_dynar_get_ptr(comm_lookup, comm);
    }
    return MPI_COMM_NULL;
@@@ -79,7 -79,7 +79,7 @@@ void mpi_init__(int* ierr) 
     comm_lookup = xbt_dynar_new(sizeof(MPI_Comm), NULL);
     new_comm(MPI_COMM_WORLD);
  
-    request_lookup = xbt_dict_new();
+    request_lookup = xbt_dict_new_homogeneous(NULL);
  
     datatype_lookup = xbt_dynar_new(sizeof(MPI_Datatype), NULL);
     new_datatype(MPI_BYTE);
  void mpi_finalize__(int* ierr) {
     *ierr = MPI_Finalize();
     xbt_dynar_free(&op_lookup);
 +   op_lookup = NULL;
     xbt_dynar_free(&datatype_lookup);
 +   datatype_lookup = NULL;
     xbt_dict_free(&request_lookup);
 +   request_lookup = NULL;
     xbt_dynar_free(&comm_lookup);
 +   comm_lookup = NULL;
  }
  
  void mpi_abort__(int* comm, int* errorcode, int* ierr) {
diff --combined src/smpi/smpi_global.c
@@@ -5,7 -5,6 +5,7 @@@
    * under the terms of the license (GNU LGPL) which comes with this package. */
  
  #include <stdint.h>
 +#include <stdio.h>
  #include <stdlib.h>
  
  #include "private.h"
@@@ -99,7 -98,6 +99,7 @@@ int smpi_global_size(void) 
     char* value = getenv("SMPI_GLOBAL_SIZE");
  
     if(!value) {
 +      fprintf(stderr, "Please set env var SMPI_GLOBAL_SIZE to expected number of processes.\n");
        abort();
     }
     return atoi(value);
  
  smpi_process_data_t smpi_process_data(void)
  {
-   return SIMIX_process_self_get_data();
+   return SIMIX_process_self_get_data(SIMIX_process_self());
  }
  
  smpi_process_data_t smpi_process_remote_data(int index)
@@@ -180,7 -178,8 +180,7 @@@ void smpi_global_init(void
    MPI_Group group;
    char name[MAILBOX_NAME_MAXLEN];
  
 -  SIMIX_comm_set_copy_data_callback
 -      (&SIMIX_comm_copy_buffer_callback);
 +  SIMIX_comm_set_copy_data_callback(&smpi_comm_copy_data_callback);
    process_count = SIMIX_process_count();
    process_data = xbt_new(smpi_process_data_t, process_count);
    for (i = 0; i < process_count; i++) {
@@@ -254,6 -253,7 +254,7 @@@ int MAIN__(void
                     NULL);
  
    if(getenv("SMPI_PRETEND_CC") != NULL) {
+       /* Hack to ensure that smpicc can pretend to be a simple compiler. Particularly handy to pass it to the configuration tools */
      return 0;
    }
  
      SIMIX_run();
  
    if (xbt_cfg_get_int(_surf_cfg_set, "smpi/display_timing"))
-     XBT_INFO("simulation time %g", SIMIX_get_clock());
+     XBT_INFO("Simulation time: %g seconds.", SIMIX_get_clock());
  
    smpi_global_destroy();
  
diff --combined src/surf/network.c
@@@ -1,4 -1,12 +1,12 @@@
- /* Copyright (c) 2004, 2005, 2006, 2007, 2008, 2009, 2010. The SimGrid Team.
+ /*
+  * Network with improved management of tasks, IM (Improved Management).
+  * Uses a heap to store actions so that the share_resources is faster.
+  * This model automatically sets the selective update flag to 1 and is
+  * highly dependent on the maxmin lmm module.
+  */
+ /* Copyright (c) 2009, 2010, 2011. The SimGrid Team.
   * All rights reserved.                                                     */
  
  /* This program is free software; you can redistribute it and/or modify it
  #include "xbt/log.h"
  #include "xbt/str.h"
  
+ #include "surf_private.h"
+ #include "xbt/dict.h"
+ #include "maxmin_private.h"
+ #include "surf/surfxml_parse_values.h"
+ #include "surf/surf_resource.h"
+ #include "surf/surf_resource_lmm.h"
+ #undef GENERIC_ACTION
+ #define GENERIC_ACTION(action) action->generic_action
  XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_network, surf,
                                  "Logging specific to the SURF network module");
  
@@@ -21,67 -40,43 +40,43 @@@ double sg_bandwidth_factor = 1.0
  double sg_weight_S_parameter = 0.0;     /* default value; can be set by model or from command line */
  
  double sg_tcp_gamma = 0.0;
- int sg_network_fullduplex = 0;
+ int sg_network_crosstraffic = 0;
  
  xbt_dict_t gap_lookup = NULL;
  
- static double net_get_link_bandwidth(const void *link);
+ e_UM_t network_update_mechanism = UM_UNDEFINED;
+ static int selective_update = 0;
  
- static void gap_append(double size, const link_CM02_t link, surf_action_network_CM02_t action) {
-    const char* src = link->lmm_resource.generic_resource.name;
-    xbt_fifo_t fifo;
-    surf_action_network_CM02_t last_action;
-    double bw;
+ static int net_action_is_suspended(surf_action_t action);
+ static void update_action_remaining(double now);
  
-    if(sg_sender_gap > 0.0) {
-       if(!gap_lookup) {
-          gap_lookup = xbt_dict_new();
-       }
-       fifo = (xbt_fifo_t)xbt_dict_get_or_null(gap_lookup, src);
-       action->sender.gap = 0.0;
-       if(fifo && xbt_fifo_size(fifo) > 0) {
-          /* Compute gap from last send */
-          last_action = (surf_action_network_CM02_t)xbt_fifo_get_item_content(xbt_fifo_get_last_item(fifo));
-          bw = net_get_link_bandwidth(link);
-          action->sender.gap = last_action->sender.gap + max(sg_sender_gap, last_action->sender.size / bw);
-          action->latency += action->sender.gap;
-       }
-       /* Append action as last send */
-       action->sender.link_name = link->lmm_resource.generic_resource.name;
-       fifo = (xbt_fifo_t)xbt_dict_get_or_null(gap_lookup, action->sender.link_name);
-       if(!fifo) {
-          fifo = xbt_fifo_new();
-          xbt_dict_set(gap_lookup, action->sender.link_name, fifo, NULL);
-       }
-       action->sender.fifo_item = xbt_fifo_push(fifo, action);
-       action->sender.size = size;
-    }
- }
+ static xbt_swag_t net_modified_set = NULL;
+ static xbt_heap_t net_action_heap = NULL;
+ xbt_swag_t keep_track = NULL;
  
- static void gap_unknown(surf_action_network_CM02_t action) {
-    action->sender.gap = 0.0;
-    action->sender.link_name = NULL;
-    action->sender.fifo_item = NULL;
-    action->sender.size = 0.0;
+ /* added to manage the communication action's heap */
+ static void net_action_update_index_heap(void *action, int i)
+ {
+   ((surf_action_network_CM02_t) action)->index_heap = i;
  }
  
- static void gap_remove(surf_action_network_CM02_t action) {
-    xbt_fifo_t fifo;
-    size_t size;
+ /* insert action on heap using a given key and a hat (heap_action_type)
+  * a hat can be of three types for communications:
+  *
+  * NORMAL = this is a normal heap entry stating the date to finish transmitting
+  * LATENCY = this is a heap entry to warn us when the latency is payed
+  * MAX_DURATION =this is a heap entry to warn us when the max_duration limit is reached
+  */
+ static void heap_insert(surf_action_network_CM02_t    action, double key, enum heap_action_type hat){
+   action->hat = hat;
+   xbt_heap_push(net_action_heap, action, key);
+ }
  
-    if(sg_sender_gap > 0.0 && action->sender.link_name && action->sender.fifo_item) {
-       fifo = (xbt_fifo_t)xbt_dict_get_or_null(gap_lookup, action->sender.link_name);
-       xbt_fifo_remove_item(fifo, action->sender.fifo_item);
-       size = xbt_fifo_size(fifo);
-       if(size == 0) {
-          xbt_fifo_free(fifo);
-          xbt_dict_remove(gap_lookup, action->sender.link_name);
-          size = xbt_dict_size(gap_lookup);
-          if(size == 0) {
-             xbt_dict_free(&gap_lookup);
-          }
-       }
-    }
+ static void heap_remove(surf_action_network_CM02_t action){
+   action->hat = NONE;
+   if(((surf_action_network_CM02_t) action)->index_heap >= 0){
+       xbt_heap_remove(net_action_heap,action->index_heap);
+   }
  }
  
  /******************************************************************************/
@@@ -103,54 -98,41 +98,46 @@@ static double constant_bandwidth_constr
    return rate;
  }
  
- /**--------- <copy/paste C code snippet in surf/network.c> -------------
-   * produced by:
-   * ./regression2.py ./pingpong-in.dat 0.15 100 2 2.4e-5 1.25e8
-   * outliers: 65
-   * gnuplot: 
-     plot "./pingpong-in.dat" using 1:2 with lines title "data", \
-         (x >= 65472) ? 0.00850436*x+558.894 : \
-         (x >= 15424) ? 0.0114635*x+167.446 : \
-         (x >= 9376) ? 0.0136219*x+124.464 : \
-         (x >= 5776) ? 0.00735707*x+105.022 : \
-         (x >= 3484) ? 0.0103235*x+90.2886 : \
-         (x >= 1426) ? 0.0131384*x+77.3159 : \
-         (x >= 732) ? 0.0233927*x+93.6146 : \
-         (x >= 257) ? 0.0236608*x+93.7637 : \
-         (x >= 0) ? 0.00985119*x+96.704 : \
-         1.0 with lines title "piecewise function"
-   *-------------------------------------------------------------------*/
 -
+ /**********************/
+ /*   SMPI callbacks   */
+ /**********************/
+ static double smpi_latency_factor(double size)
+ {
+   /* 1 B <= size <= 1 KiB */
+   if (size <= 1024.0) {
+     return 1.0056;
+   }
  
 -  /* 2 KiB <= size <= 32 KiB */
 -  if (size <= 32768.0) {
 -    return 1.8805;
 -  }
 +static double smpi_bandwidth_factor(double size)
 +{
  
 -  /* 64 KiB <= size <= 4 MiB */
 -  return 22.7111;
 +    if (size >= 65472) return 0.940694;
 +    if (size >= 15424) return 0.697866;
 +    if (size >= 9376) return 0.58729;
 +    if (size >= 5776) return 1.08739;
 +    if (size >= 3484) return 0.77493;
 +    if (size >= 1426) return 0.608902;
 +    if (size >= 732) return 0.341987;
 +    if (size >= 257) return 0.338112;
 +    if (size >= 0) return 0.812084;
 +    return 1.0;
  }
  
 -static double smpi_bandwidth_factor(double size)
 +static double smpi_latency_factor(double size)
  {
 -  /* 1 B <= size <= 1 KiB */
 -  if (size <= 1024.0) {
 -    return 0.2758;
 -  }
 -
 -  /* 2 KiB <= size <= 32 KiB */
 -  if (size <= 32768.0) {
 -    return 0.5477;
 -  }
  
 -  /* 64 KiB <= size <= 4 MiB */
 -  return 0.9359;
 +    if (size >= 65472) return 11.6436;
 +    if (size >= 15424) return 3.48845;
 +    if (size >= 9376) return 2.59299;
 +    if (size >= 5776) return 2.18796;
 +    if (size >= 3484) return 1.88101;
 +    if (size >= 1426) return 1.61075;
 +    if (size >= 732) return 1.9503;
 +    if (size >= 257) return 1.95341;
 +    if (size >= 0) return 2.01467;
 +    return 1.0;
  }
 +/**--------- <copy/paste C code snippet in surf/network.c> -----------*/
  
  static double smpi_bandwidth_constraint(double rate, double bound,
                                          double size)
    return rate < 0 ? bound : min(bound, rate * smpi_bandwidth_factor(size));
  }
  
  static double (*latency_factor_callback) (double) =
      &constant_latency_factor;
  static double (*bandwidth_factor_callback) (double) =
  static double (*bandwidth_constraint_callback) (double, double, double) =
      &constant_bandwidth_constraint;
  
+ static void (*gap_append) (double, const link_CM02_t, surf_action_network_CM02_t) = NULL;
+ static void (*gap_remove) (surf_action_network_CM02_t) = NULL;
  
- static link_CM02_t net_link_new(char *name,
+ static void* net_create_resource(const char *name,
                                  double bw_initial,
                                  tmgr_trace_t bw_trace,
                                  double lat_initial,
    return nw_link;
  }
  
- static void net_parse_link_init(void)
- {
-   char *name_link;
-   double bw_initial;
-   tmgr_trace_t bw_trace;
-   double lat_initial;
-   tmgr_trace_t lat_trace;
-   e_surf_resource_state_t state_initial_link = SURF_RESOURCE_ON;
-   e_surf_link_sharing_policy_t policy_initial_link = SURF_LINK_SHARED;
-   tmgr_trace_t state_trace;
-   XBT_DEBUG("link_CM02");
-   name_link = xbt_strdup(A_surfxml_link_id);
-   surf_parse_get_double(&bw_initial, A_surfxml_link_bandwidth);
-   bw_trace = tmgr_trace_new(A_surfxml_link_bandwidth_file);
-   surf_parse_get_double(&lat_initial, A_surfxml_link_latency);
-   lat_trace = tmgr_trace_new(A_surfxml_link_latency_file);
-   xbt_assert((A_surfxml_link_state == A_surfxml_link_state_ON)
-               || (A_surfxml_link_state ==
-                   A_surfxml_link_state_OFF), "Invalid state");
-   if (A_surfxml_link_state == A_surfxml_link_state_ON)
-     state_initial_link = SURF_RESOURCE_ON;
-   else if (A_surfxml_link_state == A_surfxml_link_state_OFF)
-     state_initial_link = SURF_RESOURCE_OFF;
-   if (A_surfxml_link_sharing_policy == A_surfxml_link_sharing_policy_SHARED)
-     policy_initial_link = SURF_LINK_SHARED;
-   else
-         {
-         if (A_surfxml_link_sharing_policy == A_surfxml_link_sharing_policy_FATPIPE)
-                 policy_initial_link = SURF_LINK_FATPIPE;
-         else if (A_surfxml_link_sharing_policy == A_surfxml_link_sharing_policy_FULLDUPLEX)
-                 policy_initial_link = SURF_LINK_FULLDUPLEX;
-         }
-   state_trace = tmgr_trace_new(A_surfxml_link_state_file);
-   if(policy_initial_link == SURF_LINK_FULLDUPLEX)
-   {
-         net_link_new(bprintf("%s_UP",name_link), bw_initial, bw_trace,
-                      lat_initial, lat_trace, state_initial_link, state_trace,
-                      policy_initial_link, xbt_dict_new());
-         net_link_new(bprintf("%s_DOWN",name_link), bw_initial, bw_trace,
-                      lat_initial, lat_trace, state_initial_link, state_trace,
-                      policy_initial_link, xbt_dict_new());
+ static void net_parse_link_init(sg_platf_link_cbarg_t link)
+ {
+   if(link->policy == SURF_LINK_FULLDUPLEX){
+     char *link_id;
+     link_id = bprintf("%s_UP", link->id);
+         net_create_resource(link_id,
+                            link->bandwidth,
+                            link->bandwidth_trace,
+                            link->latency,
+                            link->latency_trace,
+                            link->state,
+                            link->state_trace,
+                            link->policy,
+                            link->properties);
+         xbt_free(link_id);
+     link_id = bprintf("%s_DOWN", link->id);
+     net_create_resource(link_id,
+                         link->bandwidth,
+                         link->bandwidth_trace,
+                         link->latency,
+                         link->latency_trace,
+                         link->state,
+                         link->state_trace,
+                         link->policy,
+                         link->properties);
+     xbt_free(link_id);
    }
-   else
-   {
-         net_link_new(name_link, bw_initial, bw_trace,
-                      lat_initial, lat_trace, state_initial_link, state_trace,
-                      policy_initial_link, xbt_dict_new());
+   else{
+     net_create_resource(link->id,
+                         link->bandwidth,
+                         link->bandwidth_trace,
+                         link->latency,
+                         link->latency_trace,
+                         link->state,
+                         link->state_trace,
+                         link->policy,
+                         link->properties);
    }
- }
- static void net_create_resource(char *name,
-                                 double bw_initial,
-                                 tmgr_trace_t bw_trace,
-                                 double lat_initial,
-                                 tmgr_trace_t lat_trace,
-                                 e_surf_resource_state_t
-                                 state_initial,
-                                 tmgr_trace_t state_trace,
-                                 e_surf_link_sharing_policy_t policy,
-                                 xbt_dict_t properties)
- {
-   net_link_new(name, bw_initial, bw_trace,
-                lat_initial, lat_trace, state_initial, state_trace,
-                policy, xbt_dict_new());
  }
  
  static void net_add_traces(void)
    xbt_dict_foreach(trace_connect_list_link_avail, cursor, trace_name, elm) {
      tmgr_trace_t trace = xbt_dict_get_or_null(traces_set_list, trace_name);
      link_CM02_t link =
-         xbt_lib_get_or_null(link_lib, elm, SURF_LINK_LEVEL);
+               xbt_lib_get_or_null(link_lib, elm, SURF_LINK_LEVEL);
  
      xbt_assert(link, "Cannot connect trace %s to link %s: link undefined",
                  trace_name, elm);
    }
  }
  
- static void net_define_callbacks(const char *file)
+ static void net_define_callbacks(void)
  {
    /* Figuring out the network links */
-   surfxml_add_callback(STag_surfxml_link_cb_list, &net_parse_link_init);
-   surfxml_add_callback(ETag_surfxml_platform_cb_list, &net_add_traces);
+   sg_platf_link_add_cb(net_parse_link_init);
+   sg_platf_postparse_add_cb(net_add_traces);
  }
  
  static int net_resource_used(void *resource_id)
@@@ -350,14 -302,18 +307,18 @@@ static int net_action_unref(surf_action
    action->refcount--;
    if (!action->refcount) {
      xbt_swag_remove(action, action->state_set);
-     if (((surf_action_network_CM02_t) action)->variable)
+     if (((surf_action_network_CM02_t) action)->variable){
        lmm_variable_free(network_maxmin_system,
                          ((surf_action_network_CM02_t) action)->variable);
+     }
+     if(network_update_mechanism == UM_LAZY){// remove action from the heap
+       heap_remove((surf_action_network_CM02_t) action);
+       xbt_swag_remove(action, net_modified_set);
+     }
  #ifdef HAVE_TRACING
      xbt_free(((surf_action_network_CM02_t) action)->src_name);
      xbt_free(((surf_action_network_CM02_t) action)->dst_name);
-     if (action->category)
-       xbt_free(action->category);
+     xbt_free(action->category);
  #endif
      surf_action_free(&action);
      return 1;
    return 0;
  }
  
  static void net_action_cancel(surf_action_t action)
  {
    surf_network_model->action_state_set(action, SURF_ACTION_FAILED);
+   if(network_update_mechanism == UM_LAZY){// remove action from the heap
+     xbt_swag_remove(action, net_modified_set);
+     heap_remove((surf_action_network_CM02_t) action);
+   }
  }
  
  void net_action_recycle(surf_action_t action)
  }
  
  #ifdef HAVE_LATENCY_BOUND_TRACKING
- int net_get_link_latency_limited(surf_action_t action)
static int net_get_link_latency_limited(surf_action_t action)
  {
    return action->latency_limited;
  }
  
  double net_action_get_remains(surf_action_t action)
  {
+   if(network_update_mechanism == UM_LAZY)/* update remains before return it */
+     update_action_remaining(surf_get_clock());
    return action->remains;
  }
  
- static double net_share_resources(double now)
+ static void update_action_remaining(double now){
+   surf_action_network_CM02_t action = NULL;
+   double delta = 0.0;
+   xbt_swag_foreach(action, net_modified_set) {
+     if(action->suspended != 0){
+         continue;
+     }
+     delta = now - action->last_update;
+     double_update(&(action->generic_action.remains),
+                   lmm_variable_getvalue(action->variable) * delta);
+     if (action->generic_action.max_duration != NO_MAX_DURATION)
+       double_update(&(action->generic_action.max_duration), delta);
+     if ((action->generic_action.remains <= 0) &&
+         (lmm_get_variable_weight(action->variable) > 0)) {
+       action->generic_action.finish = surf_get_clock();
+       surf_network_model->action_state_set((surf_action_t) action,
+                                            SURF_ACTION_DONE);
+       heap_remove(action);
+     } else if ((action->generic_action.max_duration != NO_MAX_DURATION)
+                && (action->generic_action.max_duration <= 0)) {
+       action->generic_action.finish = surf_get_clock();
+       surf_network_model->action_state_set((surf_action_t) action,
+                                            SURF_ACTION_DONE);
+       heap_remove(action);
+     }
+     action->last_update = now;
+   }
+ }
+ static double net_share_resources_full(double now)
  {
    s_surf_action_network_CM02_t s_action;
    surf_action_network_CM02_t action = NULL;
      }
  #endif
      if (action->latency > 0) {
-       if (min < 0)
-         min = action->latency;
-       else if (action->latency < min)
-         min = action->latency;
+       min = (min<0)?action->latency:min(min,action->latency);
      }
    }
  
    return min;
  }
  
- static void net_update_actions_state(double now, double delta)
+ static double net_share_resources_lazy(double now)
+ {
+   surf_action_network_CM02_t action = NULL;
+   double min=-1;
+   double value;
+   XBT_DEBUG("Before share resources, the size of modified actions set is %d", xbt_swag_size(net_modified_set));
+   update_action_remaining(now);
+   keep_track = net_modified_set;
+   lmm_solve(network_maxmin_system);
+   keep_track = NULL;
+   XBT_DEBUG("After share resources, The size of modified actions set is %d", xbt_swag_size(net_modified_set));
+   xbt_swag_foreach(action, net_modified_set) {
+     int max_dur_flag = 0;
+     if (GENERIC_ACTION(action).state_set != surf_network_model->states.running_action_set){
+       continue;
+     }
+     /* bogus priority, skip it */
+     if (GENERIC_ACTION(action).priority <= 0){
+       continue;
+     }
+     min = -1;
+     value = lmm_variable_getvalue(action->variable);
+     if (value > 0) {
+       if (GENERIC_ACTION(action).remains > 0) {
+         value = GENERIC_ACTION(action).remains / value;
+         min = now + value;
+       } else {
+         value = 0.0;
+         min = now;
+       }
+     }
+     if ((GENERIC_ACTION(action).max_duration != NO_MAX_DURATION)
+         && (min == -1
+             || GENERIC_ACTION(action).start +
+             GENERIC_ACTION(action).max_duration < min)){
+       min =   GENERIC_ACTION(action).start +
+           GENERIC_ACTION(action).max_duration;
+       max_dur_flag = 1;
+     }
+     XBT_DEBUG("Action(%p) Start %lf Finish %lf Max_duration %lf", action,
+         GENERIC_ACTION(action).start, now + value,
+         GENERIC_ACTION(action).max_duration);
+     if (action->index_heap >= 0) {
+       heap_remove((surf_action_network_CM02_t) action);
+     }
+     if (min != -1) {
+       heap_insert((surf_action_network_CM02_t) action, min, max_dur_flag?MAX_DURATION:NORMAL);
+       XBT_DEBUG("Insert at heap action(%p) min %lf now %lf", action, min, now);
+     }
+   }
+   //hereafter must have already the min value for this resource model
+   if(xbt_heap_size(net_action_heap) > 0 ){
+     min = xbt_heap_maxkey(net_action_heap) - now ;
+   }else{
+     min = -1;
+   }
+   XBT_DEBUG("The minimum with the HEAP %lf", min);
+   return min;
+ }
+ static void net_update_actions_state_full(double now, double delta)
  {
    double deltap = 0.0;
    surf_action_network_CM02_t action = NULL;
      }
  #ifdef HAVE_TRACING
      if (TRACE_is_enabled()) {
-       xbt_dynar_t route = global_routing->get_route(action->src_name,
-                                                     action->dst_name);
+       xbt_dynar_t route=NULL;
+       routing_get_route_and_latency(action->src_name, action->dst_name,&route,NULL);
        link_CM02_t link;
        unsigned int i;
        xbt_dynar_foreach(route, i, link) {
      }
  #endif
      if(!lmm_get_number_of_cnst_from_var(network_maxmin_system, action->variable)) {
-                               /* There is actually no link used, hence an infinite bandwidth.
-                                * This happens often when using models like vivaldi.
-                                * In such case, just make sure that the action completes immediately.
-                                */
-       double_update(&(action->generic_action.remains),
-                       action->generic_action.remains);
+         /* There is actually no link used, hence an infinite bandwidth.
+          * This happens often when using models like vivaldi.
+          * In such case, just make sure that the action completes immediately.
+          */
+       double_update(&(action->generic_action.remains),
+           action->generic_action.remains);
      }
      double_update(&(action->generic_action.remains),
                    lmm_variable_getvalue(action->variable) * deltap);
        action->generic_action.finish = surf_get_clock();
        surf_network_model->action_state_set((surf_action_t) action,
                                             SURF_ACTION_DONE);
-       gap_remove(action);
+       if(gap_remove) gap_remove(action);
      } else if ((action->generic_action.max_duration != NO_MAX_DURATION)
                 && (action->generic_action.max_duration <= 0)) {
        action->generic_action.finish = surf_get_clock();
        surf_network_model->action_state_set((surf_action_t) action,
                                             SURF_ACTION_DONE);
-       gap_remove(action);
+       if(gap_remove) gap_remove(action);
      }
    }
  
    return;
  }
  
+ static void net_update_actions_state_lazy(double now, double delta)
+ {
+   surf_action_network_CM02_t action = NULL;
+   while ((xbt_heap_size(net_action_heap) > 0)
+          && (double_equals(xbt_heap_maxkey(net_action_heap), now))) {
+     action = xbt_heap_pop(net_action_heap);
+     XBT_DEBUG("Action %p: finish", action);
+     GENERIC_ACTION(action).finish = surf_get_clock();
+     // if I am wearing a latency heat
+     if( action->hat ==  LATENCY){
+         lmm_update_variable_weight(network_maxmin_system, action->variable,
+                                            action->weight);
+         heap_remove(action);
+         action->last_update = surf_get_clock();
+     // if I am wearing a max_duration or normal hat
+     }else if( action->hat == MAX_DURATION || action->hat == NORMAL ){
+         // no need to communicate anymore
+         // assume that flows that reached max_duration have remaining of 0
+         GENERIC_ACTION(action).remains = 0;
+         action->generic_action.finish = surf_get_clock();
+               surf_network_model->action_state_set((surf_action_t) action,
+                                                    SURF_ACTION_DONE);
+         heap_remove(action);
+     }
+   }
+   return;
+ }
  static void net_update_resource_state(void *id,
                                        tmgr_trace_event_t event_type,
                                        double value, double date)
                                  (nw_link->lmm_resource.power.peak *
                                   nw_link->lmm_resource.power.scale));
  #ifdef HAVE_TRACING
-     TRACE_surf_link_set_bandwidth(date, nw_link->lmm_resource.generic_resource.name,
+     TRACE_surf_link_set_bandwidth(date, (char *)(((nw_link->lmm_resource).generic_resource).name),
                                    sg_bandwidth_factor *
                                    (nw_link->lmm_resource.power.peak *
                                     nw_link->lmm_resource.power.scale));
      xbt_abort();
    }
  
+   XBT_DEBUG("There were a resource state event, need to update actions related to the constraint (%p)", nw_link->lmm_resource.constraint);
    return;
  }
  
@@@ -618,27 -722,15 +727,15 @@@ static surf_action_t net_communicate(co
    surf_action_network_CM02_t action = NULL;
    double bandwidth_bound;
    double latency=0.0;
-   /* LARGE PLATFORMS HACK:
-      Add a link_CM02_t *link and a int link_nb to network_card_CM02_t. It will represent local links for this node
-      Use the cluster_id for ->id */
    xbt_dynar_t back_route = NULL;
    int constraints_per_variable = 0;
-   xbt_dynar_t route;
-   // I will need this route for some time so require for no cleanup
-   global_routing->get_route_latency(src_name, dst_name, &route, &latency, 0);
-   if (sg_network_fullduplex == 1) {
-     back_route = global_routing->get_route(dst_name, src_name);
-   }
  
-   /* LARGE PLATFORMS HACK:
-      total_route_size = route_size + src->link_nb + dst->nb */
+   xbt_dynar_t route=xbt_dynar_new(global_routing->size_of_link,NULL);
  
    XBT_IN("(%s,%s,%g,%g)", src_name, dst_name, size, rate);
-   /* LARGE PLATFORMS HACK:
-      assert on total_route_size */
-   xbt_assert(xbt_dynar_length(route) || latency,
+   routing_get_route_and_latency(src_name, dst_name, &route, &latency);
+   xbt_assert(!xbt_dynar_is_empty(route) || latency,
                "You're trying to send data from %s to %s but there is no connection at all between these two hosts.",
                src_name, dst_name);
  
        break;
      }
    }
+   if (sg_network_crosstraffic == 1) {
+     routing_get_route_and_latency(dst_name, src_name, &back_route,NULL);
+     xbt_dynar_foreach(back_route, i, link) {
+       if (link->lmm_resource.state_current == SURF_RESOURCE_OFF) {
+         failed = 1;
+         break;
+       }
+     }
+   }
    action =
        surf_action_new(sizeof(s_surf_action_network_CM02_t), size,
                        surf_network_model, failed);
  
    xbt_swag_insert(action, action->generic_action.state_set);
    action->rate = rate;
+   if(network_update_mechanism == UM_LAZY){
+     action->index_heap = -1;
+     action->last_update = surf_get_clock();
+   }
  
    bandwidth_bound = -1.0;
+   if(sg_weight_S_parameter>0) {
+     xbt_dynar_foreach(route, i, link) {
+       action->weight +=
+           sg_weight_S_parameter /
+           (link->lmm_resource.power.peak * link->lmm_resource.power.scale);
+     }
+   }
    xbt_dynar_foreach(route, i, link) {
-     action->weight +=
-         sg_weight_S_parameter /
+     double bb = bandwidth_factor_callback(size) *
          (link->lmm_resource.power.peak * link->lmm_resource.power.scale);
-     if (bandwidth_bound < 0.0)
-       bandwidth_bound =
-           (*bandwidth_factor_callback) (size) *
-           (link->lmm_resource.power.peak * link->lmm_resource.power.scale);
-     else
-       bandwidth_bound =
-           min(bandwidth_bound,
-               (*bandwidth_factor_callback) (size) *
-               (link->lmm_resource.power.peak *
-                link->lmm_resource.power.scale));
+     bandwidth_bound = (bandwidth_bound < 0.0)?bb:min(bandwidth_bound,bb);
    }
-   /* LARGE PLATFORMS HACK:
-      Add src->link and dst->link latencies */
    action->lat_current = action->latency;
-   action->latency *= (*latency_factor_callback) (size);
+   action->latency *= latency_factor_callback(size);
    action->rate =
-       (*bandwidth_constraint_callback) (action->rate, bandwidth_bound,
+       bandwidth_constraint_callback(action->rate, bandwidth_bound,
                                          size);
+   if(gap_append) {
+     xbt_assert(!xbt_dynar_is_empty(route),"Using a model with a gap (e.g., SMPI) with a platform without links (e.g. vivaldi)!!!");
  
-   if(xbt_dynar_length(route) > 0) {
      link = *(link_CM02_t*)xbt_dynar_get_ptr(route, 0);
      gap_append(size, link, action);
      XBT_DEBUG("Comm %p: %s -> %s gap=%f (lat=%f)",
             action, src_name, dst_name, action->sender.gap, action->latency);
-   } else {
-     gap_unknown(action);
    }
  
+   constraints_per_variable = xbt_dynar_length(route);
+   if (back_route != NULL)
+     constraints_per_variable += xbt_dynar_length(back_route);
  
-   /* LARGE PLATFORMS HACK:
-      lmm_variable_new(..., total_route_size) */
-   if (back_route != NULL) {
-     constraints_per_variable =
-         xbt_dynar_length(route) + xbt_dynar_length(back_route);
-   } else {
-     constraints_per_variable = xbt_dynar_length(route);
-   }
-   if (action->latency > 0)
-     action->variable =
+   if (action->latency > 0){
+       action->variable =
          lmm_variable_new(network_maxmin_system, action, 0.0, -1.0,
                           constraints_per_variable);
-   else
+     if(network_update_mechanism == UM_LAZY){
+       // add to the heap the event when the latency is payed
+       XBT_DEBUG("Added action (%p) one latency event at date %f", action, action->latency + action->last_update);
+       heap_insert(action, action->latency + action->last_update, xbt_dynar_is_empty(route)?NORMAL:LATENCY);
+     }
+   } else
      action->variable =
          lmm_variable_new(network_maxmin_system, action, 1.0, -1.0,
                           constraints_per_variable);
  
    if (action->rate < 0) {
-     if (action->lat_current > 0)
-       lmm_update_variable_bound(network_maxmin_system, action->variable,
-                                 sg_tcp_gamma / (2.0 *
-                                                 action->lat_current));
-     else
-       lmm_update_variable_bound(network_maxmin_system, action->variable,
-                                 -1.0);
+     lmm_update_variable_bound(network_maxmin_system, action->variable,
+         (action->lat_current > 0)?
+             sg_tcp_gamma / (2.0 * action->lat_current)  :-1.0);
    } else {
-     if (action->lat_current > 0)
-       lmm_update_variable_bound(network_maxmin_system, action->variable,
-                                 min(action->rate,
-                                     sg_tcp_gamma / (2.0 *
-                                                     action->lat_current)));
-     else
-       lmm_update_variable_bound(network_maxmin_system, action->variable,
-                                 action->rate);
+     lmm_update_variable_bound(network_maxmin_system, action->variable,
+         (action->lat_current > 0)?
+             min(action->rate, sg_tcp_gamma / (2.0 * action->lat_current))
+             :action->rate);
    }
  
    xbt_dynar_foreach(route, i, link) {
                 action->variable, 1.0);
    }
  
-   if (sg_network_fullduplex == 1) {
-     XBT_DEBUG("Fullduplex active adding backward flow using 5%c", '%');
+   if (sg_network_crosstraffic == 1) {
+     XBT_DEBUG("Fullduplex active adding backward flow using 5%%");
      xbt_dynar_foreach(back_route, i, link) {
        lmm_expand(network_maxmin_system, link->lmm_resource.constraint,
                   action->variable, .05);
      }
    }
-   /* LARGE PLATFORMS HACK:
-      expand also with src->link and dst->link */
  #ifdef HAVE_TRACING
    if (TRACE_is_enabled()) {
      action->src_name = xbt_strdup(src_name);
  
  static xbt_dynar_t net_get_route(const char *src, const char *dst)
  {
-   return global_routing->get_route(src, dst);
+   xbt_dynar_t route=NULL;
+   routing_get_route_and_latency(src, dst,&route,NULL);
+   return route;
  }
  
  static double net_get_link_bandwidth(const void *link)
@@@ -788,6 -880,9 +885,9 @@@ static void net_action_suspend(surf_act
    lmm_update_variable_weight(network_maxmin_system,
                               ((surf_action_network_CM02_t)
                                action)->variable, 0.0);
+   if(network_update_mechanism == UM_LAZY)// remove action from the heap
+     heap_remove((surf_action_network_CM02_t) action);
  }
  
  static void net_action_resume(surf_action_t action)
                                 ((surf_action_network_CM02_t)
                                  action)->weight);
      ((surf_action_network_CM02_t) action)->suspended = 0;
+     if(network_update_mechanism == UM_LAZY)// remove action from the heap
+       heap_remove((surf_action_network_CM02_t) action);
    }
  }
  
@@@ -810,6 -907,8 +912,8 @@@ static int net_action_is_suspended(surf
  void net_action_set_max_duration(surf_action_t action, double duration)
  {
    action->max_duration = duration;
+   if(network_update_mechanism == UM_LAZY)// remove action from the heap
+     heap_remove((surf_action_network_CM02_t) action);
  }
  
  #ifdef HAVE_TRACING
@@@ -824,14 -923,68 +928,68 @@@ static void net_finalize(void
    surf_model_exit(surf_network_model);
    surf_network_model = NULL;
  
-   global_routing->finalize();
    lmm_system_free(network_maxmin_system);
    network_maxmin_system = NULL;
+   if(network_update_mechanism == UM_LAZY){
+     xbt_heap_free(net_action_heap);
+     xbt_swag_free(net_modified_set);
+   }
+ }
+ static void smpi_gap_append(double size, const link_CM02_t link, surf_action_network_CM02_t action) {
+    const char* src = link->lmm_resource.generic_resource.name;
+    xbt_fifo_t fifo;
+    surf_action_network_CM02_t last_action;
+    double bw;
+    if(sg_sender_gap > 0.0) {
+       if(!gap_lookup) {
+          gap_lookup = xbt_dict_new();
+       }
+       fifo = (xbt_fifo_t)xbt_dict_get_or_null(gap_lookup, src);
+       action->sender.gap = 0.0;
+       if(fifo && xbt_fifo_size(fifo) > 0) {
+          /* Compute gap from last send */
+          last_action = (surf_action_network_CM02_t)xbt_fifo_get_item_content(xbt_fifo_get_last_item(fifo));
+          bw = net_get_link_bandwidth(link);
+          action->sender.gap = last_action->sender.gap + max(sg_sender_gap, last_action->sender.size / bw);
+          action->latency += action->sender.gap;
+       }
+       /* Append action as last send */
+       action->sender.link_name = link->lmm_resource.generic_resource.name;
+       fifo = (xbt_fifo_t)xbt_dict_get_or_null(gap_lookup, action->sender.link_name);
+       if(!fifo) {
+          fifo = xbt_fifo_new();
+          xbt_dict_set(gap_lookup, action->sender.link_name, fifo, NULL);
+       }
+       action->sender.fifo_item = xbt_fifo_push(fifo, action);
+       action->sender.size = size;
+    }
+ }
+ static void smpi_gap_remove(surf_action_network_CM02_t action) {
+    xbt_fifo_t fifo;
+    size_t size;
+    if(sg_sender_gap > 0.0 && action->sender.link_name && action->sender.fifo_item) {
+       fifo = (xbt_fifo_t)xbt_dict_get_or_null(gap_lookup, action->sender.link_name);
+       xbt_fifo_remove_item(fifo, action->sender.fifo_item);
+       size = xbt_fifo_size(fifo);
+       if(size == 0) {
+          xbt_fifo_free(fifo);
+          xbt_dict_remove(gap_lookup, action->sender.link_name);
+          size = xbt_dict_length(gap_lookup);
+          if(size == 0) {
+             xbt_dict_free(&gap_lookup);
+          }
+       }
+    }
  }
  
  static void surf_network_model_init_internal(void)
  {
+   s_surf_action_network_CM02_t comm;
    surf_network_model = surf_model_init();
  
    surf_network_model->name = "network";
  #endif
  
    surf_network_model->model_private->resource_used = net_resource_used;
-   surf_network_model->model_private->share_resources = net_share_resources;
-   surf_network_model->model_private->update_actions_state =
-       net_update_actions_state;
+   if(network_update_mechanism == UM_LAZY) {
+     surf_network_model->model_private->share_resources = net_share_resources_lazy;
+     surf_network_model->model_private->update_actions_state = net_update_actions_state_lazy;
+   } else if(network_update_mechanism == UM_FULL) {
+     surf_network_model->model_private->share_resources = net_share_resources_full;
+     surf_network_model->model_private->update_actions_state = net_update_actions_state_full;
+   }
    surf_network_model->model_private->update_resource_state =
-       net_update_resource_state;
+                 net_update_resource_state;
    surf_network_model->model_private->finalize = net_finalize;
  
    surf_network_model->suspend = net_action_suspend;
    surf_network_model->resume = net_action_resume;
    surf_network_model->is_suspended = net_action_is_suspended;
-   surf_network_model->set_max_duration = net_action_set_max_duration;
- #ifdef HAVE_TRACING
-   surf_network_model->set_category = net_action_set_category;
- #endif
+   surf_cpu_model->set_max_duration = net_action_set_max_duration;
  
    surf_network_model->extension.network.communicate = net_communicate;
    surf_network_model->extension.network.get_route = net_get_route;
    surf_network_model->extension.network.get_link_bandwidth =
-       net_get_link_bandwidth;
+                 net_get_link_bandwidth;
    surf_network_model->extension.network.get_link_latency =
-       net_get_link_latency;
+                 net_get_link_latency;
    surf_network_model->extension.network.link_shared = net_link_shared;
    surf_network_model->extension.network.add_traces = net_add_traces;
    surf_network_model->extension.network.create_resource =
-       net_create_resource;
-   if (!network_maxmin_system)
-     network_maxmin_system = lmm_system_new();
-   routing_model_create(sizeof(link_CM02_t),
-                        net_link_new(xbt_strdup("__loopback__"),
-                                     498000000, NULL, 0.000015, NULL,
-                                     SURF_RESOURCE_ON, NULL,
-                                     SURF_LINK_FATPIPE, NULL),
-                      net_get_link_latency);
+                 net_create_resource;
+  if (!network_maxmin_system)
+     network_maxmin_system = lmm_system_new(selective_update);
+  routing_model_create(sizeof(link_CM02_t),
+       net_create_resource("__loopback__",
+           498000000, NULL, 0.000015, NULL,
+           SURF_RESOURCE_ON, NULL,
+           SURF_LINK_FATPIPE, NULL));
+   if(network_update_mechanism == UM_LAZY){
+     net_action_heap = xbt_heap_new(8,NULL);
+     xbt_heap_set_update_callback(net_action_heap, net_action_update_index_heap);
+     net_modified_set =
+         xbt_swag_new(xbt_swag_offset(comm, action_list_hookup));
+   }
  }
  
+ static void set_update_mechanism(void) {
+   char *optim = xbt_cfg_get_string(_surf_cfg_set, "network/optim");
+   int select = xbt_cfg_get_int(_surf_cfg_set, "network/maxmin_selective_update");
+   if(!strcmp(optim,"Full")) {
+     network_update_mechanism = UM_FULL;
+     selective_update = select;
+   } else if (!strcmp(optim,"Lazy")) {
+     network_update_mechanism = UM_LAZY;
+     selective_update = 1;
+     xbt_assert((select==1) || (xbt_cfg_is_default_value(_surf_cfg_set,"network/maxmin_selective_update")),
+         "Disabling selective update while using the lazy update mechanism is dumb!");
+   } else {
+     xbt_die("Unsupported optimization (%s) for this model",optim);
+   }
+ }
  
  /************************************************************************/
  /* New model based on LV08 and experimental results of MPI ping-pongs   */
  /************************************************************************/
- void surf_network_model_init_SMPI(const char *filename)
+ /* @Inproceedings{smpi_ipdps, */
+ /*  author={Pierre-Nicolas Clauss and Mark Stillwell and Stéphane Genaud and Frédéric Suter and Henri Casanova and Martin Quinson}, */
+ /*  title={Single Node On-Line Simulation of {MPI} Applications with SMPI}, */
+ /*  booktitle={25th IEEE International Parallel and Distributed Processing Symposium (IPDPS'11)}, */
+ /*  address={Anchorage (Alaska) USA}, */
+ /*  month=may, */
+ /*  year={2011} */
+ /*  } */
+ void surf_network_model_init_SMPI(void)
  {
  
    if (surf_network_model)
      return;
+   set_update_mechanism();
    surf_network_model_init_internal();
    latency_factor_callback = &smpi_latency_factor;
    bandwidth_factor_callback = &smpi_bandwidth_factor;
    bandwidth_constraint_callback = &smpi_bandwidth_constraint;
-   net_define_callbacks(filename);
+   gap_append = &smpi_gap_append;
+   gap_remove = &smpi_gap_remove;
+   net_define_callbacks();
    xbt_dynar_push(model_list, &surf_network_model);
    network_solve = lmm_solve;
  
    xbt_cfg_setdefault_double(_surf_cfg_set, "network/sender_gap", 10e-6);
    xbt_cfg_setdefault_double(_surf_cfg_set, "network/weight_S", 8775);
-   update_model_description(surf_network_model_description,
-                            "SMPI", surf_network_model);
  }
  
  /************************************************************************/
- /* New model based on optimizations discussed during this thesis        */
+ /* New model based on optimizations discussed during Pedro Velho's thesis*/
  /************************************************************************/
- void surf_network_model_init_LegrandVelho(const char *filename)
+ /* @techreport{VELHO:2011:HAL-00646896:1, */
+ /*      url = {http://hal.inria.fr/hal-00646896/en/}, */
+ /*      title = {{Flow-level network models: have we reached the limits?}}, */
+ /*      author = {Velho, Pedro and Schnorr, Lucas and Casanova, Henri and Legrand, Arnaud}, */
+ /*      type = {Rapport de recherche}, */
+ /*      institution = {INRIA}, */
+ /*      number = {RR-7821}, */
+ /*      year = {2011}, */
+ /*      month = Nov, */
+ /*      pdf = {http://hal.inria.fr/hal-00646896/PDF/rr-validity.pdf}, */
+ /*  } */
+ void surf_network_model_init_LegrandVelho(void)
  {
    if (surf_network_model)
      return;
+   set_update_mechanism();
    surf_network_model_init_internal();
-   net_define_callbacks(filename);
+   net_define_callbacks();
    xbt_dynar_push(model_list, &surf_network_model);
    network_solve = lmm_solve;
  
-   xbt_cfg_setdefault_double(_surf_cfg_set, "network/latency_factor", 10.4);
-   xbt_cfg_setdefault_double(_surf_cfg_set, "network/bandwidth_factor",
-                             0.92);
-   xbt_cfg_setdefault_double(_surf_cfg_set, "network/weight_S", 8775);
-   update_model_description(surf_network_model_description,
-                            "LV08", surf_network_model);
+   xbt_cfg_setdefault_double(_surf_cfg_set, "network/latency_factor", 10.4); // 13.01 when callibration is done without phase effects
+   xbt_cfg_setdefault_double(_surf_cfg_set, "network/bandwidth_factor",0.92);// 0.97 when callibration is done without phase effects
+   xbt_cfg_setdefault_double(_surf_cfg_set, "network/weight_S", 8775);       // 20537 when callibration is done without phase effects
  }
  
  /***************************************************************************/
  /*   month         = {oct}, */
  /*   year          = {2002} */
  /* } */
- void surf_network_model_init_CM02(const char *filename)
+ void surf_network_model_init_CM02(void)
  {
  
    if (surf_network_model)
      return;
+   set_update_mechanism();
    surf_network_model_init_internal();
-   net_define_callbacks(filename);
+   net_define_callbacks();
    xbt_dynar_push(model_list, &surf_network_model);
    network_solve = lmm_solve;
  
-   update_model_description(surf_network_model_description,
-                            "CM02", surf_network_model);
+   xbt_cfg_setdefault_double(_surf_cfg_set, "network/latency_factor", 1.0);
+   xbt_cfg_setdefault_double(_surf_cfg_set, "network/bandwidth_factor", 1.0);
+   xbt_cfg_setdefault_double(_surf_cfg_set, "network/weight_S", 0.0);
  }
  
- void surf_network_model_init_Reno(const char *filename)
+ /***************************************************************************/
+ /* The models from Steven H. Low                                           */
+ /***************************************************************************/
+ /* @article{Low03,                                                         */
+ /*   author={Steven H. Low},                                               */
+ /*   title={A Duality Model of {TCP} and Queue Management Algorithms},     */
+ /*   year={2003},                                                          */
+ /*   journal={{IEEE/ACM} Transactions on Networking},                      */
+ /*    volume={11}, number={4},                                             */
+ /*  }                                                                      */
+ void surf_network_model_init_Reno(void)
  {
    if (surf_network_model)
      return;
+   set_update_mechanism();
    surf_network_model_init_internal();
-   net_define_callbacks(filename);
+   net_define_callbacks();
  
    xbt_dynar_push(model_list, &surf_network_model);
    lmm_set_default_protocol_function(func_reno_f, func_reno_fp,
    xbt_cfg_setdefault_double(_surf_cfg_set, "network/bandwidth_factor",
                              0.92);
    xbt_cfg_setdefault_double(_surf_cfg_set, "network/weight_S", 8775);
-   update_model_description(surf_network_model_description,
-                            "Reno", surf_network_model);
  }
  
  
- void surf_network_model_init_Reno2(const char *filename)
+ void surf_network_model_init_Reno2(void)
  {
    if (surf_network_model)
      return;
+   set_update_mechanism();
    surf_network_model_init_internal();
-   net_define_callbacks(filename);
+   net_define_callbacks();
  
    xbt_dynar_push(model_list, &surf_network_model);
    lmm_set_default_protocol_function(func_reno2_f, func_reno2_fp,
                              0.92);
    xbt_cfg_setdefault_double(_surf_cfg_set, "network/weight_S_parameter",
                              8775);
-   update_model_description(surf_network_model_description,
-                            "Reno2", surf_network_model);
  }
  
- void surf_network_model_init_Vegas(const char *filename)
+ void surf_network_model_init_Vegas(void)
  {
    if (surf_network_model)
      return;
+   set_update_mechanism();
    surf_network_model_init_internal();
-   net_define_callbacks(filename);
+   net_define_callbacks();
  
    xbt_dynar_push(model_list, &surf_network_model);
    lmm_set_default_protocol_function(func_vegas_f, func_vegas_fp,
    xbt_cfg_setdefault_double(_surf_cfg_set, "network/bandwidth_factor",
                              0.92);
    xbt_cfg_setdefault_double(_surf_cfg_set, "network/weight_S", 8775);
-   update_model_description(surf_network_model_description,
-                            "Vegas", surf_network_model);
  }