Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' of scm.gforge.inria.fr:/gitroot/simgrid/simgrid
authorMartin Quinson <martin.quinson@loria.fr>
Tue, 14 Jun 2016 19:33:40 +0000 (21:33 +0200)
committerMartin Quinson <martin.quinson@loria.fr>
Tue, 14 Jun 2016 19:33:40 +0000 (21:33 +0200)
13 files changed:
ChangeLog
include/simgrid/simix.h
include/xbt/synchro_core.h
src/mc/mc_base.cpp
src/mc/mc_request.cpp
src/simix/smx_global.cpp
src/simix/smx_network.cpp
src/simix/smx_process_private.h
src/simix/smx_synchro.cpp
src/simix/smx_synchro_private.h
src/smpi/smpi_base.cpp
src/smpi/smpirun.in
teshsuite/xbt/heap_bench/heap_bench.c

index 86e9353..5d6e12c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -6,6 +6,11 @@ SimGrid (3.14) UNRELEASED; urgency=low
    your trace files and slow down or speed up the simulation between two 
    consecutive calls by using an adjustment file. (See the documentation.)
 
+ * Fixed computation of timings for MPI_Send, MPI_Recv but possibly also others
+   We've found a bug that prevented SMPI to account for MPI_Send, MPI_Recv
+   and others (in some cases) in a correct way. That is, the smpi/os, smpi/or
+   values were ignored in some cases. The timings of these functions can now
+   be significantly different.
 
  -- $date Da SimGrid team <simgrid-devel@lists.gforge.inria.fr>
 
index bc07ffe..065bf3b 100644 (file)
@@ -32,24 +32,26 @@ namespace simix {
   class Process;
   class Context;
   class ContextFactory;
-
+  class Mutex;
 }
 }
 
 typedef simgrid::simix::Context *smx_context_t;
 typedef simgrid::simix::Process *smx_process_t;
 
+/**
+ * \ingroup simix_synchro_management
+ */
+typedef simgrid::simix::Mutex   *smx_mutex_t;
+
 #else
 
 typedef struct s_smx_context *smx_context_t;
 typedef struct s_smx_process *smx_process_t;
+typedef struct s_smx_mutex   *smx_mutex_t;
 
 #endif
 
-
-
-SG_BEGIN_DECL()
-
 /**************************** Scalar Values **********************************/
 
 typedef union u_smx_scalar u_smx_scalar_t;
@@ -83,10 +85,7 @@ typedef enum {
 /** @} */
 
 /* ******************************** Synchro ************************************ */
-/**
- * \ingroup simix_synchro_management
- */
-typedef struct s_smx_mutex *smx_mutex_t;
+
 /**
  * \ingroup simix_synchro_management
  */
@@ -127,6 +126,8 @@ extern int smx_context_stack_size_was_set;
 extern int smx_context_guard_size;
 extern int smx_context_guard_size_was_set;
 
+SG_BEGIN_DECL()
+
 XBT_PUBLIC(xbt_dynar_t) SIMIX_process_get_runnable(void);
 XBT_PUBLIC(smx_process_t) SIMIX_process_from_PID(int PID);
 XBT_PUBLIC(xbt_dynar_t) SIMIX_processes_as_dynar(void);
@@ -374,6 +375,7 @@ XBT_PUBLIC(void) simcall_set_category(smx_synchro_t synchro, const char *categor
 /************************** Synchro simcalls **********************************/
 XBT_PUBLIC(smx_mutex_t) simcall_mutex_init(void);
 XBT_PUBLIC(void) SIMIX_mutex_destroy(smx_mutex_t mutex);
+XBT_PUBLIC(smx_mutex_t) SIMIX_mutex_dup(smx_mutex_t mutex);
 XBT_PUBLIC(void) simcall_mutex_lock(smx_mutex_t mutex);
 XBT_PUBLIC(int) simcall_mutex_trylock(smx_mutex_t mutex);
 XBT_PUBLIC(void) simcall_mutex_unlock(smx_mutex_t mutex);
index 50684ed..b859f17 100644 (file)
@@ -13,6 +13,8 @@
 #ifndef _XBT_THREAD_H
 #define _XBT_THREAD_H
 
+#include <simgrid/simix.h>
+
 #include "xbt/misc.h"           /* SG_BEGIN_DECL */
 #include "xbt/function_types.h"
 
index df068fa..7c350f7 100644 (file)
@@ -162,10 +162,10 @@ bool request_is_enabled(smx_simcall_t req)
   case SIMCALL_MUTEX_LOCK: {
     smx_mutex_t mutex = simcall_mutex_lock__get__mutex(req);
 #if HAVE_MC
-    s_smx_mutex_t temp_mutex;
+    simgrid::mc::Remote<simgrid::simix::Mutex> temp_mutex;
     if (mc_model_checker != nullptr) {
-      mc_model_checker->process().read(&temp_mutex, remote(mutex));
-      mutex = &temp_mutex;
+      mc_model_checker->process().read(temp_mutex.getBuffer(), remote(mutex));
+      mutex = temp_mutex.getBuffer();
     }
 #endif
 
index d89c89d..cf8a8bf 100644 (file)
@@ -387,8 +387,8 @@ std::string simgrid::mc::request_to_string(smx_simcall_t req, int value, simgrid
     else
       type = "Mutex TRYLOCK";
 
-    s_smx_mutex_t mutex;
-    mc_model_checker->process().read_bytes(&mutex, sizeof(mutex),
+    simgrid::mc::Remote<simgrid::simix::Mutex> mutex;
+    mc_model_checker->process().read_bytes(mutex.getBuffer(), sizeof(mutex),
       remote(
         req->call == SIMCALL_MUTEX_LOCK
         ? simcall_mutex_lock__get__mutex(req)
@@ -396,12 +396,12 @@ std::string simgrid::mc::request_to_string(smx_simcall_t req, int value, simgrid
       ));
     s_xbt_swag_t mutex_sleeping;
     mc_model_checker->process().read_bytes(&mutex_sleeping, sizeof(mutex_sleeping),
-      remote(mutex.sleeping));
+      remote(mutex.getBuffer()->sleeping));
 
     args = bprintf("locked = %d, owner = %d, sleeping = %d",
-      mutex.locked,
-      mutex.owner != nullptr ? (int) mc_model_checker->process().resolveProcess(
-        simgrid::mc::remote(mutex.owner))->pid : -1,
+      mutex.getBuffer()->locked,
+      mutex.getBuffer()->owner != nullptr ? (int) mc_model_checker->process().resolveProcess(
+        simgrid::mc::remote(mutex.getBuffer()->owner))->pid : -1,
       mutex_sleeping.count);
     break;
   }
index e242207..7643bdd 100644 (file)
@@ -264,6 +264,18 @@ int smx_cleaned = 0;
 void SIMIX_clean(void)
 {
   if (smx_cleaned) return; // to avoid double cleaning by java and C
+
+#if HAVE_SMPI
+  if (SIMIX_process_count()>0){
+    if(smpi_process_initialized()){
+      xbt_die("Process exited without calling MPI_Finalize - Killing simulation");
+    }else{
+      XBT_WARN("Process called exit when leaving - Skipping cleanups");
+      return;
+    }
+  }
+#endif
+
   smx_cleaned = 1;
   XBT_DEBUG("SIMIX_clean called. Simulation's over.");
   if (!xbt_dynar_is_empty(simix_global->process_to_run) && SIMIX_get_clock() == 0.0) {
index 266b0cd..7da114e 100644 (file)
@@ -455,6 +455,8 @@ void simcall_HANDLER_comm_testany(smx_simcall_t simcall, xbt_dynar_t synchros)
 {
   unsigned int cursor;
   smx_synchro_t synchro;
+  // The default result is -1 -- this means, "nothing is ready".
+  // It can be changed below, but only if something matches.
   simcall_comm_testany__set__result(simcall, -1);
 
   if (MC_is_active() || MC_record_replay_is_active()){
index 87c9b10..0a81e9a 100644 (file)
@@ -29,45 +29,45 @@ class ProcessArg {
 public:
   std::string name;
   std::function<void()> code;
-  void *data = nullptr;
-  const char *hostname = nullptr;
-  double kill_time = 0.0;
-  xbt_dict_t properties  = nullptr;
-  bool auto_restart = false;
+  void *data            = nullptr;
+  const char *hostname  = nullptr;
+  double kill_time      = 0.0;
+  xbt_dict_t properties = nullptr;
+  bool auto_restart     = false;
 };
 
 class Process {
 public:
 
   // TODO, replace with boost intrusive container hooks
-  s_xbt_swag_hookup_t process_hookup = { nullptr, nullptr };   /* simix_global->process_list */
-  s_xbt_swag_hookup_t synchro_hookup = { nullptr, nullptr };   /* {mutex,cond,sem}->sleeping */
+  s_xbt_swag_hookup_t process_hookup   = { nullptr, nullptr };   /* simix_global->process_list */
+  s_xbt_swag_hookup_t synchro_hookup   = { nullptr, nullptr };   /* {mutex,cond,sem}->sleeping */
   s_xbt_swag_hookup_t host_proc_hookup = { nullptr, nullptr }; /* smx_host->process_lis */
-  s_xbt_swag_hookup_t destroy_hookup = { nullptr, nullptr };   /* simix_global->process_to_destroy */
+  s_xbt_swag_hookup_t destroy_hookup   = { nullptr, nullptr };   /* simix_global->process_to_destroy */
 
-  unsigned long pid = 0;
+  unsigned long pid  = 0;
   unsigned long ppid = 0;
   simgrid::xbt::string name;
-  sg_host_t host = nullptr;     /* the host on which the process is running */
+  sg_host_t host        = nullptr;     /* the host on which the process is running */
   smx_context_t context = nullptr; /* the context (uctx/raw/thread) that executes the user function */
 
   // TODO, pack them
   std::exception_ptr exception;
-  bool blocked = false;
-  bool suspended = false;
+  bool blocked      = false;
+  bool suspended    = false;
   bool auto_restart = false;
 
-  sg_host_t new_host = nullptr;     /* if not null, the host on which the process must migrate to */
+  sg_host_t new_host            = nullptr;     /* if not null, the host on which the process must migrate to */
   smx_synchro_t waiting_synchro = nullptr;  /* the current blocking synchro if any */
-  xbt_fifo_t comms = nullptr;       /* the current non-blocking communication synchros */
-  xbt_dict_t properties = nullptr;
+  xbt_fifo_t comms              = nullptr;       /* the current non-blocking communication synchros */
+  xbt_dict_t properties         = nullptr;
   s_smx_simcall_t simcall;
-  void *data = nullptr;    /* kept for compatibility, it should be replaced with moddata */
+  void *data          = nullptr;    /* kept for compatibility, it should be replaced with moddata */
   xbt_dynar_t on_exit = nullptr; /* list of functions executed when the process dies */
 
   std::function<void()> code;
   smx_timer_t kill_timer = nullptr;
-  int segment_index = 0;    /*Reference to an SMPI process' data segment. Default value is -1 if not in SMPI context*/
+  int segment_index      = 0;    /*Reference to an SMPI process' data segment. Default value is -1 if not in SMPI context*/
 };
 
 }
index 2797cb5..5a4d449 100644 (file)
@@ -1,3 +1,4 @@
+
 /* Copyright (c) 2007-2015. The SimGrid Team.
  * All rights reserved.                                                     */
 
@@ -93,130 +94,132 @@ void SIMIX_synchro_finish(smx_synchro_t synchro)
 }
 /*********************************** Mutex ************************************/
 
-smx_mutex_t simcall_HANDLER_mutex_init(smx_simcall_t simcall){
-  return SIMIX_mutex_init();
-}
-/**
- * \brief Initialize a mutex.
- *
- * Allocs and creates the data for the mutex.
- * \return A mutex
- */
-smx_mutex_t SIMIX_mutex_init(void)
+namespace simgrid {
+namespace simix {
+
+Mutex::Mutex()
 {
-  XBT_IN("()");
-  simgrid::simix::Process p;            /* useful to initialize sleeping swag */
+  XBT_IN("(%p)", this);
+  // Useful to initialize sleeping swag:
+  simgrid::simix::Process p;
+  this->sleeping = xbt_swag_new(xbt_swag_offset(p, synchro_hookup));
+  XBT_OUT();
+}
 
-  smx_mutex_t mutex = xbt_new0(s_smx_mutex_t, 1);
-  mutex->locked = 0;
-  mutex->sleeping = xbt_swag_new(xbt_swag_offset(p, synchro_hookup));
+Mutex::~Mutex()
+{
+  XBT_IN("(%p)", this);
+  xbt_swag_free(this->sleeping);
   XBT_OUT();
-  return mutex;
 }
 
-/**
- * \brief Handles a mutex lock simcall.
- * \param simcall the simcall
- */
-void simcall_HANDLER_mutex_lock(smx_simcall_t simcall, smx_mutex_t mutex)
+void Mutex::lock(smx_process_t issuer)
 {
-  XBT_IN("(%p)",simcall);
+  XBT_IN("(%p; %p)", this, issuer);
   /* FIXME: check where to validate the arguments */
   smx_synchro_t synchro = nullptr;
-  smx_process_t process = simcall->issuer;
 
-  if (mutex->locked) {
+  if (this->locked) {
     /* FIXME: check if the host is active ? */
     /* Somebody using the mutex, use a synchronization to get host failures */
-    synchro = SIMIX_synchro_wait(process->host, -1);
-    synchro->simcalls.push_back(simcall);
-    simcall->issuer->waiting_synchro = synchro;
-    xbt_swag_insert(simcall->issuer, mutex->sleeping);   
+    synchro = SIMIX_synchro_wait(issuer->host, -1);
+    synchro->simcalls.push_back(&issuer->simcall);
+    issuer->waiting_synchro = synchro;
+    xbt_swag_insert(issuer, this->sleeping);
   } else {
     /* mutex free */
-    mutex->locked = 1;
-    mutex->owner = simcall->issuer;
-    SIMIX_simcall_answer(simcall);
+    this->locked = true;
+    this->owner = issuer;
+    SIMIX_simcall_answer(&issuer->simcall);
   }
   XBT_OUT();
 }
 
-int simcall_HANDLER_mutex_trylock(smx_simcall_t simcall, smx_mutex_t mutex){
-  return SIMIX_mutex_trylock(mutex, simcall->issuer);
-}
-/**
- * \brief Tries to lock a mutex.
+/** Tries to lock the mutex for a process
  *
- * Tries to lock a mutex, return 1 if the mutex is unlocked, else 0.
- * This function does not block and wait for the mutex to be unlocked.
- * \param mutex The mutex
- * \param issuer The process that tries to acquire the mutex
- * \return 1 - mutex free, 0 - mutex used
+ * \param  issuer  the process that tries to acquire the mutex
+ * \return whether we managed to lock the mutex
  */
-int SIMIX_mutex_trylock(smx_mutex_t mutex, smx_process_t issuer)
+bool Mutex::try_lock(smx_process_t issuer)
 {
-  XBT_IN("(%p, %p)",mutex,issuer);
-  if (mutex->locked){
+  XBT_IN("(%p, %p)", this, issuer);
+  if (this->locked) {
     XBT_OUT();
-    return 0;
+    return false;
   }
 
-  mutex->locked = 1;
-  mutex->owner = issuer;
+  this->locked = true;
+  this->owner = issuer;
   XBT_OUT();
-  return 1;
+  return true;
 }
 
-void simcall_HANDLER_mutex_unlock(smx_simcall_t simcall, smx_mutex_t mutex){
-   SIMIX_mutex_unlock(mutex, simcall->issuer);
-}
-/**
- * \brief Unlocks a mutex.
+/** Unlock a mutex for a process
  *
  * Unlocks the mutex and gives it to a process waiting for it. 
  * If the unlocker is not the owner of the mutex nothing happens.
  * If there are no process waiting, it sets the mutex as free.
- * \param mutex The mutex
- * \param issuer The process trying to unlock the mutex
  */
-void SIMIX_mutex_unlock(smx_mutex_t mutex, smx_process_t issuer)
+void Mutex::unlock(smx_process_t issuer)
 {
-  XBT_IN("(%p, %p)",mutex,issuer);
+  XBT_IN("(%p, %p)", this, issuer);
 
   /* If the mutex is not owned by the issuer, that's not good */
-  if (issuer != mutex->owner)
+  if (issuer != this->owner)
     THROWF(mismatch_error, 0, "Cannot release that mutex: it was locked by %s (pid:%d), not by you.",
-        SIMIX_process_get_name(mutex->owner),SIMIX_process_get_PID(mutex->owner));
+        SIMIX_process_get_name(this->owner),SIMIX_process_get_PID(this->owner));
 
-  if (xbt_swag_size(mutex->sleeping) > 0) {
+  if (xbt_swag_size(this->sleeping) > 0) {
     /*process to wake up */
-    smx_process_t p = (smx_process_t) xbt_swag_extract(mutex->sleeping);
+    smx_process_t p = (smx_process_t) xbt_swag_extract(this->sleeping);
     delete p->waiting_synchro;
     p->waiting_synchro = nullptr;
-    mutex->owner = p;
+    this->owner = p;
     SIMIX_simcall_answer(&p->simcall);
   } else {
     /* nobody to wake up */
-    mutex->locked = 0;
-    mutex->owner = nullptr;
+    this->locked = false;
+    this->owner = nullptr;
   }
   XBT_OUT();
 }
 
-/**
- * \brief Destroys a mutex.
- *
- * Destroys and frees the mutex's memory. 
- * \param mutex A mutex
- */
+}
+}
+
 void SIMIX_mutex_destroy(smx_mutex_t mutex)
 {
-  XBT_IN("(%p)",mutex);
-  if (mutex){
-    xbt_swag_free(mutex->sleeping);
-    xbt_free(mutex);
-  }
-  XBT_OUT();
+  if (mutex != nullptr)
+    intrusive_ptr_release(mutex);
+}
+
+XBT_PUBLIC(smx_mutex_t) SIMIX_mutex_dup(smx_mutex_t mutex)
+{
+  if (mutex != nullptr)
+    intrusive_ptr_add_ref(mutex);
+  return mutex;
+}
+
+smx_mutex_t simcall_HANDLER_mutex_init(smx_simcall_t simcall)
+{
+  return new simgrid::simix::Mutex();
+}
+
+// Simcall handlers:
+
+void simcall_HANDLER_mutex_lock(smx_simcall_t simcall, smx_mutex_t mutex)
+{
+  mutex->lock(simcall->issuer);
+}
+
+int simcall_HANDLER_mutex_trylock(smx_simcall_t simcall, smx_mutex_t mutex)
+{
+  return mutex->try_lock(simcall->issuer);
+}
+
+void simcall_HANDLER_mutex_unlock(smx_simcall_t simcall, smx_mutex_t mutex)
+{
+  mutex->unlock(simcall->issuer);
 }
 
 /********************************* Condition **********************************/
@@ -279,7 +282,7 @@ static void _SIMIX_cond_wait(smx_cond_t cond, smx_mutex_t mutex, double timeout,
   /* FIXME: what happens if the issuer is not the owner of the mutex? */
   if (mutex != nullptr) {
     cond->mutex = mutex;
-    SIMIX_mutex_unlock(mutex, issuer);
+    mutex->unlock(issuer);
   }
 
   synchro = SIMIX_synchro_wait(issuer->host, timeout);
index c8ea1f6..802716a 100644 (file)
@@ -7,16 +7,51 @@
 #ifndef _SIMIX_SYNCHRO_PRIVATE_H
 #define _SIMIX_SYNCHRO_PRIVATE_H
 
+#include <atomic>
+
 #include "xbt/base.h"
 #include "xbt/swag.h"
 #include "xbt/xbt_os_thread.h"
 #include "src/simix/popping_private.h"
 
-typedef struct s_smx_mutex {
-  unsigned int locked;
-  smx_process_t owner;
-  xbt_swag_t sleeping;          /* list of sleeping process */
-} s_smx_mutex_t;
+namespace simgrid {
+namespace simix {
+
+class XBT_PUBLIC() Mutex {
+public:
+  Mutex();
+  ~Mutex();
+  Mutex(Mutex const&) = delete;
+  Mutex& operator=(Mutex const&) = delete;
+
+  void lock(smx_process_t issuer);
+  bool try_lock(smx_process_t issuer);
+  void unlock(smx_process_t issuer);
+
+  bool locked = false;
+  smx_process_t owner = nullptr;
+  // List of sleeping processes:
+  xbt_swag_t sleeping = nullptr;
+
+  // boost::intrusive_ptr<Mutex> support:
+  friend void intrusive_ptr_add_ref(Mutex* mutex)
+  {
+    auto previous = ++mutex->refcount_;
+    xbt_assert(previous != 0);
+    (void) previous;
+  }
+  friend void intrusive_ptr_release(Mutex* mutex)
+  {
+    auto count = mutex->refcount_--;
+    if (count == 0)
+      delete mutex;
+  }
+private:
+  std::atomic_int_fast32_t refcount_ { 1 };
+};
+
+}
+}
 
 typedef struct s_smx_cond {
   smx_mutex_t mutex;
@@ -33,10 +68,6 @@ XBT_PRIVATE void SIMIX_synchro_stop_waiting(smx_process_t process, smx_simcall_t
 XBT_PRIVATE void SIMIX_synchro_destroy(smx_synchro_t synchro);
 XBT_PRIVATE void SIMIX_synchro_finish(smx_synchro_t synchro);
 
-XBT_PRIVATE smx_mutex_t SIMIX_mutex_init(void);
-XBT_PRIVATE int SIMIX_mutex_trylock(smx_mutex_t mutex, smx_process_t issuer);
-XBT_PRIVATE void SIMIX_mutex_unlock(smx_mutex_t mutex, smx_process_t issuer);
-
 XBT_PRIVATE smx_cond_t SIMIX_cond_init(void);
 XBT_PRIVATE void SIMIX_cond_broadcast(smx_cond_t cond);
 XBT_PRIVATE void SIMIX_cond_signal(smx_cond_t cond);
index 679ab29..ccc85cd 100644 (file)
@@ -5,6 +5,8 @@
  * under the terms of the license (GNU LGPL) which comes with this package. */
 
 #include <xbt/config.hpp>
+#include <boost/tokenizer.hpp>
+#include <algorithm>
 
 #include "private.h"
 #include "xbt/virtu.h"
@@ -71,14 +73,13 @@ static int match_send(void* a, void* b,smx_synchro_t ignored) {
 // These are taken from surf/network.c and generalized to have more values for each factor
 typedef struct s_smpi_factor_multival *smpi_os_factor_multival_t;
 typedef struct s_smpi_factor_multival { // FIXME: this should be merged (deduplicated) with s_smpi_factor defined in network_smpi.c
-  long factor;
-  int nb_values;
-  double values[4];//arbitrary set to 4
+  long factor=0;
+  std::vector<double> values;
 } s_smpi_factor_multival_t;
 
-xbt_dynar_t smpi_os_values  = nullptr;
-xbt_dynar_t smpi_or_values  = nullptr;
-xbt_dynar_t smpi_ois_values = nullptr;
+std::vector<s_smpi_factor_multival_t> smpi_os_values;
+std::vector<s_smpi_factor_multival_t> smpi_or_values;
+std::vector<s_smpi_factor_multival_t> smpi_ois_values;
 
 static simgrid::config::Flag<double> smpi_wtime_sleep(
   "smpi/wtime", "Minimum time to inject inside a call to MPI_Wtime", 0.0);
@@ -89,67 +90,76 @@ static simgrid::config::Flag<double> smpi_iprobe_sleep(
 static simgrid::config::Flag<double> smpi_test_sleep(
   "smpi/test", "Minimum time to inject inside a call to MPI_Test", 1e-4);
 
-static int factor_cmp(const void *pa, const void *pb)
+static int factor_cmp(const s_smpi_factor_multival_t& pa, const s_smpi_factor_multival_t& pb)
 {
-  return ((static_cast<const s_smpi_factor_multival_t*>(pa))->factor > (static_cast<const s_smpi_factor_multival_t*>(pb))->factor) ? 1 :
-         ((static_cast<const s_smpi_factor_multival_t*>(pa))->factor < (static_cast<const s_smpi_factor_multival_t*>(pb))->factor) ? -1 : 0;
+  return (pa.factor > pb.factor) ? 1 :
+         (pa.factor < pb.factor) ? -1 : 0;
 }
 
-static xbt_dynar_t parse_factor(const char *smpi_coef_string)
+static std::vector<s_smpi_factor_multival_t> parse_factor(const char *smpi_coef_string)
 {
-  char *value = nullptr;
-  unsigned int iter = 0;
+  std::vector<s_smpi_factor_multival_t> smpi_factor;
   s_smpi_factor_multival_t fact;
-  fact.nb_values=0;
-  unsigned int i=0;
-  xbt_dynar_t radical_elements2 = nullptr;
-
-  xbt_dynar_t smpi_factor = xbt_dynar_new(sizeof(s_smpi_factor_multival_t), nullptr);
-  xbt_dynar_t radical_elements = xbt_str_split(smpi_coef_string, ";");
-  xbt_dynar_foreach(radical_elements, iter, value) {
-    memset(&fact, 0, sizeof(s_smpi_factor_multival_t));
-    radical_elements2 = xbt_str_split(value, ":");
-    if (xbt_dynar_length(radical_elements2) <2 || xbt_dynar_length(radical_elements2) > 5)
+
+  /** Setup the tokenizer that parses the string **/
+  typedef boost::tokenizer<boost::char_separator<char>> Tokenizer;
+  boost::char_separator<char> sep(";");
+  boost::char_separator<char> factor_separator(":");
+  std::string tmp_string(smpi_coef_string);
+  Tokenizer tokens(tmp_string, sep);
+
+  /** 
+   * Iterate over patterns like A:B:C:D;E:F;G:H
+   * These will be broken down into:
+   * A --> B, C, D
+   * E --> F
+   * G --> H
+   */
+  for (Tokenizer::iterator token_iter = tokens.begin();
+         token_iter != tokens.end(); token_iter++) {
+    Tokenizer factor_values(*token_iter, factor_separator);
+
+    if (factor_values.begin() == factor_values.end()) {
       xbt_die("Malformed radical for smpi factor: '%s'", smpi_coef_string);
-    for(i =0; i<xbt_dynar_length(radical_elements2);i++ ){
+    }
+    unsigned int iteration = 0;
+    for (Tokenizer::iterator factor_iter = factor_values.begin();
+         factor_iter != factor_values.end(); factor_iter++, iteration++) {
       char *errmsg;
-      if (i==0) {
-        errmsg = bprintf("Invalid factor in chunk #%d: %%s", iter+1);
-        fact.factor = xbt_str_parse_int(xbt_dynar_get_as(radical_elements2, i, char *), errmsg);
-      } else {
-        errmsg = bprintf("Invalid factor value %d in chunk #%d: %%s", i, iter+1);
-        fact.values[fact.nb_values] = xbt_str_parse_double(xbt_dynar_get_as(radical_elements2, i, char *), errmsg);
-        fact.nb_values++;
+
+      if (factor_iter == factor_values.begin()) { /* first element */
+        errmsg = bprintf("Invalid factor in chunk #%zu: %%s", smpi_factor.size()+1);
+        fact.factor = xbt_str_parse_int(factor_iter->c_str(), errmsg);
+      }
+      else {
+        errmsg = bprintf("Invalid factor value %d in chunk #%zu: %%s", iteration, smpi_factor.size()+1);
+        fact.values.push_back(xbt_str_parse_double((*factor_iter).c_str(), errmsg));
       }
       xbt_free(errmsg);
     }
 
-    xbt_dynar_push_as(smpi_factor, s_smpi_factor_multival_t, fact);
-    XBT_DEBUG("smpi_factor:\t%ld : %d values, first: %f", fact.factor, fact.nb_values ,fact.values[0]);
-    xbt_dynar_free(&radical_elements2);
+    smpi_factor.push_back(fact);
+    XBT_DEBUG("smpi_factor:\t%ld : %zu values, first: %f", fact.factor, smpi_factor.size(), fact.values[0]);
   }
-  xbt_dynar_free(&radical_elements);
-  xbt_dynar_sort(smpi_factor, &factor_cmp);
-  xbt_dynar_foreach(smpi_factor, iter, fact) {
-    XBT_DEBUG("smpi_factor:\t%ld : %d values, first: %f", fact.factor, fact.nb_values ,fact.values[0]);
+  std::sort(smpi_factor.begin(), smpi_factor.end(), &factor_cmp);
+  for (auto& fact : smpi_factor) {
+    XBT_DEBUG("smpi_factor:\t%ld : %zu values, first: %f", fact.factor, smpi_factor.size() ,fact.values[0]);
   }
+
   return smpi_factor;
 }
 
 static double smpi_os(double size)
 {
-  if (smpi_os_values == nullptr) {
+  if (smpi_os_values.empty()) {
     smpi_os_values = parse_factor(xbt_cfg_get_string("smpi/os"));
-    smpi_register_static(smpi_os_values, xbt_dynar_free_voidp);
   }
-  unsigned int iter = 0;
-  s_smpi_factor_multival_t fact;
   double current=0.0;
   // Iterate over all the sections that were specified and find the right
   // value. (fact.factor represents the interval sizes; we want to find the
   // section that has fact.factor <= size and no other such fact.factor <= size)
   // Note: parse_factor() (used before) already sorts the dynar we iterate over!
-  xbt_dynar_foreach(smpi_os_values, iter, fact) {
+  for (auto& fact : smpi_os_values) {
     if (size <= fact.factor) { // Values already too large, use the previously
                                // computed value of current!
         XBT_DEBUG("os : %f <= %ld return %f", size, fact.factor, current);
@@ -160,24 +170,21 @@ static double smpi_os(double size)
       current = fact.values[0]+fact.values[1]*size;
     }
   }
-  XBT_DEBUG("os : %f > %ld return %f", size, fact.factor, current);
+  XBT_DEBUG("Searching for smpi/os: %f is larger than the largest boundary, return %f", size, current);
 
   return current;
 }
 
 static double smpi_ois(double size)
 {
-  if (smpi_ois_values == nullptr) {
+  if (smpi_ois_values.empty()) {
     smpi_ois_values = parse_factor(xbt_cfg_get_string("smpi/ois"));
-    smpi_register_static(smpi_ois_values, xbt_dynar_free_voidp);
   }
-  unsigned int iter = 0;
-  s_smpi_factor_multival_t fact;
   double current=0.0;
   // Iterate over all the sections that were specified and find the right value. (fact.factor represents the interval
   // sizes; we want to find the section that has fact.factor <= size and no other such fact.factor <= size)
   // Note: parse_factor() (used before) already sorts the dynar we iterate over!
-  xbt_dynar_foreach(smpi_ois_values, iter, fact) {
+  for (auto& fact : smpi_ois_values) {
     if (size <= fact.factor) { // Values already too large, use the previously  computed value of current!
         XBT_DEBUG("ois : %f <= %ld return %f", size, fact.factor, current);
       return current;
@@ -187,24 +194,21 @@ static double smpi_ois(double size)
       current = fact.values[0]+fact.values[1]*size;
     }
   }
-  XBT_DEBUG("ois : %f > %ld return %f", size, fact.factor, current);
+  XBT_DEBUG("Searching for smpi/ois: %f is larger than the largest boundary, return %f", size, current);
 
   return current;
 }
 
 static double smpi_or(double size)
 {
-  if (smpi_or_values == nullptr) {
+  if (smpi_or_values.empty()) {
     smpi_or_values = parse_factor(xbt_cfg_get_string("smpi/or"));
-    smpi_register_static(smpi_or_values, xbt_dynar_free_voidp);
   }
-  unsigned int iter = 0;
-  s_smpi_factor_multival_t fact;
   double current=0.0;
   // Iterate over all the sections that were specified and find the right value. (fact.factor represents the interval
   // sizes; we want to find the section that has fact.factor <= size and no other such fact.factor <= size)
   // Note: parse_factor() (used before) already sorts the dynar we iterate over!
-  xbt_dynar_foreach(smpi_or_values, iter, fact) {
+  for (auto fact : smpi_or_values) {
     if (size <= fact.factor) { // Values already too large, use the previously
                                // computed value of current!
         XBT_DEBUG("or : %f <= %ld return %f", size, fact.factor, current);
@@ -215,7 +219,7 @@ static double smpi_or(double size)
       current=fact.values[0]+fact.values[1]*size;
     }
   }
-  XBT_DEBUG("or : %f > %ld return %f", size, fact.factor, current);
+  XBT_DEBUG("smpi_or: %f is larger than largest boundary, return %f", size, current);
 
   return current;
 }
@@ -771,44 +775,39 @@ int smpi_mpi_testany(int count, MPI_Request requests[], int *index, MPI_Status *
 {
   xbt_dynar_t comms;
   int i;
-  int* map;
   int flag = 0;
-  int size = 0;
 
   *index = MPI_UNDEFINED;
   comms = xbt_dynar_new(sizeof(smx_synchro_t), nullptr);
-  map = xbt_new(int, count);
+  std::vector<int> map; /** Maps all matching comms back to their location in requests **/
   for(i = 0; i < count; i++) {
     if ((requests[i] != MPI_REQUEST_NULL) && requests[i]->action && !(requests[i]->flags & PREPARED)) {
        xbt_dynar_push(comms, &requests[i]->action);
-       map[size] = i;
-       size++;
+       map.push_back(i);
     }
   }
-  if(size > 0) {
+  if(!map.empty()) {
     //multiplier to the sleeptime, to increase speed of execution, each failed testany will increase it
     static int nsleeps = 1;
     if(smpi_test_sleep > 0) 
       simcall_process_sleep(nsleeps*smpi_test_sleep);
 
-    i = simcall_comm_testany(comms);
-    // not MPI_UNDEFINED, as this is a simix return code
-    if(i != -1) {
-      *index = map[i];
+    i = simcall_comm_testany(comms); // The i-th element in comms matches!
+    if (i != -1) { // -1 is not MPI_UNDEFINED but a SIMIX return code. (nothing matches)
+      *index = map[i]; 
       finish_wait(&requests[*index], status);
-      if (requests[*index] != MPI_REQUEST_NULL && (requests[*index]->flags & NON_PERSISTENT))
-      requests[*index] = MPI_REQUEST_NULL;
-      flag = 1;
-      nsleeps=1;
-    }else{
+      flag             = 1;
+      nsleeps          = 1;
+      if (requests[*index] != MPI_REQUEST_NULL && (requests[*index]->flags & NON_PERSISTENT)) {
+        requests[*index] = MPI_REQUEST_NULL;
+      }
+    } else {
       nsleeps++;
     }
-  }else{
-      //all requests are null or inactive, return true
-      flag=1;
+  } else {
+      flag = 0; // all requests are null or inactive, return false
       smpi_empty_status(status);
   }
-  xbt_free(map);
   xbt_dynar_free(&comms);
 
   return flag;
index 8e07eaf..97fad0b 100755 (executable)
@@ -279,7 +279,7 @@ if [ -z "${HOSTFILE}" ] ; then
                  }
                }
              } elsif (/<cluster/) {
-               die ("Unparsable cluster tag. Either provide an hostfile yourself or give the attributes prefix, radical and suffix in that order on the <cluster line");
+            die ("Unparsable cluster tag. smpirun uses a primitive regular expression to parse cluster tags. Either provide a hostfile yourself or give the attributes prefix, radical and suffix IN THAT ORDER and ON THE SAME LINE as the opening tag (<cluster)");
              }' ${PLATFORM} >> ${HOSTFILE}
 fi
 UNROLLEDHOSTFILETMP=0
index cff04fe..3d2c542 100644 (file)
@@ -7,10 +7,11 @@
  * under the terms of the license (GNU LGPL) which comes with this package. */
 
 #include <stdio.h>
+#include <math.h>
 #include <xbt/xbt_os_time.h>
 
 #include "xbt/heap.h"
-#include "xbt/sysdep.h"         /* calloc, printf */
+#include "xbt/sysdep.h"
 
 #define MAX_TEST 1000000
 
@@ -21,9 +22,9 @@ static int compare_double(const void *a, const void *b)
 
   if (pa > pb)
     return 1;
-  if (pa == pb)
-    return 0;
-  return -1;
+  if (pa < pb)
+    return -1;
+  return 0;
 }
 
 static void test_reset_heap(xbt_heap_t * heap, int size)
@@ -50,8 +51,7 @@ static void test_heap_validity(int size)
   qsort(tab, size, sizeof(double), compare_double);
 
   for (i = 0; i < size; i++) {
-    /*     printf("%g" " ", xbt_heap_maxkey(heap)); */
-    if (xbt_heap_maxkey(heap) != tab[i]) {
+    if (fabs(xbt_heap_maxkey(heap) - tab[i]) > 1e-9) {
       fprintf(stderr, "Problem !\n");
       exit(1);
     }