Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' of git+ssh://scm.gforge.inria.fr/gitroot/simgrid/simgrid
authordegomme <augustin.degomme@unibas.ch>
Thu, 28 Jul 2016 10:01:38 +0000 (12:01 +0200)
committerdegomme <augustin.degomme@unibas.ch>
Thu, 28 Jul 2016 10:01:38 +0000 (12:01 +0200)
137 files changed:
.gitignore
TODO
doc/doxygen/FAQ.doc
doc/doxygen/community_giveback.doc
doc/doxygen/module-smpi.doc
doc/doxygen/module-xbt.doc
doc/doxygen/options.doc
doc/doxygen/uhood.doc
examples/java/app/bittorrent/Main.java
examples/msg/io-file/io-file.tesh
examples/platforms/storage/content/storage_content.txt
examples/s4u/actions-comm/s4u_actions-comm.cpp
examples/s4u/basic/s4u_basic.cpp
examples/s4u/basic/s4u_basic.h
examples/s4u/basic/s4u_basic_deployment.cpp
examples/s4u/basic/s4u_basic_function.cpp
examples/s4u/io/s4u_io.cpp
examples/s4u/mutex/s4u_mutex.cpp
examples/simdag/dag-dotload/sd_dag-dotload.tesh
examples/simdag/daxload/sd_daxload.tesh
examples/simdag/ptg-dotload/sd_ptg-dotload.tesh
examples/simdag/schedule-dotload/sd_schedule-dotload.tesh
examples/simdag/scheduling/sd_scheduling.c
examples/smpi/CMakeLists.txt
examples/smpi/bcbench/bcbench.c [deleted file]
examples/smpi/mvmul/mvmul.c [deleted file]
include/simgrid/chrono.hpp [new file with mode: 0644]
include/simgrid/msg.h
include/simgrid/s4u.hpp [moved from include/simgrid/s4u.h with 95% similarity]
include/simgrid/s4u/Activity.hpp
include/simgrid/s4u/Actor.hpp [moved from include/simgrid/s4u/actor.hpp with 91% similarity]
include/simgrid/s4u/comm.hpp
include/simgrid/s4u/conditionVariable.hpp
include/simgrid/s4u/mailbox.hpp
include/simgrid/simdag.h
include/simgrid/simix.h
include/xbt/dict.h
include/xbt/dynar.h
include/xbt/fifo.h
include/xbt/heap.h
include/xbt/log.h
include/xbt/log.hpp
include/xbt/swag.h
sonar-project.properties
src/bindings/java/jmsg_rngstream.cpp
src/instr/instr_config.cpp
src/instr/instr_paje_trace.cpp
src/mc/AddressSpace.hpp
src/mc/Channel.hpp
src/mc/Checker.hpp
src/mc/ChunkedData.hpp
src/mc/DwarfExpression.hpp
src/mc/Frame.cpp
src/mc/LocationList.hpp
src/mc/ModelChecker.cpp
src/mc/ObjectInformation.cpp
src/mc/ObjectInformation.hpp
src/mc/RemotePtr.hpp
src/mc/Session.cpp
src/mc/Session.hpp
src/mc/mc_dwarf.cpp
src/mc/mc_record.h
src/mc/mc_replay.h
src/mc/mc_request.cpp
src/mc/mc_state.cpp
src/msg/msg_gos.cpp
src/msg/msg_io.cpp
src/msg/msg_mailbox.cpp
src/msg/msg_synchro.cpp
src/msg/msg_task.cpp
src/msg/msg_vm.cpp
src/routing/AsCluster.cpp [moved from src/surf/AsCluster.cpp with 99% similarity]
src/routing/AsCluster.hpp [moved from src/surf/AsCluster.hpp with 97% similarity]
src/routing/AsClusterDragonfly.cpp [moved from src/surf/AsClusterDragonfly.cpp with 83% similarity]
src/routing/AsClusterDragonfly.hpp [moved from src/surf/AsClusterDragonfly.hpp with 98% similarity]
src/routing/AsClusterFatTree.cpp [moved from src/surf/AsClusterFatTree.cpp with 99% similarity]
src/routing/AsClusterFatTree.hpp [moved from src/surf/AsClusterFatTree.hpp with 99% similarity]
src/routing/AsClusterTorus.cpp [moved from src/surf/AsClusterTorus.cpp with 99% similarity]
src/routing/AsClusterTorus.hpp [moved from src/surf/AsClusterTorus.hpp with 96% similarity]
src/routing/AsDijkstra.cpp [moved from src/surf/AsDijkstra.cpp with 99% similarity]
src/routing/AsDijkstra.hpp [moved from src/surf/AsDijkstra.hpp with 98% similarity]
src/routing/AsFloyd.cpp [moved from src/surf/AsFloyd.cpp with 93% similarity]
src/routing/AsFloyd.hpp [moved from src/surf/AsFloyd.hpp with 95% similarity]
src/routing/AsFull.cpp [moved from src/surf/AsFull.cpp with 99% similarity]
src/routing/AsFull.hpp [moved from src/surf/AsFull.hpp with 95% similarity]
src/routing/AsImpl.cpp [moved from src/surf/AsImpl.cpp with 99% similarity]
src/routing/AsImpl.hpp [moved from src/surf/AsImpl.hpp with 100% similarity]
src/routing/AsNone.cpp [moved from src/surf/AsNone.cpp with 95% similarity]
src/routing/AsNone.hpp [moved from src/surf/AsNone.hpp with 95% similarity]
src/routing/AsRoutedGraph.cpp [moved from src/surf/AsRoutedGraph.cpp with 99% similarity]
src/routing/AsRoutedGraph.hpp [moved from src/surf/AsRoutedGraph.hpp with 96% similarity]
src/routing/AsVivaldi.cpp [moved from src/surf/AsVivaldi.cpp with 98% similarity]
src/routing/AsVivaldi.hpp [moved from src/surf/AsVivaldi.hpp with 95% similarity]
src/s4u/s4u_actor.cpp
src/s4u/s4u_comm.cpp
src/s4u/s4u_conditionVariable.cpp
src/s4u/s4u_file.cpp
src/s4u/s4u_mailbox.cpp
src/simdag/sd_daxloader.cpp
src/simdag/sd_dotloader.cpp
src/simdag/sd_global.cpp
src/simdag/sd_task.cpp
src/simdag/sd_workstation.cpp
src/simdag/simdag_private.h
src/simgrid/sg_config.cpp
src/simix/libsmx.cpp
src/simix/popping_accessors.h
src/simix/popping_bodies.cpp
src/simix/popping_generated.cpp
src/simix/popping_private.h
src/simix/simcalls.in
src/simix/smx_global.cpp
src/simix/smx_network.cpp
src/simix/smx_network_private.h
src/simix/smx_process_private.h
src/simix/smx_vm.cpp
src/smpi/smpi_base.cpp
src/surf/HostImpl.cpp
src/surf/HostImpl.hpp
src/surf/instr_routing.cpp
src/surf/lagrange.cpp
src/surf/plugins/energy.cpp
src/surf/sg_platf.cpp
src/surf/surf_routing.cpp
src/surf/surf_routing.hpp
src/xbt/exception.cpp
src/xbt/fifo.c
src/xbt/xbt_main.c
teshsuite/simdag/basic3/basic3.tesh
teshsuite/simdag/basic4/basic4.tesh
teshsuite/surf/lmm_usage/lmm_usage.cpp
teshsuite/surf/surf_usage2/surf_usage2.cpp
tools/cmake/DefinePackages.cmake
tools/internal/check_dist_archive.exclude
tools/internal/spell_comments.pl
tools/internal/travis-sonarqube.sh
tools/tesh/tesh.pl

index 7fe508f..98812d8 100644 (file)
@@ -199,7 +199,6 @@ examples/simdag/throttling/sd_throttling
 examples/simdag/fail/sd_fail
 examples/simdag/test/sd_test
 examples/simdag/typed_tasks/sd_typed_tasks
-examples/smpi/bcbench/smpi_bcbench
 examples/smpi/energy/f77/sef
 examples/smpi/energy/f90/sef90
 examples/smpi/energy/smpi_energy
@@ -214,7 +213,6 @@ examples/smpi/mc/send_deterministic
 examples/smpi/NAS/dt
 examples/smpi/NAS/ep
 examples/smpi/NAS/is
-examples/smpi/mvmul/smpi_mvmul
 examples/smpi/replay_multiple/replay_multiple
 examples/smpi/replay/one_trace
 examples/smpi/ring_c
@@ -284,6 +282,7 @@ teshsuite/smpi/coll-bcast/coll-bcast
 teshsuite/smpi/coll-barrier/coll-barrier
 teshsuite/smpi/coll-gather/coll-gather
 teshsuite/smpi/macro-sample/macro-sample
+teshsuite/smpi/timers/timers
 teshsuite/smpi/type-hvector/type-hvector
 teshsuite/smpi/type-indexed/type-indexed
 teshsuite/smpi/isp/umpire/abort
diff --git a/TODO b/TODO
index fbcc497..cbe2792 100644 (file)
--- a/TODO
+++ b/TODO
@@ -25,6 +25,6 @@
 
 * Replace XBT with the C++ standard library
 
-* Some XBT datacontainers seem to overlap. Kill some of them all.
+* Some XBT datacontainers seem to overlap. Kill some/all of them.
     - replace fifo with dynars
     - replace set with SWAG
index 2a8a74d..c5d64e9 100644 (file)
@@ -531,22 +531,6 @@ Both options are needed in order to run the SMPI process under GDB.
 If you don't, you really should use valgrind to debug your code, it's
 almost magic.
 
-\subsubsection faq_trouble_vg_longjmp longjmp madness in valgrind
-
-This is when valgrind starts complaining about longjmp things, just like:
-
-\verbatim ==21434== Conditional jump or move depends on uninitialised value(s)
-==21434==    at 0x420DBE5: longjmp (longjmp.c:33)
-==21434==
-==21434== Use of uninitialised value of size 4
-==21434==    at 0x420DC3A: __longjmp (__longjmp.S:48)
-\endverbatim
-
-This is the sign that you didn't used the exception mechanism well. Most
-probably, you have a <tt>return;</tt> somewhere within a <tt>TRY{}</tt>
-block. This is <b>evil</b>, and you must not do this. Did you read the section
-about \ref XBT_ex??
-
 \subsubsection faq_trouble_vg_libc Valgrind spits tons of errors about backtraces!
 
 It may happen that valgrind, the memory debugger beloved by any decent C
@@ -616,8 +600,6 @@ list. Just be aware that you'll be severely punished if the mistake is
 on your side... We have plenty of FAQ entries to redact and new
 features to implement for the impenitents! ;)
 
-Using 
-
 \subsection faq_surf_network_latency I get weird timings when I play with the latencies.
 
 OK, first of all, remember that units should be Bytes, Flops and
index a67ccae..cc428d0 100644 (file)
@@ -112,66 +112,234 @@ are easy, though):
 @subsection contributing_todo_cxxification Migration to C++
 
 The code is being migrated to C++ but a large part is still C (or C++ with
- idioms). It would be valuable to replace C idioms with C++ ones:
+C idioms). It would be valuable to replace C idioms with C++ ones:
 
- - replace XBT structures with C++ containers;
+ - replace XBT structures and C dynamic arrays with C++ containers;
 
- - replace `char*` with `std::string`;
+ - replace `char*` strings with `std::string`;
 
- - use RAII (`std::unique_ptr`, etc.) instead of explicit `malloc/free` or
-   `new/delete`.
+ - use exception-safe RAII (`std::unique_ptr`, etc.) instead of explicit
+   `malloc/free` or `new/delete`;
 
-@subsection contributing_todo_exceptions Migration to C++
+ - use `std::function` (or template functionoid arguments) instead of function
+   pointers;
+
+@subsubsection contributing_todo_exceptions Exceptions
 
 SimGrid used to implement exceptions in C. This has been replaced with C++
 exceptions but some bits of the C exceptions are still remaining:
 
  - `xbt_ex` was the type of C exceptions. It is now a standard C++ exception.
-    We might want to remove this and use a more idiomatic C++ solution.
-    `std::system_error` might be used for some error categories.
+    We might want to remove this exception and use a more idiomatic C++
+    solution with dedicated exception classes for different errors.
+    `std::system_error` might be used as well by replacing some `xbt_errcat_t`
+    with custom subclasses of `std::error_category`.
+
+ - The C API currently throws exceptions. Throwing exceptions out of a C API is
+   not very friendly. C code does not expect them, cannot catch them and cannot
+   handle resource management properly in face of exceptions. We should clearly
+   separate the C++ API and the C API and catch all exceptions before they get
+   ouf of C APIs.
+
+@subsubsection contributing_todo_time Time and duration
 
- - The C API currently throws exceptions exceptions. Throwing exceptions out
-   of C API is not very friendly. C code does not expect them, cannot catch
-   them and cannot handle resource management properly with exceptions.
-   We should clearly separate the C++ API and the C API and catch all exceptions
-   before they get ouf of C APIs.
+Some support for C++11-style time/duration is implemented (see `chrono.hpp`)
+but only available in some (S4U) APIs. It would be nice to add support for
+them in the rest of the C++ code.
 
-@subsection contributing_todo_futures Additions to the futures
+A related change would be to avoid using "-1" to mean "forever" at least in S4U
+and in the internal code. For compatibility, MSG should probably keep this
+semantic. We should probably always use separate functions
+(`wait` vs `wait_for`).
+
+@subsubsection contributing_todo_futures Futures
 
  - Some features are missing in the Maestro future implementation
-  (`simgrid::simix::Future`, `simgrid::simix::Promise`)
+  (`simgrid::kernel::Future`, `simgrid::kernel::Promise`)
   could be extended to support additional features:
   `when_any`, `shared_future`, etc.
 
  - The corresponding feature might then be implemented in the user process
-   futures.
+   futures (`simgrid::simix::Future`).
+
+ - Currently `.then()` is not available for user futures. We would need to add
+   a basic user event loop in order to queue the pending continuations.
 
  - We might need to provide the option to cancel a pending operation. This
    might be achieved by defining some `Action` or `Operation` class with an
    API compatible with `Future` (and convertiable to it) but with an
    additional `.cancel()` method.
 
-@subsection contributing_todo_simcalls Simcalls cleanup
+@subsection contributing_todo_smpi SMPI
+
+@subsubsection contributing_smpi_split_process Process-based privatization
+
+Currently, all the simulated processes live in the same process as the SimGrid
+simulator. The benefit is that we don't have to do context switches and IPC
+between the simulator and the processes.
+
+The fact that they share the same address space means that one memory corruption
+in one simulated process can propagate to the other ones and the SimGrid
+simulator itself.
+
+Moreover, the current design for SMPI applications is to compile the MPI code
+normally and execute it once per simulated process in the same system process:
+This means that all the existing simulated MPI processes share the same virtual
+address space and share by default sthe same global variables. This is not
+correct as each MPI process is expected to use its own address space and have
+its own global variables. In order to fix, this problem we have an optional
+SMPI privatization feature which creates a instanciation of the executable
+data segment per MPI process and map the correct one (using `mmap`) at each
+context switch.
+
+This approach has many problems:
+
+ 1. It is not completely safe. We only handle SMPI privatization for the global
+    variables in the execute data segment. Shared objects are ignored but some
+    may contain global variables which may need to be privatized:
+
+    - libsimgrid for example must not be privatized because it contains
+      shared state for the simulator;
 
- - Remove simcalls by using the generic ones. One issue with this is that we
-   didn't devise a good way to deal with generic simcalls in the model-checker
-   yet.
+    - libc must not be privatized for the same reason (but some global variables
+      in the libc may not be privatized);
+
+    - if we use global variables of some shared object in the executable, this
+      global variable will be instanciated in the executable (because of copy
+      relocation) and will be privatized even if it shoud not.
+
+ 2. We cannot execute the MPI processes in parallel. Only one can execute at
+    the same time because only one privatization segment can be mapped at a
+    given time.
+
+In order to fix this, the standard solution is to move each MPI process in its
+system process and use IPC to communicate with the simulator. One concern would
+be the impact on performance and memory consumption:
+
+ - It would introduce a lot of context switches and IPC communications between
+   the MPI processes and the SimGrid simulator. However, currently every context
+   switch needs a `mmap` for SMPI privatization which is costly as well
+   (TLB flush).
+
+ - Instanciating a lot of processes might consume more memory which might be a
+   problem if we want to simulate a lot of MPI processes. Compiling MPI programs
+   as static executables with a lightweight libc might help and we might want to
+   support that. The SMPI processes should probably not embed all the SimGrid
+   simulator and its dependencies, the C++ runtime, etc.
+
+We would need to modify the model-checker as well which currently can only
+manage on model-checked process. For the model-checker we can expect some
+benefits from this approach: if a process did not execute, we know its state
+did not change and we don't need to take its snapshot and compare its state.
+
+Other solutions for this might include:
+
+ - Mapping each MPI process in the process of the simulator but in a different
+   symbol namespace (see `dlmopen`). Each process would have its own separate
+   instanciation and would not share libraries.
+
+ - Instanciate each MPI process in a separate lightweight VM (for example based
+   on WebAssembly) in the simualtor process.
 
 @subsection contributing_todo_mc Model-checker
 
- - Find a good solution to handle generic simcalls in the model-checker.
+@subsubsection contributing_todo_mc_state_compare Overhaul the state comparison code
+
+The state comparison code is quite complicated. It has very long functions and
+is programmed mostly using C idioms and is difficult to understanda and debug.
+It is in need or an overhaul:
+
+  - cleanup, refactorisation, usage of C++ features.
+
+  - The state comparison code works by infering types of blocks allocated on the
+    heap by following pointers from known roots (global variables, local
+    variables). Usually the first type found for a given block is used even if
+    a better one could be found later. By using a first pass of type inference,
+    on each snapshot before comparing the states, we might use a better type
+    information on the different blocks.
+
+  - We might benefit from adding logic for handling some known types. For
+    example, both `std::string` and `std::vector` have a capacity which might
+    be larger than the current size of the container. We should might ignore
+    the corresponding elements when comparing the states and infering the types.
+
+  - Another difficulty in the state comparison code is the detection of
+    dangling pointers. We cannot easily know if a pointer is dangling and
+    dangling pointers might lead us to choose the wrong type when infering
+    heap blocks. We might mitigate this problem by delaying the reallocation of
+    a freed block until there is no blocks pointing to it anymore using some
+    sort of basic garbage-collector.
+
+@subsubsection contributing_todo_state_hashing Hashing the states
+
+In order to speed up the state comparison an idea was to create a hash of the
+state. Only states with the same hash would need to be compared using the
+state comparison algorithm. Some information should not be inclueded in the
+hash in order to avoid considering different states which would otherwise
+would have been considered equal.
+
+The stated could be indexed by their hash. Currently they are indexed
+by the number of processes and the amount of heap currently allocated
+(see `DerefAndCompareByNbProcessesAndUsedHeap`).
+
+Good candidate informations for the state hashing:
+
+ - number of processes;
+
+ - their backtraces (instruction addresses);
+
+ - their current simcall numbers;
+
+ - some simcall arguments (eg. number of elements in a waitany);
+
+ - number of pending communications;
+
+ - etc.
+
+Some basic infrastructure for this is already in the code (see `mc_hash.cpp`)
+but it is currently disabled.
+
+@subsubsection contributing_todo_mc_separation Separate the model-checker code from libsimgrid
+
+@subsubsection contributing_todo_mc_mced_interface Interface with the model-checked processes
+
+The model-checker reads many informations about the model-checked process
+by `process_vm_readv()`-ing brutally the data structure of the model-checked
+process leading to some horrible code such as walking a swag from another
+process. It prevents us as well from replacing some XBT data structures with
+standard C++ ones. We need a sane way to expose the relevant informations to
+the model-checker.
+
+@subsubsection contributing_todo_mc_generic_simcalls Generic simcalls
+
+We have introduced some generic simcalls which can be used to execute a
+callback in SimGrid Maestro context. It makes it a lot easier to interface
+the simulated process with the maestro. However, the callbacks for the
+model-checker which cannot decide how it should handle them. We would need a
+solution for this if we want to be able to replace the simcalls the
+model-checker cares about by generic simcalls.
+
+@subsubsection contributing_todo_mc_api Definig an API for writing Model-Checking algorithms
+
+Currently, writing a new model-checking algorithms in SimGridMC is quite
+difficult: the logic of the model-checking algorithm is mixed with a lot of
+low-level concerns about the way the model-checker is implemented. This makes it
+difficult to write new algorithms and difficult to understand, debug and modify
+the existing ones. We need a clean API to express the model-checking algorithms
+in a form which is closer to the text-book/paper description. This API muste
+be exposed in a a language which is more adequate to this task.
+
+Tasks:
 
- - Define a clear interface to be used by model-checking algorithms. The
-   `Session` class in intended to expose this interface but it is not a thing
-   yet.
+  1. Design and implement a clean API for expression model-checking algorithms.
+     A `Session` class currently exists for this but is not feature complete
+     and should probably be rewritten. It should be easy to create bindings
+     for different languages on top of this API.
 
- - Rewrite the different algorithms as implementations of the `Checker` class
-   using the `Session` inteface.
+  2. Create a binding to some better suited, dynamic, scripting language
+     (eg. Lua).
 
- - Currently a lot of informations the model-checker reads many informations
-   about the model-checked process by `process_vm_readv()`-ing brutally the
-   data structure leading to some horrible code such as walking a swag from
-   another process. It would be nice to have a sane way for the model-checker
-   to expose the relevant information to the model-checker.
+  3. Rewrite the existing model-checking algorithms in this language using the
+     new API.
 
 */
\ No newline at end of file
index 4c9e2f8..2410812 100644 (file)
@@ -1,5 +1,5 @@
 /** 
-@defgroup SMPI_API      SMPI: Semulate real MPI applications
+@defgroup SMPI_API      SMPI: Simulate real MPI applications
 @brief Programming environment for the simulation of MPI applications
     
 This programming environment enables the study of MPI application by
index ef58360..1ecc29e 100644 (file)
   @{ */
      /** @defgroup XBT_dynar  Dynar: generic dynamic array */
      /** @defgroup XBT_dict   Dict: generic dictionnary */
-     /** @defgroup XBT_set    Set: generic set datatype */
      /** @defgroup XBT_fifo   Fifo: generic workqueue */
      /** @defgroup XBT_swag   Swag: O(1) set datatype */
      /** @defgroup XBT_heap Heap: generic heap data structure */
-     /** @defgroup XBT_dd Data description */
 /** @} */
 
 
index 45b5624..2f5f95f 100644 (file)
@@ -199,17 +199,6 @@ the \b maxmin/precision item (default value: 0.00001). Changing it
 may speedup the simulation by discarding very small actions, at the
 price of a reduced numerical precision.
 
-\subsection options_model_nthreads Parallel threads for model updates
-
-By default, Surf computes the analytical models sequentially to share their
-resources and update their actions. It is possible to run them in parallel,
-using the \b surf/nthreads item (default value: 1). If you use a
-negative or null value, the amount of available cores is automatically
-detected  and used instead.
-
-Depending on the workload of the models and their complexity, you may get a
-speedup or a slowdown because of the synchronization costs of threads.
-
 \subsection options_model_network Configuring the Network model
 
 \subsubsection options_model_network_gamma Maximal TCP window size
index 6a75337..7a750df 100644 (file)
@@ -12,20 +12,20 @@ TBD
 S4U classes are designed to be user process interfaces to Maestro resources.
 We provide an uniform interface to them:
 
-* automatic reference count with intrusive smart pointers `simgrid::s4u::FooPtr`
 (also called `simgrid::s4u::Foo::Ptr`);
+- automatic reference count with intrusive smart pointers `simgrid::s4u::FooPtr`
+ (also called `simgrid::s4u::Foo::Ptr`);
 
-* manual reference count with `intrusive_ptr_add_ref(p)`,
+- manual reference count with `intrusive_ptr_add_ref(p)`,
   `intrusive_ptr_release(p)` (which is the interface used by
   [`boost::intrusive_ptr`](http://www.boost.org/doc/libs/1_61_0/libs/smart_ptr/intrusive_ptr.html));
 
-* delegation of the operations to a opaque `pimpl` (which is the Maestro object);
+- delegation of the operations to a opaque `pimpl` (which is the Maestro object);
 
-* the Maestro object and the corresponding S4U object have the same lifetime
+- the Maestro object and the corresponding S4U object have the same lifetime
   (and share the same reference count).
 
 The ability to manipulate thge objects thought pointers and have the ability
-to use explicite reference count management is useful for creating C wrappers
+to use explicit reference count management is useful for creating C wrappers
 to the S4U and should play nicely with other language bindings (such as
 SWIG-based ones).
 
@@ -38,18 +38,18 @@ corresponding C++ standard classes. For example, the methods of
 `simgrid::s4u::Mutex` are based on [`std::mutex`](http://en.cppreference.com/w/cpp/thread/mutex).
 This has several benefits:
 
* we use a proven interface with a well defined and documented semantic;
- we use a proven interface with a well defined and documented semantic;
 
* the interface is easy to understand and remember for people used to the C++
- the interface is easy to understand and remember for people used to the C++
    standard interface;
 
* we can use some standard C++ algorithms and helper classes with our types
 we can use some standard C++ algorithms and helper classes with our types
    (`simgrid::s4u::Mutex` can be used with
    [`std::lock`](http://en.cppreference.com/w/cpp/thread/lock),
    [`std::unique_lock`](http://en.cppreference.com/w/cpp/thread/unique_lock),
    etc.).
 
-Example of `simgris::s4u::Actor`:
+Example of `simgrid::s4u::Actor`:
 
 ~~~
 class Actor {
@@ -205,7 +205,7 @@ The current implementation of the model-checker uses two distinct processes:
 
  - the SimGrid model-checker (`simgrid-mc`) itself lives in the parent process;
 
- - it spaws a child process for the SimGrid simulator/mastro and the simulated
+ - it spaws a child process for the SimGrid simulator/maestro and the simulated
    processes.
 
 They communicate using a `AF_UNIX` `SOCK_DGRAM` socket and exchange messages
@@ -215,15 +215,15 @@ set to the file descriptor of this socket in the child process.
 The model-checker analyzes, saves and restores the state of the model-checked
 process using the following techniques:
 
-* the model-checker reads and writes in the model-checked address space;
+- the model-checker reads and writes in the model-checked address space;
 
-* the model-cheker `ptrace()`s the model-checked process and is thus able to
+- the model-cheker `ptrace()`s the model-checked process and is thus able to
   know the state of the model-checked process if it crashes;
 
-* DWARF debug informations are used to unwind the stack and identify local
+- DWARF debug informations are used to unwind the stack and identify local
   variables;
 
-* a custom heap is enabled in the model-checked process which allows the model
+- a custom heap is enabled in the model-checked process which allows the model
   checker to know which chunks are allocated and which are freed.
 
 \subsection simgrid_uhood_mc_address_space Address space
index 8c7fb2c..b918505 100644 (file)
@@ -8,6 +8,7 @@ package app.bittorrent;
 
 import org.simgrid.msg.Msg;
 import org.simgrid.msg.MsgException;
+import org.simgrid.msg.RngStream;
 
 class Main{
   private Main() {
@@ -15,6 +16,9 @@ class Main{
   }
 
   public static void main(String[] args) throws MsgException {
+    int[] seed = { 12345, 12345, 12345, 12345, 12345, 12345 };
+    RngStream.setPackageSeed(seed);
+
     Msg.init(args);
     if(args.length < 2) {
       Msg.info("Usage   : Bittorrent platform_file deployment_file");
index 560bb8a..c0ee4dd 100644 (file)
@@ -15,8 +15,8 @@ $ ${bindir:=.}/io-file ${srcdir:=.}/storage/storage.xml "--log=root.fmt:[%10.6r]
 >              File Descriptor Id: 0
 > [  0.000000] (1:host@denise)         Open file '/home/doc/simgrid/examples/platforms/g5k.xml'
 > [  0.000000] (2:host@alice)  Capacity of the storage element 'c:\Windows\setupact.log' is stored on: 2391537133 / 536870912000
-> [  0.000000] (3:host@carl)   Capacity of the storage element '/home/doc/simgrid/examples/platforms/g5k_cabinets.xml' is stored on: 36942866 / 536870912000
-> [  0.000000] (4:host@bob)    Capacity of the storage element '/home/doc/simgrid/examples/platforms/nancy.xml' is stored on: 36942866 / 536870912000
+> [  0.000000] (3:host@carl)   Capacity of the storage element '/home/doc/simgrid/examples/platforms/g5k_cabinets.xml' is stored on: 36933331 / 536870912000
+> [  0.000000] (4:host@bob)    Capacity of the storage element '/home/doc/simgrid/examples/platforms/nancy.xml' is stored on: 36933331 / 536870912000
 > [  0.000000] (1:host@denise)         Capacity of the storage element '/home/doc/simgrid/examples/platforms/g5k.xml' is stored on: 13221994 / 536870912000
 > [  0.000040] (4:host@bob)    Have read 4028 from '/home/doc/simgrid/examples/platforms/nancy.xml'
 > [  0.000085] (1:host@denise)         Have read 17028 from '/home/doc/simgrid/examples/platforms/g5k.xml'
@@ -33,10 +33,10 @@ $ ${bindir:=.}/io-file ${srcdir:=.}/storage/storage.xml "--log=root.fmt:[%10.6r]
 > [  0.002725] (2:host@alice)  Have read 110000 from 'c:\Windows\setupact.log' (of size 201663)
 > [  0.002725] (2:host@alice)  Coming back to the beginning of the stream for file 'c:\Windows\setupact.log'
 > [  0.003374] (4:host@bob)    Have written 100000 in '/home/doc/simgrid/examples/platforms/nancy.xml'. Size now is: 104028
-> [  0.003374] (4:host@bob)    Capacity of the storage element '/home/doc/simgrid/examples/platforms/nancy.xml' is stored on: 37042866 / 536870912000
+> [  0.003374] (4:host@bob)    Capacity of the storage element '/home/doc/simgrid/examples/platforms/nancy.xml' is stored on: 37033331 / 536870912000
 > [  0.003374] (4:host@bob)    Coming back to the beginning of the stream for file '/home/doc/simgrid/examples/platforms/nancy.xml'
 > [  0.003560] (3:host@carl)   Have written 100000 in '/home/doc/simgrid/examples/platforms/g5k_cabinets.xml'. Size now is: 122645
-> [  0.003560] (3:host@carl)   Capacity of the storage element '/home/doc/simgrid/examples/platforms/g5k_cabinets.xml' is stored on: 37042866 / 536870912000
+> [  0.003560] (3:host@carl)   Capacity of the storage element '/home/doc/simgrid/examples/platforms/g5k_cabinets.xml' is stored on: 37033331 / 536870912000
 > [  0.003560] (3:host@carl)   Coming back to the beginning of the stream for file '/home/doc/simgrid/examples/platforms/g5k_cabinets.xml'
 > [  0.004135] (1:host@denise)         Have written 110000 in '/home/doc/simgrid/examples/platforms/g5k.xml'. Size now is: 110000
 > [  0.004135] (1:host@denise)         Capacity of the storage element '/home/doc/simgrid/examples/platforms/g5k.xml' is stored on: 13314966 / 536870912000
@@ -49,9 +49,9 @@ $ ${bindir:=.}/io-file ${srcdir:=.}/storage/storage.xml "--log=root.fmt:[%10.6r]
 > [  0.004660] (3:host@carl)   Have read 110000 from '/home/doc/simgrid/examples/platforms/g5k_cabinets.xml' (of size 122645)
 > [  0.004660] (3:host@carl)   Coming back to the beginning of the stream for file '/home/doc/simgrid/examples/platforms/g5k_cabinets.xml'
 > [  0.008081] (4:host@bob)    Have written 110000 in '/home/doc/simgrid/examples/platforms/nancy.xml'. Size now is: 110000
-> [  0.008081] (4:host@bob)    Capacity of the storage element '/home/doc/simgrid/examples/platforms/nancy.xml' is stored on: 37048838 / 536870912000
+> [  0.008081] (4:host@bob)    Capacity of the storage element '/home/doc/simgrid/examples/platforms/nancy.xml' is stored on: 37039303 / 536870912000
 > [  0.008081] (4:host@bob)    Close file '/home/doc/simgrid/examples/platforms/nancy.xml'
 > [  0.008326] (3:host@carl)   Have written 110000 in '/home/doc/simgrid/examples/platforms/g5k_cabinets.xml'. Size now is: 110000
-> [  0.008326] (3:host@carl)   Capacity of the storage element '/home/doc/simgrid/examples/platforms/g5k_cabinets.xml' is stored on: 37030221 / 536870912000
+> [  0.008326] (3:host@carl)   Capacity of the storage element '/home/doc/simgrid/examples/platforms/g5k_cabinets.xml' is stored on: 37020686 / 536870912000
 > [  0.008326] (3:host@carl)   Close file '/home/doc/simgrid/examples/platforms/g5k_cabinets.xml'
 > [  0.008326] (0:maestro@) Simulation time 0.00832645
index 53a74b5..ec8ccf8 100644 (file)
 /doc/simgrid/examples/smpi/compute2.c  628
 /doc/simgrid/examples/smpi/sendrecv.c  1652
 /doc/simgrid/examples/smpi/allreduce.c  2135
-/doc/simgrid/examples/smpi/mvmul.c  7069
 /doc/simgrid/examples/smpi/alltoallv.c  4441
 /doc/simgrid/examples/smpi/smpi_traced.c  8529
 /doc/simgrid/examples/smpi/compute3.c  816
 /doc/simgrid/examples/smpi/reduce.c  3545
-/doc/simgrid/examples/smpi/bcbench.c  2466
 /doc/simgrid/examples/smpi/ttest01.c  1273
 /doc/simgrid/examples/smpi/compute.c  622
 /doc/simgrid/examples/smpi/barrier.c  766
index 51c89d3..3221411 100644 (file)
@@ -8,7 +8,7 @@
 #include "simgrid/msg.h"
 #include "simgrid/simix.h"      /* semaphores for the barrier */
 #include <xbt/replay.h>
-#include "simgrid/s4u.h"
+#include "simgrid/s4u.hpp"
 
 XBT_LOG_NEW_DEFAULT_CATEGORY(actions, "Messages specific for this msg example");
 int communicator_size = 0;
index 7ee0a43..e5a0e21 100644 (file)
@@ -4,8 +4,7 @@
  * under the terms of the license (GNU LGPL) which comes with this package. */
 
 #include <xbt/sysdep.h>
-
-#include <simgrid/s4u.h>
+#include <simgrid/s4u.hpp>
 
 #include "s4u_basic.h"
 
index f4e85e0..1cfdc83 100644 (file)
@@ -5,7 +5,7 @@
 
 #include <xbt/sysdep.h>
 
-#include "simgrid/s4u.h"
+#include <simgrid/s4u.hpp>
 
 XBT_LOG_NEW_DEFAULT_CATEGORY(s4u_test, "a sample log category");
 
index f40b9aa..7b68d2a 100644 (file)
@@ -7,8 +7,7 @@
 #include <vector>
 
 #include <xbt/sysdep.h>
-
-#include <simgrid/s4u.h>
+#include <simgrid/s4u.hpp>
 
 #include "s4u_basic.h"
 
index 9759056..c915ed7 100644 (file)
@@ -8,7 +8,7 @@
 
 #include <xbt/sysdep.h>
 
-#include <simgrid/s4u.h>
+#include <simgrid/s4u.hpp>
 
 #include "s4u_basic.h"
 
index 9d0545e..e9ebf57 100644 (file)
@@ -5,7 +5,7 @@
 
 #include <unordered_map>
 
-#include "simgrid/s4u.h"
+#include "simgrid/s4u.hpp"
 
 XBT_LOG_NEW_DEFAULT_CATEGORY(s4u_test, "a sample log category");
 
index c9073e4..bffc85d 100644 (file)
@@ -8,7 +8,7 @@
 
 #include <xbt/sysdep.h>
 
-#include "simgrid/s4u.h"
+#include "simgrid/s4u.hpp"
 
 #define NB_ACTOR 2
 
@@ -55,7 +55,7 @@ static void master()
       simgrid::s4u::Actor::createActor("worker", simgrid::s4u::Host::by_name("Tremblay"), worker,          mutex, std::ref(result));
   }
 
-  simgrid::s4u::this_actor::sleep(10);
+  simgrid::s4u::this_actor::sleep_for(10);
   XBT_INFO("Results is -> %d", result);
 }
 
index 58f4773..095e851 100644 (file)
@@ -10,8 +10,8 @@ $ $SG_TEST_EXENV ${bindir:=.}/dag-dotload/sd_dag-dotload --log=no_loc ${srcdir:=
 > [0.000000] [sd_task/INFO]   - amount: 0
 > [0.000000] [sd_task/INFO]   - Dependencies to satisfy: 0
 > [0.000000] [sd_task/INFO]   - post-dependencies:
-> [0.000000] [sd_task/INFO]     root->5
 > [0.000000] [sd_task/INFO]     0
+> [0.000000] [sd_task/INFO]     root->5
 > [0.000000] [sd_task/INFO] Displaying task 0
 > [0.000000] [sd_task/INFO]   - state: not scheduled not runnable
 > [0.000000] [sd_task/INFO]   - kind: sequential computation
@@ -63,8 +63,8 @@ $ $SG_TEST_EXENV ${bindir:=.}/dag-dotload/sd_dag-dotload --log=no_loc ${srcdir:=
 > [0.000000] [sd_task/INFO]   - amount: 10000000046
 > [0.000000] [sd_task/INFO]   - Dependencies to satisfy: 2
 > [0.000000] [sd_task/INFO]   - pre-dependencies:
-> [0.000000] [sd_task/INFO]     4->5
 > [0.000000] [sd_task/INFO]     root->5
+> [0.000000] [sd_task/INFO]     4->5
 > [0.000000] [sd_task/INFO]   - post-dependencies:
 > [0.000000] [sd_task/INFO]     6
 > [0.000000] [sd_task/INFO] Displaying task 6
@@ -84,8 +84,8 @@ $ $SG_TEST_EXENV ${bindir:=.}/dag-dotload/sd_dag-dotload --log=no_loc ${srcdir:=
 > [0.000000] [sd_task/INFO]   - pre-dependencies:
 > [0.000000] [sd_task/INFO]     6->7
 > [0.000000] [sd_task/INFO]   - post-dependencies:
-> [0.000000] [sd_task/INFO]     7->8
 > [0.000000] [sd_task/INFO]     7->end
+> [0.000000] [sd_task/INFO]     7->8
 > [0.000000] [sd_task/INFO] Displaying task 8
 > [0.000000] [sd_task/INFO]   - state: not scheduled not runnable
 > [0.000000] [sd_task/INFO]   - kind: sequential computation
@@ -182,8 +182,8 @@ $ $SG_TEST_EXENV ${bindir:=.}/dag-dotload/sd_dag-dotload --log=no_loc ${srcdir:=
 > [0.000000] [sd_task/INFO]   - amount: 10000000129
 > [0.000000] [sd_task/INFO]   - Dependencies to satisfy: 2
 > [0.000000] [sd_task/INFO]   - pre-dependencies:
-> [0.000000] [sd_task/INFO]     7->end
 > [0.000000] [sd_task/INFO]     9
+> [0.000000] [sd_task/INFO]     7->end
 > [0.000000] [test/INFO] ------------------- Schedule tasks ---------------------------
 > [0.000000] [test/INFO] ------------------- Run the schedule ---------------------------
 > [110.006082] [test/INFO] ------------------- Produce the trace file---------------------------
index fbb6c25..ece1172 100644 (file)
@@ -12,8 +12,8 @@ $ $SG_TEST_EXENV ${bindir:=.}/daxload/sd_daxload --log=no_loc ${srcdir:=.}/../pl
 > [0.000000] [sd_task/INFO]   - amount: 0
 > [0.000000] [sd_task/INFO]   - Dependencies to satisfy: 0
 > [0.000000] [sd_task/INFO]   - post-dependencies:
-> [0.000000] [sd_task/INFO]     root_i2_2@task2
 > [0.000000] [sd_task/INFO]     root_i1_1@task1
+> [0.000000] [sd_task/INFO]     root_i2_2@task2
 > [0.000000] [sd_task/INFO] Displaying task 1@task1
 > [0.000000] [sd_task/INFO]   - state: not scheduled not runnable
 > [0.000000] [sd_task/INFO]   - kind: sequential computation
@@ -40,10 +40,10 @@ $ $SG_TEST_EXENV ${bindir:=.}/daxload/sd_daxload --log=no_loc ${srcdir:=.}/../pl
 > [0.000000] [sd_task/INFO]   - amount: 42000000000
 > [0.000000] [sd_task/INFO]   - Dependencies to satisfy: 4
 > [0.000000] [sd_task/INFO]   - pre-dependencies:
-> [0.000000] [sd_task/INFO]     1@task1
 > [0.000000] [sd_task/INFO]     2@task2
-> [0.000000] [sd_task/INFO]     1@task1_o1_3@task1
+> [0.000000] [sd_task/INFO]     1@task1
 > [0.000000] [sd_task/INFO]     2@task2_o2_3@task1
+> [0.000000] [sd_task/INFO]     1@task1_o1_3@task1
 > [0.000000] [sd_task/INFO]   - post-dependencies:
 > [0.000000] [sd_task/INFO]     3@task1_o3_end
 > [0.000000] [sd_task/INFO] Displaying task root_i2_2@task2
index 116eef3..6c08678 100644 (file)
@@ -11,8 +11,8 @@ $ $SG_TEST_EXENV ${bindir:=.}/ptg-dotload/sd_ptg-dotload  ${srcdir:=.}/../platfo
 > [0.000000] [sd_task/INFO]   - alpha: 0.00
 > [0.000000] [sd_task/INFO]   - Dependencies to satisfy: 0
 > [0.000000] [sd_task/INFO]   - post-dependencies:
-> [0.000000] [sd_task/INFO]     root->c1
 > [0.000000] [sd_task/INFO]     root->c2
+> [0.000000] [sd_task/INFO]     root->c1
 > [0.000000] [sd_task/INFO] Displaying task c1
 > [0.000000] [sd_task/INFO]   - state: not scheduled not runnable
 > [0.000000] [sd_task/INFO]   - kind: parallel computation following Amdahl's law
@@ -40,8 +40,8 @@ $ $SG_TEST_EXENV ${bindir:=.}/ptg-dotload/sd_ptg-dotload  ${srcdir:=.}/../platfo
 > [0.000000] [sd_task/INFO]   - alpha: 0.00
 > [0.000000] [sd_task/INFO]   - Dependencies to satisfy: 2
 > [0.000000] [sd_task/INFO]   - pre-dependencies:
-> [0.000000] [sd_task/INFO]     c1->c3
 > [0.000000] [sd_task/INFO]     c2
+> [0.000000] [sd_task/INFO]     c1->c3
 > [0.000000] [sd_task/INFO]   - post-dependencies:
 > [0.000000] [sd_task/INFO]     c3->end
 > [0.000000] [sd_task/INFO] Displaying task c1->c3
index b59adcb..ab26689 100644 (file)
@@ -21,9 +21,9 @@ $ $SG_TEST_EXENV ${bindir:=.}/schedule-dotload/sd_schedule-dotload --log=no_loc
 > [0.000000] [sd_task/INFO]   - amount: 0
 > [0.000000] [sd_task/INFO]   - Dependencies to satisfy: 0
 > [0.000000] [sd_task/INFO]   - post-dependencies:
-> [0.000000] [sd_task/INFO]     root->5
-> [0.000000] [sd_task/INFO]     0
 > [0.000000] [sd_task/INFO]     1
+> [0.000000] [sd_task/INFO]     0
+> [0.000000] [sd_task/INFO]     root->5
 > [0.000000] [sd_task/INFO] Displaying task 0
 > [0.000000] [sd_task/INFO]   - state: scheduled not runnable
 > [0.000000] [sd_task/INFO]   - kind: sequential computation
@@ -32,8 +32,8 @@ $ $SG_TEST_EXENV ${bindir:=.}/schedule-dotload/sd_schedule-dotload --log=no_loc
 > [0.000000] [sd_task/INFO]   - pre-dependencies:
 > [0.000000] [sd_task/INFO]     root
 > [0.000000] [sd_task/INFO]   - post-dependencies:
-> [0.000000] [sd_task/INFO]     0->2
 > [0.000000] [sd_task/INFO]     2
+> [0.000000] [sd_task/INFO]     0->2
 > [0.000000] [sd_task/INFO] Displaying task 1
 > [0.000000] [sd_task/INFO]   - state: scheduled not runnable
 > [0.000000] [sd_task/INFO]   - kind: sequential computation
@@ -42,31 +42,31 @@ $ $SG_TEST_EXENV ${bindir:=.}/schedule-dotload/sd_schedule-dotload --log=no_loc
 > [0.000000] [sd_task/INFO]   - pre-dependencies:
 > [0.000000] [sd_task/INFO]     root
 > [0.000000] [sd_task/INFO]   - post-dependencies:
-> [0.000000] [sd_task/INFO]     1->2
 > [0.000000] [sd_task/INFO]     4
+> [0.000000] [sd_task/INFO]     1->2
 > [0.000000] [sd_task/INFO] Displaying task 2
 > [0.000000] [sd_task/INFO]   - state: scheduled not runnable
 > [0.000000] [sd_task/INFO]   - kind: sequential computation
 > [0.000000] [sd_task/INFO]   - amount: 10000000121
 > [0.000000] [sd_task/INFO]   - Dependencies to satisfy: 3
 > [0.000000] [sd_task/INFO]   - pre-dependencies:
-> [0.000000] [sd_task/INFO]     0->2
-> [0.000000] [sd_task/INFO]     1->2
 > [0.000000] [sd_task/INFO]     0
+> [0.000000] [sd_task/INFO]     1->2
+> [0.000000] [sd_task/INFO]     0->2
 > [0.000000] [sd_task/INFO]   - post-dependencies:
-> [0.000000] [sd_task/INFO]     2->3
 > [0.000000] [sd_task/INFO]     3
+> [0.000000] [sd_task/INFO]     2->3
 > [0.000000] [sd_task/INFO] Displaying task 3
 > [0.000000] [sd_task/INFO]   - state: scheduled not runnable
 > [0.000000] [sd_task/INFO]   - kind: sequential computation
 > [0.000000] [sd_task/INFO]   - amount: 10000000231
 > [0.000000] [sd_task/INFO]   - Dependencies to satisfy: 2
 > [0.000000] [sd_task/INFO]   - pre-dependencies:
-> [0.000000] [sd_task/INFO]     2->3
 > [0.000000] [sd_task/INFO]     2
+> [0.000000] [sd_task/INFO]     2->3
 > [0.000000] [sd_task/INFO]   - post-dependencies:
-> [0.000000] [sd_task/INFO]     4
 > [0.000000] [sd_task/INFO]     8
+> [0.000000] [sd_task/INFO]     4
 > [0.000000] [sd_task/INFO] Displaying task 4
 > [0.000000] [sd_task/INFO]   - state: scheduled not runnable
 > [0.000000] [sd_task/INFO]   - kind: sequential computation
@@ -76,17 +76,17 @@ $ $SG_TEST_EXENV ${bindir:=.}/schedule-dotload/sd_schedule-dotload --log=no_loc
 > [0.000000] [sd_task/INFO]     3
 > [0.000000] [sd_task/INFO]     1
 > [0.000000] [sd_task/INFO]   - post-dependencies:
-> [0.000000] [sd_task/INFO]     4->5
 > [0.000000] [sd_task/INFO]     5
+> [0.000000] [sd_task/INFO]     4->5
 > [0.000000] [sd_task/INFO] Displaying task 5
 > [0.000000] [sd_task/INFO]   - state: scheduled not runnable
 > [0.000000] [sd_task/INFO]   - kind: sequential computation
 > [0.000000] [sd_task/INFO]   - amount: 10000000046
 > [0.000000] [sd_task/INFO]   - Dependencies to satisfy: 3
 > [0.000000] [sd_task/INFO]   - pre-dependencies:
-> [0.000000] [sd_task/INFO]     root->5
-> [0.000000] [sd_task/INFO]     4->5
 > [0.000000] [sd_task/INFO]     4
+> [0.000000] [sd_task/INFO]     4->5
+> [0.000000] [sd_task/INFO]     root->5
 > [0.000000] [sd_task/INFO]   - post-dependencies:
 > [0.000000] [sd_task/INFO]     6
 > [0.000000] [sd_task/INFO] Displaying task 6
@@ -97,28 +97,28 @@ $ $SG_TEST_EXENV ${bindir:=.}/schedule-dotload/sd_schedule-dotload --log=no_loc
 > [0.000000] [sd_task/INFO]   - pre-dependencies:
 > [0.000000] [sd_task/INFO]     5
 > [0.000000] [sd_task/INFO]   - post-dependencies:
-> [0.000000] [sd_task/INFO]     6->7
 > [0.000000] [sd_task/INFO]     7
+> [0.000000] [sd_task/INFO]     6->7
 > [0.000000] [sd_task/INFO] Displaying task 7
 > [0.000000] [sd_task/INFO]   - state: scheduled not runnable
 > [0.000000] [sd_task/INFO]   - kind: sequential computation
 > [0.000000] [sd_task/INFO]   - amount: 10000000041
 > [0.000000] [sd_task/INFO]   - Dependencies to satisfy: 2
 > [0.000000] [sd_task/INFO]   - pre-dependencies:
-> [0.000000] [sd_task/INFO]     6->7
 > [0.000000] [sd_task/INFO]     6
+> [0.000000] [sd_task/INFO]     6->7
 > [0.000000] [sd_task/INFO]   - post-dependencies:
-> [0.000000] [sd_task/INFO]     7->8
-> [0.000000] [sd_task/INFO]     7->end
 > [0.000000] [sd_task/INFO]     end
+> [0.000000] [sd_task/INFO]     7->end
+> [0.000000] [sd_task/INFO]     7->8
 > [0.000000] [sd_task/INFO] Displaying task 8
 > [0.000000] [sd_task/INFO]   - state: scheduled not runnable
 > [0.000000] [sd_task/INFO]   - kind: sequential computation
 > [0.000000] [sd_task/INFO]   - amount: 10000000250
 > [0.000000] [sd_task/INFO]   - Dependencies to satisfy: 2
 > [0.000000] [sd_task/INFO]   - pre-dependencies:
-> [0.000000] [sd_task/INFO]     7->8
 > [0.000000] [sd_task/INFO]     3
+> [0.000000] [sd_task/INFO]     7->8
 > [0.000000] [sd_task/INFO]   - post-dependencies:
 > [0.000000] [sd_task/INFO]     9
 > [0.000000] [sd_task/INFO] Displaying task 9
@@ -208,9 +208,9 @@ $ $SG_TEST_EXENV ${bindir:=.}/schedule-dotload/sd_schedule-dotload --log=no_loc
 > [0.000000] [sd_task/INFO]   - amount: 10000000129
 > [0.000000] [sd_task/INFO]   - Dependencies to satisfy: 3
 > [0.000000] [sd_task/INFO]   - pre-dependencies:
-> [0.000000] [sd_task/INFO]     7->end
 > [0.000000] [sd_task/INFO]     9
 > [0.000000] [sd_task/INFO]     7
+> [0.000000] [sd_task/INFO]     7->end
 > [0.000000] [test/INFO] ------------------- Run the schedule ---------------------------
 > [100.003561] [test/INFO] ------------------- Produce the trace file---------------------------
 > [100.003561] [test/INFO] Producing the trace of the run into dag_with_good_schedule.trace
index 7269bc6..e4531aa 100644 (file)
@@ -92,24 +92,15 @@ static double finish_on_at(SD_task_t task, sg_host_t host)
     xbt_dynar_foreach(parents, i, parent) {
       /* normal case */
       if (SD_task_get_kind(parent) == SD_TASK_COMM_E2E) {
-        xbt_dynar_t grand_parents = SD_task_get_parents(parent);
-        SD_task_t grand_parent;
-
-        xbt_assert(xbt_dynar_length(grand_parents) <2, "Error: transfer %s has 2 parents", SD_task_get_name(parent));
-
-        xbt_dynar_get_cpy(grand_parents, 0, &grand_parent);
-
-        sg_host_t * grand_parent_host_list = SD_task_get_workstation_list(grand_parent);
+        sg_host_t * parent_host= SD_task_get_workstation_list(parent);
         /* Estimate the redistribution time from this parent */
         if (SD_task_get_amount(parent) <= 1e-6){
           redist_time= 0;
         } else {
-          redist_time = SD_route_get_latency(grand_parent_host_list[0], host) +
-                        SD_task_get_amount(parent) / SD_route_get_bandwidth(grand_parent_host_list[0], host);
+          redist_time = SD_route_get_latency(parent_host[0], host) +
+                        SD_task_get_amount(parent) / SD_route_get_bandwidth(parent_host[0], host);
         }
-        data_available = SD_task_get_finish_time(grand_parent) + redist_time;
-
-        xbt_dynar_free_container(&grand_parents);
+        data_available = SD_task_get_start_time(parent) + redist_time;
       }
 
       /* no transfer, control dependency */
@@ -134,7 +125,7 @@ static double finish_on_at(SD_task_t task, sg_host_t host)
 
 static sg_host_t SD_task_get_best_host(SD_task_t task)
 {
-  const sg_host_t *hosts = sg_host_list();
+  sg_host_t *hosts = sg_host_list();
   int nhosts = sg_host_count();
   sg_host_t best_host = hosts[0];
   double min_EFT = finish_on_at(task, hosts[0]);
@@ -148,6 +139,7 @@ static sg_host_t SD_task_get_best_host(SD_task_t task)
       best_host = hosts[i];
     }
   }
+  xbt_free(hosts);
   return best_host;
 }
 
@@ -175,7 +167,7 @@ int main(int argc, char **argv)
 
   /*  Allocating the host attribute */
   int total_nhosts = sg_host_count();
-  const sg_host_t *hosts = sg_host_list();
+  sg_host_t *hosts = sg_host_list();
 
   for (cursor = 0; cursor < total_nhosts; cursor++)
     sg_host_allocate_attribute(hosts[cursor]);
@@ -259,6 +251,7 @@ int main(int argc, char **argv)
   for (cursor = 0; cursor < total_nhosts; cursor++)
     sg_host_free_attribute(hosts[cursor]);
 
+  xbt_free(hosts);
   /* exit */
   SD_exit();
   return 0;
index e1847b2..376a992 100644 (file)
@@ -4,7 +4,7 @@ if(enable_smpi)
 
   file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mc/")
 
-  foreach(x bcbench mvmul replay trace trace_simple trace_call_location energy)
+  foreach(x replay trace trace_simple trace_call_location energy)
     add_executable       (smpi_${x} ${CMAKE_CURRENT_SOURCE_DIR}/${x}/${x}.c)
     target_link_libraries(smpi_${x} simgrid)
     set_target_properties(smpi_${x} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${x})
diff --git a/examples/smpi/bcbench/bcbench.c b/examples/smpi/bcbench/bcbench.c
deleted file mode 100644 (file)
index 082250d..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/* Copyright (c) 2009-2010, 2012-2014. 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 <stdio.h>
-#include <stdlib.h>
-#include <mpi.h>
-
-#ifdef _WIN32
-  #define srandom srand
-  #define random rand
-#endif
-
-#define GETTIMEOFDAY_ERROR 1
-
-#define N_START 1
-#define N_STOP  1024*1024
-#define N_NEXT  (N*2)
-#define ITER    100
-#define ONE_MILLION 1000000.0
-#define RAND_SEED 842270
-
-int main(int argc, char *argv[])
-{
-  int size, rank;
-  struct timeval *start_time = NULL, *stop_time = NULL;
-  double seconds = 0;
-  char *buffer;
-  int check;
-
-  srandom(RAND_SEED);
-
-  MPI_Init(&argc, &argv);
-
-  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
-  MPI_Comm_size(MPI_COMM_WORLD, &size);
-
-  if (0 == rank) {
-    start_time = (struct timeval *) malloc(sizeof(struct timeval));
-    stop_time = (struct timeval *) malloc(sizeof(struct timeval));
-  }
-
-  for (int N = N_START; N <= N_STOP; N = N_NEXT) {
-    buffer = malloc(sizeof(char) * N);
-
-    if (0 == rank) {
-      for (int j = 0; j < N; j++) {
-        buffer[j] = (char) (random() % 256);
-      }
-      if (-1 == gettimeofday(start_time, NULL)) {
-        printf("couldn't set start_time on node 0!\n");
-        MPI_Abort(MPI_COMM_WORLD, GETTIMEOFDAY_ERROR);
-        exit(EXIT_FAILURE);
-      }
-    }
-
-    for (int i = 0; i < ITER; i++) {
-      MPI_Bcast(buffer, N, MPI_BYTE, 0, MPI_COMM_WORLD);
-      if (0 == rank) {
-        for (int j = 1; j < size; j++) {
-          MPI_Recv(&check, 1, MPI_INT, MPI_ANY_SOURCE, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
-        }
-      } else {
-        MPI_Send(&rank, 1, MPI_INT, 0, 1, MPI_COMM_WORLD);
-      }
-    }
-
-    if (0 == rank) {
-      if (-1 == gettimeofday(stop_time, NULL)) {
-        printf("couldn't set start_time on node 0!\n");
-        MPI_Abort(MPI_COMM_WORLD, GETTIMEOFDAY_ERROR);
-        exit(EXIT_FAILURE);
-      }
-      seconds = (double) (stop_time->tv_sec - start_time->tv_sec) +
-                (double) (stop_time->tv_usec - start_time->tv_usec) / ONE_MILLION;
-    }
-
-    free(buffer);
-
-    if (0 == rank) {
-      printf("N: %10d, iter: %d, time: %10f s, avg rate: %12f Mbps\n", N, ITER, seconds,
-             ((double) N * ITER * 8) / (1024.0 * 1024.0 * seconds));
-    }
-  }
-
-  if (0 == rank) {
-    free(start_time);
-    free(stop_time);
-  }
-
-  MPI_Finalize();
-
-  return 0;
-}
diff --git a/examples/smpi/mvmul/mvmul.c b/examples/smpi/mvmul/mvmul.c
deleted file mode 100644 (file)
index fd25813..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
-/* Copyright (c) 2009-2010, 2013-2014. 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 <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <mpi.h>
-#include <xbt/str.h>
-
-#define ITERATIONS         10
-#define USAGE_ERROR        1
-#define SANITY_ERROR       2
-#define GETTIMEOFDAY_ERROR 3
-
-int main(int argc, char *argv[])
-{
-  int size, rank;
-  int N, n, i, j, k, current_iteration, successful_iterations = 0;
-  double *matrix = NULL, *vector = NULL, *vcalc, *vcheck;
-  MPI_Status status;
-  struct timeval *start_time = NULL, *stop_time = NULL;
-  long parallel_usecs, parallel_usecs_total = 0, sequential_usecs, sequential_usecs_total = 0;
-
-  MPI_Init(&argc, &argv);
-
-  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
-  MPI_Comm_size(MPI_COMM_WORLD, &size);
-
-  if (0 == rank) {
-    // root node parses cmdline args
-    if (2 > argc || !isdigit(*argv[1])) {
-      printf("usage:\n%s <size>\n", argv[0]);
-      MPI_Abort(MPI_COMM_WORLD, USAGE_ERROR);
-      exit(USAGE_ERROR);
-    }
-
-    N = xbt_str_parse_int(argv[1], "Invalid size: %s");
-
-    start_time = (struct timeval *) malloc(sizeof(struct timeval));
-    stop_time = (struct timeval *) malloc(sizeof(struct timeval));
-  }
-
-  for (current_iteration = 0; current_iteration < ITERATIONS; current_iteration++) {
-    if (0 == rank) {
-      matrix = (double *) malloc(N * N * sizeof(double));
-      vector = (double *) malloc(N * sizeof(double));
-
-      for (i = 0; i < N * N; i++) {
-        matrix[i] = (double) rand() / ((double) RAND_MAX + 1);
-      }
-
-      for (i = 0; i < N; i++) {
-        vector[i] = (double) rand() / ((double) RAND_MAX + 1);
-      }
-
-      // for the sake of argument, the parallel algorithm begins when the root node begins to transmit the matrix to the
-      // workers.
-      if (-1 == gettimeofday(start_time, NULL)) {
-        printf("couldn't set start_time on node 0!\n");
-        MPI_Abort(MPI_COMM_WORLD, GETTIMEOFDAY_ERROR);
-        exit(GETTIMEOFDAY_ERROR);
-      }
-
-      for (i = 1; i < size; i++) {
-        MPI_Send(&N, 1, MPI_INT, i, 0, MPI_COMM_WORLD);
-      }
-    } else {
-      MPI_Recv(&N, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &status);
-    }
-
-    // this algorithm uses at most N processors...
-    if (rank < N) {
-      if (size > N)
-        size = N;
-      n = N / size + ((rank < (N % size)) ? 1 : 0);
-
-      if (0 == rank) {
-        for (i = 1, j = n; i < size && j < N; i++, j += k) {
-          k = N / size + ((i < (N % size)) ? 1 : 0);
-          MPI_Send(matrix + N * j, N * k, MPI_DOUBLE, i, 0, MPI_COMM_WORLD);
-          MPI_Send(vector, N, MPI_DOUBLE, i, 0, MPI_COMM_WORLD);
-        }
-
-        // sanity check
-#ifdef DEBUG
-        if (i != size || j != N) {
-          printf("index calc error: i = %d, size = %d, j = %d, N = %d\n", i, size, j, N);
-          MPI_Abort(MPI_COMM_WORLD, SANITY_ERROR);
-          exit(SANITY_ERROR);
-        }
-#endif
-
-        vcalc = (double *) malloc(N * sizeof(double));
-      } else {
-        matrix = (double *) malloc(N * n * sizeof(double));
-        vector = (double *) malloc(N * sizeof(double));
-        vcalc = (double *) malloc(n * sizeof(double));
-
-        MPI_Recv(matrix, N * n, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, &status);
-        MPI_Recv(vector, N, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, &status);
-      }
-
-      for (i = 0; i < n; i++) {
-        vcalc[i] = 0.0;
-        for (j = 0; j < N; j++) {
-          vcalc[i] += matrix[N * i + j] * vector[j];
-        }
-      }
-
-      if (0 != rank) {
-        MPI_Send(vcalc, n, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD);
-      } else {
-        for (i = 1, j = n; i < size && j < N; i++, j += k) {
-          k = N / size + ((i < (N % size)) ? 1 : 0);
-          MPI_Recv(vcalc + j, k, MPI_DOUBLE, i, 0, MPI_COMM_WORLD, &status);
-        }
-
-        // sanity check
-#ifdef DEBUG
-        if (i != size || j != N) {
-          printf("index calc error 2: i = %d, size = %d, j = %d, N = %d\n", i, size, j, N);
-          MPI_Abort(MPI_COMM_WORLD, SANITY_ERROR);
-          exit(SANITY_ERROR);
-        }
-#endif
-
-        if (-1 == gettimeofday(stop_time, NULL)) {
-          printf("couldn't set stop_time on node 0!\n");
-          MPI_Abort(MPI_COMM_WORLD, GETTIMEOFDAY_ERROR);
-          exit(GETTIMEOFDAY_ERROR);
-        }
-
-        parallel_usecs = (stop_time->tv_sec * 1000000 + stop_time->tv_usec) -
-                         (start_time->tv_sec * 1000000 + start_time->tv_usec);
-
-        if (-1 == gettimeofday(start_time, NULL)) {
-          printf("couldn't set start_time on node 0!\n");
-          MPI_Abort(MPI_COMM_WORLD, GETTIMEOFDAY_ERROR);
-          exit(GETTIMEOFDAY_ERROR);
-        }
-        // calculate serially
-        vcheck = (double *) malloc(N * sizeof(double));
-        for (i = 0; i < N; i++) {
-          vcheck[i] = 0.0;
-          for (j = 0; j < N; j++) {
-            vcheck[i] += matrix[N * i + j] * vector[j];
-          }
-        }
-
-        if (-1 == gettimeofday(stop_time, NULL)) {
-          printf("couldn't set stop_time on node 0!\n");
-          MPI_Abort(MPI_COMM_WORLD, GETTIMEOFDAY_ERROR);
-          exit(GETTIMEOFDAY_ERROR);
-        }
-
-        sequential_usecs = (stop_time->tv_sec * 1000000 + stop_time->tv_usec) -
-                           (start_time->tv_sec * 1000000 + start_time->tv_usec);
-
-        // verify correctness
-        for (i = 0; i < N && vcalc[i] == vcheck[i]; i++);
-
-        printf("prog: blocking, i: %d ", current_iteration);
-
-        if (i == N) {
-          printf("ptime: %ld us, stime: %ld us, speedup: %.3f, nodes: %d, efficiency: %.3f\n",
-               parallel_usecs, sequential_usecs, (double) sequential_usecs / (double) parallel_usecs, size,
-               (double) sequential_usecs / ((double) parallel_usecs * (double) size));
-
-          parallel_usecs_total += parallel_usecs;
-          sequential_usecs_total += sequential_usecs;
-          successful_iterations++;
-        } else {
-          printf("parallel calc != serial calc, ");
-        }
-
-        free(vcheck);
-      }
-
-      free(matrix);
-      free(vector);
-      free(vcalc);
-    }
-  }
-
-  if (0 == rank) {
-    printf("prog: blocking, ");
-    if (0 < successful_iterations) {
-      printf("iterations: %d, avg. ptime: %.3f us, avg. stime: %.3f us, avg. speedup: %.3f, nodes: %d, avg. efficiency: %.3f\n",
-           successful_iterations, (double) parallel_usecs_total / (double) successful_iterations,
-           (double) sequential_usecs_total / (double) successful_iterations,
-           (double) sequential_usecs_total / (double) parallel_usecs_total, size,
-           (double) sequential_usecs_total / ((double) parallel_usecs_total * (double) size));
-    } else {
-      printf("no successful iterations!\n");
-    }
-
-    free(start_time);
-    free(stop_time);
-  }
-
-  MPI_Finalize();
-
-  return 0;
-}
diff --git a/include/simgrid/chrono.hpp b/include/simgrid/chrono.hpp
new file mode 100644 (file)
index 0000000..4395b41
--- /dev/null
@@ -0,0 +1,55 @@
+/* Copyright (c) 2016. 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. */
+
+#ifndef SIMGRID_CHRONO_HPP
+#define SIMGRID_CHRONO_HPP
+
+/** @file chrono.hpp Time support
+ *
+ *  Define clock, duration types, time point types compatible with the standard
+ *  C++ library API.
+ */
+
+#include <chrono>
+#include <ratio>
+
+#include <simgrid/simix.h>
+
+namespace simgrid {
+
+/** A C++ compatible TrivialClock working with simulated-time */
+struct SimulationClock {
+  using rep        = double;
+  using period     = std::ratio<1>;
+  using duration   = std::chrono::duration<rep, period>;
+  using time_point = std::chrono::time_point<SimulationClock, duration>;
+  static constexpr bool is_steady = true;
+  static time_point now()
+  {
+    return time_point(duration(SIMIX_get_clock()));
+  }
+};
+
+/** Default duration for simulated time */
+using SimulationClockDuration  = SimulationClock::duration;
+
+/** Default time point for simulated time */
+using SimulationClockTimePoint = SimulationClock::time_point;
+
+// Durations based on doubles:
+using nanoseconds = std::chrono::duration<double, std::nano>;
+using microseconds = std::chrono::duration<double, std::micro>;
+using milliseconds = std::chrono::duration<double, std::milli>;
+using seconds = std::chrono::duration<double>;
+using minutes = std::chrono::duration<double, std::ratio<60>>;
+using hours = std::chrono::duration<double, std::ratio<3600>>;
+
+/** A time point in the simulated time */
+template<class Duration>
+using SimulationTimePoint = std::chrono::time_point<SimulationClock, Duration>;
+
+}
+
+#endif
index b3dce5f..ae778de 100644 (file)
@@ -449,13 +449,6 @@ XBT_PUBLIC(void) MSG_task_set_category (msg_task_t task, const char *category);
 XBT_PUBLIC(const char *) MSG_task_get_category (msg_task_t task);
 
 /************************** Mailbox handling ************************************/
-/* @brief MSG_mailbox_new - create a new mailbox.
- * Creates a new mailbox identified by the key specified by the parameter alias and add it in the global dictionary.
- * @param  alias  The alias of the mailbox to create.
- * @return        The newly created mailbox.
- */
-XBT_PUBLIC(msg_mailbox_t) MSG_mailbox_new(const char *alias);
-
 /* @brief MSG_mailbox_get_by_alias - get a mailbox from its alias.
  * Returns the mailbox associated with the key specified by the parameter alias. If the mailbox does not exists,
  * the function creates it.
@@ -505,7 +498,7 @@ XBT_PUBLIC(msg_sem_t) MSG_sem_init(int initial_value);
 XBT_PUBLIC(void) MSG_sem_acquire(msg_sem_t sem);
 XBT_PUBLIC(msg_error_t) MSG_sem_acquire_timeout(msg_sem_t sem, double timeout);
 XBT_PUBLIC(void) MSG_sem_release(msg_sem_t sem);
-XBT_PUBLIC(void) MSG_sem_get_capacity(msg_sem_t sem);
+XBT_PUBLIC(int) MSG_sem_get_capacity(msg_sem_t sem);
 XBT_PUBLIC(void) MSG_sem_destroy(msg_sem_t sem);
 XBT_PUBLIC(int) MSG_sem_would_block(msg_sem_t sem);
 
similarity index 95%
rename from include/simgrid/s4u.h
rename to include/simgrid/s4u.hpp
index 63b75a8..89a40e8 100644 (file)
@@ -6,7 +6,7 @@
 #ifndef SIMGRID_S4U_S4U_H
 #define SIMGRID_S4U_S4U_H
 
-#include "s4u/actor.hpp"
+#include "s4u/Actor.hpp"
 #include "s4u/mailbox.hpp"
 #include "s4u/engine.hpp"
 #include "s4u/host.hpp"
index fae7fb8..0b8d303 100644 (file)
@@ -33,6 +33,9 @@ protected:
   virtual ~Activity();
 
 public:
+  Activity(Activity const&) = delete;
+  Activity& operator=(Activity const&) = delete;
+
   /** Starts a previously created activity.
    *
    * This function is optional: you can call wait() even if you didn't call start()
similarity index 91%
rename from include/simgrid/s4u/actor.hpp
rename to include/simgrid/s4u/Actor.hpp
index 8e1b703..89a7727 100644 (file)
@@ -7,6 +7,7 @@
 #define SIMGRID_S4U_ACTOR_HPP
 
 #include <atomic>
+#include <chrono>
 #include <functional>
 #include <memory>
 #include <stdexcept>
@@ -20,6 +21,7 @@
 #include <xbt/base.h>
 #include <xbt/functional.hpp>
 
+#include <simgrid/chrono.hpp>
 #include <simgrid/simix.h>
 #include <simgrid/s4u/forward.hpp>
 
@@ -245,8 +247,10 @@ public:
 
   /** Ask kindly to all actors to die. Only the issuer will survive. */
   static void killAll();
-  
-  smx_process_t getInferior();
+
+protected:
+  /** Returns the internal implementation of this actor */
+  smx_process_t getImpl();
 };
 
 using ActorPtr = Actor::Ptr;
@@ -256,7 +260,27 @@ using ActorPtr = Actor::Ptr;
 namespace this_actor {
 
   /** Block the actor sleeping for that amount of seconds (may throws hostFailure) */
-  XBT_PUBLIC(void) sleep(double duration);
+  XBT_PUBLIC(void) sleep_for(double duration);
+  XBT_PUBLIC(void) sleep_until(double timeout);
+
+  template<class Rep, class Period>
+  inline void sleep_for(std::chrono::duration<Rep, Period> duration)
+  {
+    auto seconds = std::chrono::duration_cast<SimulationClockDuration>(duration);
+    this_actor::sleep_for(seconds.count());
+  }
+  template<class Duration>
+  inline void sleep_until(const SimulationTimePoint<Duration>& timeout_time)
+  {
+    auto timeout_native = std::chrono::time_point_cast<SimulationClockDuration>(timeout_time);
+    this_actor::sleep_until(timeout_native.time_since_epoch().count());
+  }
+
+  XBT_ATTRIB_DEPRECATED("Use sleep_for()")
+  inline void sleep(double duration)
+  {
+    return sleep_for(duration);
+  }
 
   /** Block the actor, computing the given amount of flops */
   XBT_PUBLIC(e_smx_state_t) execute(double flop);
index 47c7332..891d300 100644 (file)
 #include <simgrid/s4u/Activity.hpp>
 #include <simgrid/s4u/forward.hpp>
 #include <simgrid/s4u/mailbox.hpp>
+#include <simgrid/forward.h>
+
 
 namespace simgrid {
 namespace s4u {
 
+
 /** @brief Communication async
  *
  * Represents all asynchronous communications, that you can test or wait onto.
@@ -26,6 +29,55 @@ public:
   ~Comm() override;
 
 public:
+  
+  /*! tanke a range of s4u::Comm* (last excluded) and return when one of them is finished. The return value is an iterator on the finished Comms. */
+  template<class I> static
+  I wait_any(I first, I last)
+  {
+    // Map to dynar<Synchro*>:
+    xbt_dynar_t comms = xbt_dynar_new(sizeof(simgrid::simix::Synchro*), NULL);
+    for(I iter = first; iter != last; iter++) {
+      Comm& comm = **iter;
+      if (comm.state_ == inited)
+        comm.start();
+      xbt_assert(comm.state_ == started);
+      xbt_dynar_push_as(comms, simgrid::simix::Synchro*, comm.pimpl_);
+    }
+    // Call the underlying simcall:
+    int idx = simcall_comm_waitany(comms, -1);
+    xbt_dynar_free(&comms);
+    // Not found:
+    if (idx == -1)
+      return last;
+    // Lift the index to the corresponding iterator:
+    auto res = std::next(first, idx);
+    (*res)->state_ = finished;
+    return res;
+  }
+  /*! Same as wait_any, but with a timeout. If wait_any_for return because of the timeout last is returned.*/
+  template<class I> static
+  I wait_any_for(I first, I last, double timeout)
+  {
+    // Map to dynar<Synchro*>:
+    xbt_dynar_t comms = xbt_dynar_new(sizeof(simgrid::simix::Synchro*), NULL);
+    for(I iter = first; iter != last; iter++) {
+      Comm& comm = **iter;
+      if (comm.state_ == inited)
+        comm.start();
+      xbt_assert(comm.state_ == started);
+      xbt_dynar_push_as(comms, simgrid::simix::Synchro*, comm.pimpl_);
+    }
+    // Call the underlying simcall:
+    int idx = simcall_comm_waitany(comms, timeout);
+    xbt_dynar_free(&comms);
+    // Not found:
+    if (idx == -1)
+      return last;
+    // Lift the index to the corresponding iterator:
+    auto res = std::next(first, idx);
+    (*res)->state_ = finished;
+    return res;
+  }
   /** Creates (but don't start) an async send to the mailbox @p dest */
   static Comm &send_init(Mailbox &dest);
   /** Creates and start an async send to the mailbox @p dest */
@@ -56,6 +108,8 @@ public:
   /** Retrieve the size of the received data */
   size_t getDstDataSize();
 
+  bool test();
+
 
 private:
   double rate_ = -1;
index cad7507..3b03bca 100644 (file)
@@ -6,6 +6,7 @@
 #ifndef SIMGRID_S4U_COND_VARIABLE_HPP
 #define SIMGRID_S4U_COND_VARIABLE_HPP
 
+#include <chrono>
 #include <condition_variable>
 #include <future>
 #include <mutex>
@@ -16,6 +17,7 @@
 #include <xbt/base.h>
 
 #include <simgrid/simix.h>
+#include <simgrid/chrono.hpp>
 #include <simgrid/s4u/mutex.hpp>
 
 namespace simgrid {
@@ -45,20 +47,20 @@ public:
 
   static Ptr createConditionVariable();
 
-  //  Wait functions:
+  //  Wait functions without time:
 
   void wait(std::unique_lock<Mutex>& lock);
-  std::cv_status wait_until(std::unique_lock<Mutex>& lock, double timeout_time);
-  std::cv_status wait_for(std::unique_lock<Mutex>& lock, double duration);
-
-  // Variants which takes a predicate:
-
   template<class P>
   void wait(std::unique_lock<Mutex>& lock, P pred)
   {
     while (!pred())
       wait(lock);
   }
+
+  // Wait function taking a plain double as time:
+
+  std::cv_status wait_until(std::unique_lock<Mutex>& lock, double timeout_time);
+  std::cv_status wait_for(std::unique_lock<Mutex>& lock, double duration);
   template<class P>
   bool wait_until(std::unique_lock<Mutex>& lock, double timeout_time, P pred)
   {
@@ -73,6 +75,39 @@ public:
     return this->wait_until(lock, SIMIX_get_clock() + duration, std::move(pred));
   }
 
+  // Wait function taking a C++ style time:
+
+  template<class Rep, class Period, class P>
+  bool wait_for(
+    std::unique_lock<Mutex>& lock, std::chrono::duration<Rep, Period> duration,
+    P pred)
+  {
+    auto seconds = std::chrono::duration_cast<SimulationClockDuration>(duration);
+    return this->wait_for(lock, seconds.count(), pred);
+  }
+  template<class Rep, class Period>
+  std::cv_status wait_for(
+    std::unique_lock<Mutex>& lock, std::chrono::duration<Rep, Period> duration)
+  {
+    auto seconds = std::chrono::duration_cast<SimulationClockDuration>(duration);
+    return this->wait_for(lock, seconds.count());
+  }
+  template<class Duration>
+  std::cv_status wait_until(std::unique_lock<Mutex>& lock,
+    const SimulationTimePoint<Duration>& timeout_time)
+  {
+    auto timeout_native = std::chrono::time_point_cast<SimulationClockDuration>(timeout_time);
+    return this->wait_until(lock, timeout_native.time_since_epoch().count());
+  }
+  template<class Duration, class P>
+  bool wait_until(std::unique_lock<Mutex>& lock,
+    const SimulationTimePoint<Duration>& timeout_time, P pred)
+  {
+    auto timeout_native = std::chrono::time_point_cast<SimulationClockDuration>(timeout_time);
+    return this->wait_until(lock, timeout_native.time_since_epoch().count(),
+      std::move(pred));
+  }
+
   // Notify functions
 
   void notify_one();
index 4238ecf..f26266a 100644 (file)
@@ -13,7 +13,7 @@
 #include <xbt/base.h>
 
 #include <simgrid/s4u/forward.hpp>
-#include <simgrid/s4u/actor.hpp>
+#include <simgrid/s4u/Actor.hpp>
 
 namespace simgrid {
 namespace s4u {
@@ -35,7 +35,7 @@ XBT_PUBLIC_CLASS Mailbox {
   Mailbox(smx_mailbox_t mbox): pimpl_(mbox) {}
 
 protected:
-  smx_mailbox_t getInferior() { return pimpl_; }
+  smx_mailbox_t getImpl() { return pimpl_; }
 
 public:
 
@@ -61,7 +61,7 @@ public:
   void setReceiver(Actor* process);
 
   /** Return the process declared as permanent receiver, or nullptr if none **/
-  Actor& receiver();
+  ActorPtr receiver();
 };
 
 using MailboxPtr = Mailbox::Ptr;
@@ -71,6 +71,5 @@ using MailboxPtr = Mailbox::Ptr;
 XBT_PUBLIC(sg_mbox_t) sg_mbox_by_name(const char*name);
 XBT_PUBLIC(int) sg_mbox_is_empty(sg_mbox_t mbox);
 XBT_PUBLIC(void)sg_mbox_setReceiver(sg_mbox_t mbox, smx_process_t process);
-XBT_PUBLIC(smx_process_t) sg_mbox_receiver(sg_mbox_t mbox);
 
 #endif /* SIMGRID_S4U_MAILBOX_HPP */
index 77f9ea6..d49faa5 100644 (file)
@@ -58,10 +58,6 @@ typedef enum {
   SD_TASK_COMM_PAR_MXN_1D_BLOCK = 4 /**< @brief MxN data redistribution (1D Block distribution) */
 } e_SD_task_kind_t;
 
-/** @brief Storage datatype
-    @ingroup SD_storage_api */
-typedef xbt_dictelm_t SD_storage_t;
-
 /************************** Workstation handling ****************************/
 /** @addtogroup SD_host_api
  *
@@ -75,11 +71,8 @@ typedef xbt_dictelm_t SD_storage_t;
  */
 XBT_PUBLIC(SD_link_t *) SD_route_get_list(sg_host_t src, sg_host_t dst);
 XBT_PUBLIC(int) SD_route_get_size(sg_host_t src, sg_host_t dst);
-
 XBT_PUBLIC(double) SD_route_get_latency(sg_host_t src, sg_host_t dst);
 XBT_PUBLIC(double) SD_route_get_bandwidth(sg_host_t src, sg_host_t dst);
-
-XBT_PUBLIC(const char*) SD_storage_get_host(SD_storage_t storage);
 /** @} */
 
 /************************** Task handling ************************************/
@@ -109,10 +102,10 @@ XBT_PUBLIC(double) SD_task_get_amount(SD_task_t task);
 XBT_PUBLIC(void) SD_task_set_amount(SD_task_t task, double amount);
 XBT_PUBLIC(double) SD_task_get_alpha(SD_task_t task);
 XBT_PUBLIC(double) SD_task_get_remaining_amount(SD_task_t task);
-XBT_PUBLIC(double) SD_task_get_execution_time(SD_task_t task, int workstation_nb, const sg_host_t *workstation_list,
+XBT_PUBLIC(double) SD_task_get_execution_time(SD_task_t task, int host_count, const sg_host_t *host_list,
                                               const double *flops_amount, const double *bytes_amount);
 XBT_PUBLIC(e_SD_task_kind_t) SD_task_get_kind(SD_task_t task);
-XBT_PUBLIC(void) SD_task_schedule(SD_task_t task, int workstation_nb, const sg_host_t *workstation_list,
+XBT_PUBLIC(void) SD_task_schedule(SD_task_t task, int host_count, const sg_host_t *host_list,
                                   const double *flops_amount, const double *bytes_amount, double rate);
 XBT_PUBLIC(void) SD_task_unschedule(SD_task_t task);
 XBT_PUBLIC(double) SD_task_get_start_time(SD_task_t task);
@@ -137,9 +130,9 @@ XBT_PUBLIC(void) SD_task_schedulel(SD_task_t task, int count, ...);
 
 /** @brief A constant to use in SD_task_schedule to mean that there is no cost.
  *
- *  For example, create a pure computation task (no comm) like this:
+ *  For example, create a pure computation task (i.e., with no communication) like this:
  *
- *  SD_task_schedule(task, my_host_count, my_host_list, my_flops_amount, SD_TASK_SCHED_NO_COST, my_rate);
+ *  SD_task_schedule(task, my_host_count, my_host_list, my_flops_amount, SD_SCHED_NO_COST, my_rate);
  */
 #define SD_SCHED_NO_COST NULL
 
@@ -154,8 +147,6 @@ XBT_PUBLIC(void) SD_task_schedulel(SD_task_t task, int count, ...);
  */
 XBT_PUBLIC(void) SD_task_dependency_add(const char *name, void *data, SD_task_t src, SD_task_t dst);
 XBT_PUBLIC(void) SD_task_dependency_remove(SD_task_t src, SD_task_t dst);
-XBT_PUBLIC(const char *) SD_task_dependency_get_name(SD_task_t src, SD_task_t dst);
-XBT_PUBLIC(void *) SD_task_dependency_get_data(SD_task_t src, SD_task_t dst);
 XBT_PUBLIC(int) SD_task_dependency_exists(SD_task_t src, SD_task_t dst);
 /** @} */
 
index d9b6007..6b7f31b 100644 (file)
@@ -359,10 +359,10 @@ XBT_PUBLIC(smx_synchro_t) simcall_comm_iprobe(smx_mailbox_t mbox, int type, int
 XBT_PUBLIC(void) simcall_comm_cancel(smx_synchro_t comm);
 
 /* FIXME: waitany is going to be a vararg function, and should take a timeout */
-XBT_PUBLIC(unsigned int) simcall_comm_waitany(xbt_dynar_t comms);
+XBT_PUBLIC(unsigned int) simcall_comm_waitany(xbt_dynar_t comms, double timeout);
 XBT_PUBLIC(void) simcall_comm_wait(smx_synchro_t comm, double timeout);
 XBT_PUBLIC(int) simcall_comm_test(smx_synchro_t comm);
-XBT_PUBLIC(int) simcall_comm_testany(xbt_dynar_t comms);
+XBT_PUBLIC(int) simcall_comm_testany(smx_synchro_t* comms, size_t count);
 
 /************************** Tracing handling **********************************/
 XBT_PUBLIC(void) simcall_set_category(smx_synchro_t synchro, const char *category);
index b3cfd35..59eb624 100644 (file)
@@ -21,7 +21,7 @@ SG_BEGIN_DECL()
  *  This section describes the API to a dictionary structure that  associates as string to a void* key. It provides the
  *  same functionality than an hash table.
  *
- *  If you are using C++, you might want to use `std::unordered_map` instead.
+ *  @deprecated If you are using C++, you might want to use `std::unordered_map` instead.
  *
  *  Here is a little example of use:
 
index 874eb46..fa25a74 100644 (file)
@@ -25,7 +25,7 @@ SG_BEGIN_DECL()
   * \ref XBT_dict section). You thus have to provide the function which will be used to free the content at
   * structure creation (of type void_f_ppvoid_t or void_f_pvoid_t).
   *
-  *  If you are using C++, you might want to use `std::vector` instead.
+  * @deprecated If you are using C++, you might want to use `std::vector` instead.
   *
   * \section XBT_dynar_exscal Example with scalar
   * \dontinclude dynar.cpp
index 5f6432b..66ccf3d 100644 (file)
@@ -17,8 +17,8 @@ SG_BEGIN_DECL()
  * These functions provide the same kind of functionality as dynamic arrays
  * but in time O(1). However these functions use malloc/free way too much often.
  *
- *  If you are using C++, you might want to used std::list, std::deque or
- *  std::queue instead.
+ *  @deprecated If you are using C++, you might want to used `std::list`,
+ *  `std::deque` or `std::queue instead`.
  */
  
 /** @defgroup XBT_fifo_cons Fifo constructor and destructor
index 3fe2951..89ee7d1 100644 (file)
@@ -15,7 +15,8 @@ SG_BEGIN_DECL()
 /** @addtogroup XBT_heap
  *  @brief This section describes the API to generic heap with O(log(n)) access.
  *
- *  If you are using C++ you might want to use std::priority_queue instead.
+ *  @deprecated If you are using C++ you might want to use `std::priority_queue`
+ *  instead.
  *
  *  @{
  */
index 4c24f32..837829f 100644 (file)
@@ -659,5 +659,7 @@ extern xbt_log_layout_t xbt_log_default_layout;
  */
 #define XBT_HERE(...) XBT_LOG(xbt_log_priority_trace, "-- was here" __VA_ARGS__)
 
+XBT_PUBLIC(void) xbt_set_terminate();
+
 SG_END_DECL()
 #endif                          /* ! _XBT_LOG_H_ */
index 875b3ad..6dbf711 100644 (file)
@@ -20,5 +20,7 @@ XBT_PUBLIC(void) logException(
   e_xbt_log_priority_t priority,
   const char* context, std::exception const& exception);
 
+XBT_PUBLIC(void) installExceptionHandler();
+
 }
 }
index 318be64..a0f6b3e 100644 (file)
@@ -24,7 +24,8 @@ SG_BEGIN_DECL()
  *  It is basically a fifo but with restrictions so that it can be used as a set. Any operation (add, remove, belongs)
  *  is O(1) and no call to malloc/free is done.
  *
- *  If you are using C++, you might want to use boost::intrusive::set instead.
+ *  @deprecated If you are using C++, you might want to use
+ *  `boost::intrusive::set` instead.
  */
 /** @defgroup XBT_swag_type Swag types
     @ingroup XBT_swag
index e83783f..9ce1556 100644 (file)
@@ -16,12 +16,21 @@ sonar.sources=src,examples,include,teshsuite
 #  - our unit tests 
 #  - the tests that we borrowed elsewhere (MPICH and ISP)
 #  - Flex-generated files
-sonar.exclusions=src/*_unit.c*,teshsuite/smpi/mpich3-test/*,teshsuite/smpi/isp/*,**/*_dtd.c
-
+#  - Collectives that we borrowed elsewhere (mpich, openMPI and other implems)
+#  - the NAS, that are included in our examples
+sonar.exclusions=src/*_unit.c*,teshsuite/smpi/mpich3-test/**,teshsuite/smpi/isp/**,**/*_dtd.c,src/smpi/colls/*,examples/smpi/NAS/*
 # Ignore files that are generated from Flex
 sonar.issue.ignore.allfile=flexGenerated
 sonar.issue.ignore.allfile.flexGenerated.fileRegexp="generated by flex"
 
+# Ignore the files that SMPI scavenged here and there (not working)
+#sonar.issue.ignore.allfile=mpiColls
+#sonar.issue.ignore.allfile.flexGenerated.mpiColls="Ahmad Faraj"
+#sonar.issue.ignore.allfile=mpivapich
+#sonar.issue.ignore.allfile.flexGenerated.mpivapich="This file is part of the MVAPICH2 software package"
+#sonar.issue.ignore.allfile=mpiOmpi
+#sonar.issue.ignore.allfile.flexGenerated.mpiOmpi="University of Tennessee"
+
 # The build-wrapper output dir
 sonar.cfamily.build-wrapper-output=bw-outputs
 
index 11db6a5..a7e82b7 100644 (file)
@@ -6,6 +6,8 @@
 /* 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 <xbt/sysdep.h>
+
 #include "jmsg_rngstream.h"
 #include "jxbt_utilities.h"
 
@@ -43,16 +45,22 @@ JNIEXPORT void JNICALL Java_org_simgrid_msg_RngStream_nativeFinalize(JNIEnv *env
 
 JNIEXPORT jboolean JNICALL
 Java_org_simgrid_msg_RngStream_setPackageSeed(JNIEnv *env, jobject jrngstream, jintArray jseed) {
-  jint buffer[6];
-
-  env->GetIntArrayRegion(jseed, 0, 6, buffer);
 
-  RngStream rngstream = jrngstream_to_native(env, jrngstream);
-  if (!rngstream)
+  if (jseed == nullptr) {
+    jxbt_throw_null(env, xbt_strdup("seed argument is null"));
     return JNI_FALSE;
+  }
 
-  int result = RngStream_SetPackageSeed((unsigned long*)buffer);
+  jint buffer[6];
+  env->GetIntArrayRegion(jseed, 0, 6, buffer);
 
+  // The C API expects unsigned long which are wider than int on LP64.
+  // We need to convert:
+  unsigned long seed[6];
+  for (int i = 0; i != 6; ++i)
+    seed[i] = buffer[i];
+
+  int result = RngStream_SetPackageSeed(seed);
   return result == -1 ? JNI_FALSE : JNI_TRUE;
 }
 
@@ -102,7 +110,13 @@ JNIEXPORT jboolean JNICALL Java_org_simgrid_msg_RngStream_setSeed(JNIEnv *env, j
   if (!rngstream)
     return JNI_FALSE;
 
-  int result = RngStream_SetSeed(rngstream, (unsigned long*)buffer);
+  // The C API expects unsigned long which are wider than int on LP64.
+  // We need to convert:
+  unsigned long seed[6];
+  for (int i = 0; i != 6; ++i)
+    seed[i] = buffer[i];
+
+  int result = RngStream_SetSeed(rngstream, seed);
 
   return result == -1 ? JNI_FALSE : JNI_TRUE;
 }
index 3e443a3..72cfabd 100644 (file)
@@ -63,7 +63,7 @@ static int trace_precision;
 static bool trace_configured = false;
 static bool trace_active     = false;
 
-static void TRACE_getopts(void)
+static void TRACE_getopts()
 {
   trace_enabled             = xbt_cfg_get_boolean(OPT_TRACING);
   trace_platform            = xbt_cfg_get_boolean(OPT_TRACING_PLATFORM);
@@ -214,138 +214,138 @@ int TRACE_end()
   return retval;
 }
 
-bool TRACE_needs_platform (void)
+bool TRACE_needs_platform ()
 {
   return TRACE_msg_process_is_enabled() || TRACE_msg_vm_is_enabled() || TRACE_categorized() ||
          TRACE_uncategorized() || TRACE_platform () || (TRACE_smpi_is_enabled() && TRACE_smpi_is_grouped());
 }
 
-bool TRACE_is_enabled(void)
+bool TRACE_is_enabled()
 {
   return trace_enabled;
 }
 
-bool TRACE_platform(void)
+bool TRACE_platform()
 {
   return trace_platform;
 }
 
-bool TRACE_platform_topology(void)
+bool TRACE_platform_topology()
 {
   return trace_platform_topology;
 }
 
-bool TRACE_is_configured(void)
+bool TRACE_is_configured()
 {
   return trace_configured;
 }
 
-bool TRACE_smpi_is_enabled(void)
+bool TRACE_smpi_is_enabled()
 {
   return (trace_smpi_enabled || TRACE_smpi_is_grouped()) && TRACE_is_enabled();
 }
 
-bool TRACE_smpi_is_grouped(void)
+bool TRACE_smpi_is_grouped()
 {
   return trace_smpi_grouped;
 }
 
-bool TRACE_smpi_is_computing(void)
+bool TRACE_smpi_is_computing()
 {
   return trace_smpi_computing;
 }
 
-bool TRACE_smpi_is_sleeping(void)
+bool TRACE_smpi_is_sleeping()
 {
   return trace_smpi_sleeping;
 }
 
-bool TRACE_smpi_view_internals(void)
+bool TRACE_smpi_view_internals()
 {
   return trace_view_internals;
 }
 
-bool TRACE_categorized (void)
+bool TRACE_categorized ()
 {
   return trace_categorized;
 }
 
-bool TRACE_uncategorized (void)
+bool TRACE_uncategorized ()
 {
   return trace_uncategorized;
 }
 
-bool TRACE_msg_process_is_enabled(void)
+bool TRACE_msg_process_is_enabled()
 {
   return trace_msg_process_enabled && TRACE_is_enabled();
 }
 
-bool TRACE_msg_vm_is_enabled(void)
+bool TRACE_msg_vm_is_enabled()
 {
   return trace_msg_vm_enabled && TRACE_is_enabled();
 }
 
-bool TRACE_disable_link(void)
+bool TRACE_disable_link()
 {
   return trace_disable_link && TRACE_is_enabled();
 }
 
-bool TRACE_disable_speed(void)
+bool TRACE_disable_speed()
 {
   return trace_disable_power && TRACE_is_enabled();
 }
 
-bool TRACE_buffer (void)
+bool TRACE_buffer ()
 {
   return trace_buffer && TRACE_is_enabled();
 }
 
-bool TRACE_onelink_only (void)
+bool TRACE_onelink_only ()
 {
   return trace_onelink_only && TRACE_is_enabled();
 }
 
-bool TRACE_disable_destroy (void)
+bool TRACE_disable_destroy ()
 {
   return trace_disable_destroy && TRACE_is_enabled();
 }
 
-bool TRACE_basic (void)
+bool TRACE_basic ()
 {
   return trace_basic && TRACE_is_enabled();
 }
 
-bool TRACE_display_sizes (void)
+bool TRACE_display_sizes ()
 {
    return trace_display_sizes && trace_smpi_enabled && TRACE_is_enabled();
 }
 
-char *TRACE_get_comment (void)
+char *TRACE_get_comment ()
 {
   return xbt_cfg_get_string(OPT_TRACING_COMMENT);
 }
 
-char *TRACE_get_comment_file (void)
+char *TRACE_get_comment_file ()
 {
   return xbt_cfg_get_string(OPT_TRACING_COMMENT_FILE);
 }
 
-int TRACE_precision (void)
+int TRACE_precision ()
 {
   return xbt_cfg_get_int(OPT_TRACING_PRECISION);
 }
 
-char *TRACE_get_filename(void)
+char *TRACE_get_filename()
 {
   return xbt_cfg_get_string(OPT_TRACING_FILENAME);
 }
 
-char *TRACE_get_viva_uncat_conf (void)
+char *TRACE_get_viva_uncat_conf ()
 {
   return xbt_cfg_get_string(OPT_VIVA_UNCAT_CONF);
 }
 
-char *TRACE_get_viva_cat_conf (void)
+char *TRACE_get_viva_cat_conf ()
 {
   return xbt_cfg_get_string(OPT_VIVA_CAT_CONF);
 }
@@ -353,7 +353,8 @@ char *TRACE_get_viva_cat_conf (void)
 void TRACE_global_init(int *argc, char **argv)
 {
   static int is_initialised = 0;
-  if (is_initialised) return;
+  if (is_initialised)
+    return;
 
   is_initialised = 1;
   /* name of the tracefile */
@@ -409,7 +410,7 @@ static void print_line (const char *option, const char *desc, const char *longde
 
   int len = strlen (str);
   printf ("%s%*.*s %s\n", str, 30-len, 30-len, "", desc);
-  if (!!longdesc && detailed){
+  if (longdesc != nullptr && detailed){
     printf ("%s\n\n", longdesc);
   }
 }
@@ -514,7 +515,7 @@ static void output_types (const char *name, xbt_dynar_t types, FILE *file)
   unsigned int i;
   fprintf (file, "  %s = (", name);
   for (i = xbt_dynar_length(types); i > 0; i--) {
-    char *type = *(char**)xbt_dynar_get_ptr(types, i - 1);
+    char *type = *(static_cast<char**>(xbt_dynar_get_ptr(types, i - 1)));
     fprintf (file, "\"%s\"", type);
     if (i - 1 > 0){
       fprintf (file, ",");
@@ -530,7 +531,7 @@ static void output_categories (const char *name, xbt_dynar_t cats, FILE *file)
   unsigned int i;
   fprintf (file, "    values = (");
   for (i = xbt_dynar_length(cats); i > 0; i--) {
-    char *cat = *(char**)xbt_dynar_get_ptr(cats, i - 1);
+    char *cat = *(static_cast<char**>(xbt_dynar_get_ptr(cats, i - 1)));
     fprintf (file, "\"%s%s\"", name, cat);
     if (i - 1 > 0){
       fprintf (file, ",");
@@ -591,13 +592,15 @@ static void generate_uncat_configuration (const char *output, const char *name,
   if (output && strlen(output) > 0){
     FILE *file = fopen (output, "w");
     if (file == nullptr){
-      THROWF (system_error, 1, "Unable to open file (%s) for writing %s graph "
-          "configuration (uncategorized).", output, name);
+      THROWF (system_error, 1, "Unable to open file (%s) for writing %s graph configuration (uncategorized).",
+              output, name);
     }
 
-    if (brackets) fprintf (file, "{\n");
+    if (brackets)
+      fprintf (file, "{\n");
     uncat_configuration (file);
-    if (brackets) fprintf (file, "}\n");
+    if (brackets)
+      fprintf (file, "}\n");
     fclose (file);
   }
 }
@@ -624,19 +627,19 @@ static void generate_cat_configuration (const char *output, const char *name, in
   }
 }
 
-void TRACE_generate_viva_uncat_conf (void)
+void TRACE_generate_viva_uncat_conf ()
 {
   generate_uncat_configuration (TRACE_get_viva_uncat_conf (), "viva", 0);
 }
 
-void TRACE_generate_viva_cat_conf (void)
+void TRACE_generate_viva_cat_conf ()
 {
   generate_cat_configuration (TRACE_get_viva_cat_conf(), "viva", 0);
 }
 
 static int previous_trace_state = -1;
 
-void instr_pause_tracing (void)
+void instr_pause_tracing ()
 {
   previous_trace_state = trace_enabled;
   if (!TRACE_is_enabled()){
@@ -648,7 +651,7 @@ void instr_pause_tracing (void)
   XBT_DEBUG ("Tracing is paused.");
 }
 
-void instr_resume_tracing (void)
+void instr_resume_tracing ()
 {
   if (TRACE_is_enabled()){
     XBT_DEBUG ("Tracing is already running while trying to resume, therefore do nothing.");
index 4ab7004..7172f7e 100644 (file)
@@ -37,13 +37,12 @@ static void print_row() {
 static void print_timestamp(paje_event_t event) {
   stream << " ";
   /* prevent 0.0000 in the trace - this was the behavior before the transition to c++ */
-  if (event->timestamp == 0) 
+  if (event->timestamp < 1e-12)
     stream << 0;
   else 
     stream << event->timestamp;
 }
 
-
 template<typename T> static void print_default_pajeLink_row(paje_event_t& event) {
   init_stream<T>(event);
   print_timestamp(event);
@@ -76,7 +75,7 @@ template<typename T> static void print_default_pajeVariable_row(paje_event_t& ev
   print_row();
 }
 
-void TRACE_paje_init(void) {
+void TRACE_paje_init() {
   active_writer.print_DefineContainerType = print_pajeDefineContainerType;
   active_writer.print_DefineVariableType  = print_pajeDefineVariableType;
   active_writer.print_DefineStateType     = print_pajeDefineStateType;
@@ -97,7 +96,7 @@ void TRACE_paje_init(void) {
   active_writer.print_NewEvent            = print_pajeNewEvent;
 }
 
-void TRACE_paje_start(void) {
+void TRACE_paje_start() {
   char *filename = TRACE_get_filename();
   tracing_file = fopen(filename, "w");
   if (tracing_file == nullptr){
@@ -127,7 +126,7 @@ void TRACE_paje_start(void) {
   TRACE_header(TRACE_basic(),TRACE_display_sizes());
 }
 
-void TRACE_paje_end(void) {
+void TRACE_paje_end() {
   fclose(tracing_file);
   char *filename = TRACE_get_filename();
   XBT_DEBUG("Filename %s is closed", filename);
index 2fc18ea..1fd9e49 100644 (file)
 namespace simgrid {
 namespace mc {
 
-/** Process index used when no process is available
+/** Process index used when no process is available (SMPI privatization)
  *
  *  The expected behavior is that if a process index is needed it will fail.
  * */
 const int ProcessIndexMissing = -1;
 
-/** Process index used when we don't care about the process index
+/** Process index used when we don't care about the process index (SMPI privatization)
  * */
 const int ProcessIndexDisabled = -2;
 
-/** Constant used when any process will do.
+/** Constant used when any process will do (SMPI privatization)
  *
- *  This is is index of the first process.
+ *  Note: This is is index of the first process.
  */
 const int ProcessIndexAny = 0;
 
@@ -102,6 +102,10 @@ public:
  *  * the current state of an existing process;
  *
  *  * a snapshot.
+ *
+ *  In order to support SMPI privatization, the can read the memory from the
+ *  context of a given SMPI process: if specified, the code reads data from the
+ *  correct SMPI privatization VMA.
  */
 class AddressSpace {
 private:
@@ -110,12 +114,16 @@ public:
   AddressSpace(Process* process) : process_(process) {}
   virtual ~AddressSpace();
 
+  /** The process of this addres space
+   *
+   *  This is where we can get debug informations, memory layout, etc.
+   */
   simgrid::mc::Process* process() const { return process_; }
 
   /** Read data from the address space
    *
    *  @param buffer        target buffer for the data
-   *  @param size          number of bytes
+   *  @param size          number of bytes to read
    *  @param address       remote source address of the data
    *  @param process_index which process (used for SMPI privatization)
    *  @param options
@@ -137,7 +145,10 @@ public:
     this->read_bytes(buffer.getBuffer(), sizeof(T), ptr, process_index);
   }
 
-  /** Read a given data structure from the address space */
+  /** Read a given data structure from the addres space
+   *
+   *  This version returns by value.
+   */
   template<class T> inline
   Remote<T> read(RemotePtr<T> ptr, int process_index = ProcessIndexMissing) const
   {
@@ -146,13 +157,13 @@ public:
     return res;
   }
 
+  /** Read a string of known size */
   std::string read_string(RemotePtr<char> address, std::size_t len) const
   {
-    // TODO, use std::vector with .data() in C++17 to avoid useless copies
-    std::vector<char> buffer(len);
-    buffer[len] = '\0';
-    this->read_bytes(buffer.data(), len, address);
-    return std::string(buffer.data(), buffer.size());
+    std::string res;
+    res.resize(len);
+    this->read_bytes(&res[0], len, address);
+    return res;
   }
 
 };
index 64219c4..30e03c6 100644 (file)
@@ -18,8 +18,8 @@ namespace mc {
 
 /** A channel for exchanging messages between model-checker and model-checked
  *
- *  This hides the way the messages are transferred. Currently, they are sent
- *  over a SOCK_DGRAM socket.
+ *  This abstracts away the way the messages are transferred. Currently, they
+ *  are sent over a (connected) `SOCK_DGRAM` socket.
  */
 class Channel {
   int socket_ = -1;
index 70a9031..4575439 100644 (file)
@@ -20,13 +20,16 @@ namespace mc {
 
 /** A model-checking algorithm
  *
- *  The goal is to move the data/state/configuration of a model-checking
- *  algorithms in subclasses. Implementing this interface will probably
- *  not be really mandatory, you might be able to write your
- *  model-checking algorithm as plain imperative code instead.
+ *  This is an abstract base class used to group the data, state, configuration
+ *  of a model-checking algorithm.
  *
- *  It works by manipulating a model-checking Session.
- */
+ *  Implementing this interface will probably not be really mandatory,
+ *  you might be able to write your model-checking algorithm as plain
+ *  imperative code instead.
+ *
+ *  It is expected to interact with the model-checking core through the
+ * `Session` interface (but currently the `Session` interface does not
+ *  have all the necessary features). */
 // abstract
 class Checker {
   Session* session_;
@@ -38,16 +41,23 @@ public:
   Checker& operator=(Checker const&) = delete;
 
   virtual ~Checker();
+
+  /** Main function of this algorithm */
   virtual int run() = 0;
 
-  // Give me your internal state:
+  /* These methods are callbacks called by the model-checking engine
+   * to get and display information about the current state of the
+   * model-checking algorithm: */
 
   /** Show the current trace/stack
    *
-   *  Could this be handled in the Session/ModelChecker instead?
-   */
+   *  Could this be handled in the Session/ModelChecker instead? */
   virtual RecordTrace getRecordTrace();
+
+  /** Generate a textual execution trace of the simulated application */
   virtual std::vector<std::string> getTextualTrace();
+
+  /** Log additional information about the state of the model-checker */
   virtual void logState();
 
 protected:
index ae6efb1..076e607 100644 (file)
 namespace simgrid {
 namespace mc {
 
-/** A byte-string represented as a sequence of chunks from a PageStor */
+/** A byte-string represented as a sequence of chunks from a PageStore
+ *
+ *  In order to save memory when taking memory snapshots, a given byte-string
+ *  is split in fixed-size chunks. Identical chunks (either from the same
+ *  snapshot or more probably from different snpashots) share the same memory
+ *  storage.
+ *
+ *  Thus a chunked is represented as a sequence of indices of each chunk.
+ */
 class ChunkedData {
+  /** This is where we store the chunks */
   PageStore* store_ = nullptr;
-  /** Indices of the chunks */
+  /** Indices of the chunks in the `PageStore` */
   std::vector<std::size_t> pagenos_;
 public:
 
@@ -72,10 +81,16 @@ public:
     return *this;
   }
 
+  /** How many pages are used */
   std::size_t page_count()          const { return pagenos_.size(); }
+
+  /** Get a chunk index */
   std::size_t pageno(std::size_t i) const { return pagenos_[i]; }
+
+  /** Get a view of the chunk indices */
   const std::size_t* pagenos()      const { return pagenos_.data(); }
 
+  /** Get a a pointer to a chunk */
   const void* page(std::size_t i) const
   {
     return store_->get_page(pagenos_[i]);
index 4f16164..4b1f202 100644 (file)
@@ -19,9 +19,9 @@
 #include "src/mc/mc_forward.hpp"
 #include "src/mc/AddressSpace.hpp"
 
-/** @file DwarfExession.hpp
+/** @file DwarfExpression.hpp
  *
- *  Evaluation of DWARF location expressions
+ *  Evaluation of DWARF location expressions.
  */
 
 namespace simgrid {
@@ -30,7 +30,7 @@ namespace dwarf {
 /** A DWARF expression
  *
  *  DWARF defines a simple stack-based VM for evaluating expressions
- *  (such as locations of variables, etc.): A DWARF expressions is
+ *  (such as locations of variables, etc.): a DWARF expression is
  *  just a sequence of dwarf instructions. We currently directly use
  *  `Dwarf_Op` from `dwarf.h` for dwarf instructions.
  */
@@ -71,6 +71,7 @@ public:
   typedef std::uintptr_t value_type;
   static const std::size_t max_size = 64;
 private:
+  // Values of the stack (the top is stack_[size_ - 1]):
   uintptr_t stack_[max_size];
   size_t size_;
 public:
@@ -103,7 +104,7 @@ public:
   void push(value_type value)
   {
     if (size_ == max_size)
-      throw evaluation_error("Dwarf stack overflow");
+      throw evaluation_error("DWARF stack overflow");
     stack_[size_++] = value;
   }
 
@@ -111,7 +112,7 @@ public:
   value_type pop()
   {
     if (size_ == 0)
-      throw evaluation_error("Stack underflow");
+      throw evaluation_error("DWARF stack underflow");
     return stack_[--size_];
   }
 
index 40f9ed3..135b79c 100644 (file)
@@ -22,8 +22,8 @@ void* Frame::frame_base(unw_cursor_t& unw_cursor) const
     return location.address();
   else if (location.in_register()) {
     // This is a special case.
-    // The register if not the location of the frame base
-    // (a frame base cannot be located in a register)
+    // The register is not the location of the frame base
+    // (a frame base cannot be located in a register).
     // Instead, DWARF defines this to mean that the register
     // contains the address of the frame base.
     unw_word_t word;
index 52efb5b..830f024 100644 (file)
 namespace simgrid {
 namespace dwarf {
 
-/** \brief A DWARF expression with optional validity constraints */
+/** A DWARF expression with optional validity constraints */
 class LocationListEntry {
 public:
   typedef simgrid::xbt::Range<std::uint64_t> range_type;
 private:
   DwarfExpression expression_;
+  // By default, the expression is always valid:
   range_type range_ = {0, UINT64_MAX};
 public:
   LocationListEntry() {}
index 2023655..5d0e4af 100644 (file)
@@ -294,10 +294,10 @@ bool ModelChecker::handle_message(char* buffer, ssize_t size)
   return true;
 }
 
-/** Terminate the model-checker aplication */
+/** Terminate the model-checker application */
 void ModelChecker::exit(int status)
 {
-  // TODO, terminate the model checker politely instead of exiting rudel
+  // TODO, terminate the model checker politely instead of exiting rudely
   if (process().running())
     kill(process().pid(), SIGKILL);
   ::exit(status);
index 59280f9..96835b8 100644 (file)
 namespace simgrid {
 namespace mc {
 
-ObjectInformation::ObjectInformation()
-{
-  this->flags = 0;
-  this->start = nullptr;
-  this->end = nullptr;
-  this->start_exec = nullptr;
-  this->end_exec = nullptr;
-  this->start_rw = nullptr;
-  this->end_rw = nullptr;
-  this->start_ro = nullptr;
-  this->end_ro = nullptr;
-}
+ObjectInformation::ObjectInformation() {}
 
-/** Find the DWARF offset for this ELF object
- *
- *  An offset is applied to address found in DWARF:
- *
- *  * for an executable object, addresses are virtual address
- *    (there is no offset) i.e.
- *    \f$\text{virtual address} = \{dwarf address}\f$;
+/* For an executable object, addresses are virtual address
+ * (there is no offset) i.e.
+ * \f$\text{virtual address} = \{dwarf address}\f$;
  *
- *  * for a shared object, the addreses are offset from the begining
- *    of the shared object (the base address of the mapped shared
- *    object must be used as offset
- *    i.e. \f$\text{virtual address} = \text{shared object base address}
+ * For a shared object, the addreses are offset from the begining
+ * of the shared object (the base address of the mapped shared
+ * object must be used as offset
+ * i.e. \f$\text{virtual address} = \text{shared object base address}
  *             + \text{dwarf address}\f$.
  */
 void *ObjectInformation::base_address() const
 {
+  // For an executable (more precisely for a ET_EXEC) the base it 0:
   if (this->executable())
     return nullptr;
 
+  // For an a shared-object (ET_DYN, including position-independant executables)
+  // the base address is its lowest address:
   void *result = this->start_exec;
   if (this->start_rw != nullptr && result > (void *) this->start_rw)
     result = this->start_rw;
@@ -55,7 +43,6 @@ void *ObjectInformation::base_address() const
   return result;
 }
 
-/* Find a function by instruction pointer */
 simgrid::mc::Frame* ObjectInformation::find_function(const void *ip) const
 {
   /* This is implemented by binary search on a sorted array.
@@ -146,16 +133,16 @@ void ObjectInformation::remove_global_variable(const char* name)
   }
 }
 
-/** \brief Ignore a local variable in a scope
+/** Ignore a local variable in a scope
  *
  *  Ignore all instances of variables with a given name in
  *  any (possibly inlined) subprogram with a given namespaced
  *  name.
  *
- *  \param var_name        Name of the local variable (or parameter to ignore)
- *  \param subprogram_name Name of the subprogram to ignore (nullptr for any)
- *  \param subprogram      (possibly inlined) Subprogram of the scope
- *  \param scope           Current scope
+ *  @param var_name        Name of the local variable to ignore
+ *  @param subprogram_name Name of the subprogram to ignore (nullptr for any)
+ *  @param subprogram      (possibly inlined) Subprogram of the scope current scope
+ *  @param scope           Current scope
  */
 static void remove_local_variable(simgrid::mc::Frame& scope,
                             const char *var_name,
index 9a55d87..e65d9d3 100644 (file)
@@ -33,23 +33,23 @@ struct FunctionIndexEntry {
   simgrid::mc::Frame* function;
 };
 
-/** Information about an (ELF) executable/sharedobject
+/** Information about an ELF module (executable or shared object)
+ *
+ *  This contains all the information we need about an executable or
+ *  shared-object in the model-checked process:
  *
- *  This contain sall the information we have at runtime about an
- *  executable/shared object in the target (modelchecked) process:
  *  - where it is located in the virtual address space;
- *  - where are located it's different memory mapping in the the
- *    virtual address space ;
- *  - all the debugging (DWARF) information,
- *    - location of the functions,
- *    - types
- *  - etc.
  *
- *  It is not copyable because we are taking pointers to Types/Frames.
- *  We'd have to update/rebuild some data structures in order to copy
- *  successfully.
+ *  - where are located its different memory mappings in the the
+ *    virtual address space;
+ *
+ *  - all the debugging (DWARF) information
+ *    - types,
+ *    - location of the functions and their local variables,
+ *    - global variables,
+ *
+ *  - etc.
  */
-
 class ObjectInformation {
 public:
   ObjectInformation();
@@ -62,45 +62,109 @@ public:
   static const int Executable = 1;
 
   /** Bitfield of flags */
-  int flags;
+  int flags = 0;
   std::string file_name;
-  const void* start;
-  const void *end;
-  char *start_exec;
-  char *end_exec; // Executable segment
-  char *start_rw;
-  char *end_rw; // Read-write segment
-  char *start_ro;
-  char *end_ro; // read-only segment
+  const void* start = nullptr;
+  const void *end = nullptr;
+  // Location of its text segment:
+  char *start_exec = nullptr;
+  char *end_exec = nullptr;
+  // Location of the read-only part of its data segment:
+  char *start_rw = nullptr;
+  char *end_rw = nullptr;
+  // Location of the read/write part of its data segment:
+  char *start_ro = nullptr;
+  char *end_ro = nullptr;
+
+  /** All of its subprograms indexed by their address */
   std::unordered_map<std::uint64_t, simgrid::mc::Frame> subprograms;
+
+  /** Index of functions by instruction address
+   *
+   * We need to efficiently find the function from any given instruction
+   * address inside its range. This index is sorted by low_pc
+   * 
+   * The entries are sorted by low_pc and a binary search can be used to look
+   * them up. In order to have a better cache locality, we only keep the
+   * information we need for the lookup in this vector. We could probably
+   * replace subprograms by an ordered vector of Frame and replace this one b
+   * a parallel `std::vector<void*>`.
+   */
+  std::vector<FunctionIndexEntry> functions_index;
+
   // TODO, remove the mutable (to remove it we'll have to add a lot of const everywhere)
   mutable std::vector<simgrid::mc::Variable> global_variables;
+
+  /** Types indexed by DWARF ID */
   std::unordered_map<std::uint64_t, simgrid::mc::Type> types;
-  std::unordered_map<std::string, simgrid::mc::Type*> full_types_by_name;
 
-  /** Index of functions by IP
+  /** Types indexed by name
    *
-   * The entries are sorted by low_pc and a binary search can be used to look
-   * them up. Should we used a binary tree instead?
+   *  Different compilation units have their separate type definitions
+   *  (for the same type). When we find an opaque type in one compilation unit,
+   *  we use this in order to try to find its definition in another compilation
+   *  unit.
    */
-  std::vector<FunctionIndexEntry> functions_index;
+  std::unordered_map<std::string, simgrid::mc::Type*> full_types_by_name;
 
+  /** Whether this module is an executable
+   *
+   *  More precisely we check if this is an ET_EXE ELF. These ELF files
+   *  use fixed addresses instead of base-addres relative addresses.
+   *  Position independant executables are in fact ET_DYN.
+   */
   bool executable() const
   {
     return this->flags & simgrid::mc::ObjectInformation::Executable;
   }
 
+  /** Base address of the module
+   *
+   *  All the location information in ELF and DWARF are expressed as an offsets
+   *  from this base address:
+   *
+   *  - location of the functions and globale variables;
+   *
+   *  - the DWARF instruction `OP_addr` pushes this on the DWARF stack.
+   **/
   void* base_address() const;
 
+  /** Find a function by instruction address
+   *
+   *  @param ip instruction address
+   *  @return corresponding function (if any) or nullptr
+   */
   simgrid::mc::Frame* find_function(const void *ip) const;
+
+  /** Find a global variable by name
+   *
+   *  This is used to ignore global variables and to find well-known variables
+   *  (`__mmalloc_default_mdp`).
+   *
+   *  @param name scopes name of the global variable (`myproject::Foo::count`)
+   *  @return corresponding variable (if any) or nullptr
+   */
   simgrid::mc::Variable* find_variable(const char* name) const;
+
+  /** Remove a global variable (in order to ignore it)
+   *
+   *  This is used to ignore a global variable for the snapshot comparison.
+   */
   void remove_global_variable(const char* name);
+
+  /** Remove a loval variables (in order to ignore it)
+   *
+   *  @param name Name of the globale variable
+   *  @param scope Namespaceed name of the function (or null for all functions)
+   */
   void remove_local_variable(
     const char* name, const char* scope);
 };
 
 XBT_PRIVATE std::shared_ptr<ObjectInformation> createObjectInformation(
   std::vector<simgrid::xbt::VmMap> const& maps, const char* name);
+
+/** Augment the current module with informations about the other ones */
 XBT_PRIVATE void postProcessObjectInformation(
   simgrid::mc::Process* process, simgrid::mc::ObjectInformation* info);
 
index 5c11ddc..e69af01 100644 (file)
 namespace simgrid {
 namespace mc {
 
-template<class M, class T, class Enable = void>
-struct pointer_to_data_member {};
-template<class M, class T>
-struct pointer_to_data_member<M,T,typename std::enable_if< std::is_union<M>::value || std::is_class<M>::value >::type> {
-  typedef T M::* type;
-};
-
-template<class M, class T>
-using pointer_to_data_member_t = typename pointer_to_data_member<M,T>::type;
-
 /** HACK, A value from another process
  *
  *  This represents a value from another process:
index ff6cef6..260edd4 100644 (file)
@@ -165,10 +165,10 @@ Session* Session::spawnv(const char *path, char *const argv[])
 }
 
 // static
-Session* Session::spawnvp(const char *path, char *const argv[])
+Session* Session::spawnvp(const char *file, char *const argv[])
 {
   return Session::fork([&] {
-    execvp(path, argv);
+    execvp(file, argv);
   });
 }
 
index 11afeda..7af4c43 100644 (file)
@@ -60,16 +60,27 @@ public:
 public: // static constructors
 
   /** Create a new session by forking
+   *
+   *  This sets up the environment for the model-checked process
+   *  (environoment variables, sockets, etc.).
    *
    *  The code is expected to `exec` the model-checker program.
    */
   static Session* fork(std::function<void(void)> code);
 
-  /** Create a session using `execv` */
+  /** Spawn a model-checked process
+   *
+   *  @param path full path of the executable
+   *  @param argv arguments for the model-checked process (NULL-terminated)
+   */
   static Session* spawnv(const char *path, char *const argv[]);
 
-  /** Create a session using `execvp` */
-  static Session* spawnvp(const char *path, char *const argv[]);
+  /** Spawn a model-checked process (using PATH)
+   *
+   *  @param file file name of the executable (found using `PATH`)
+   *  @param argv arguments for the model-checked process (NULL-terminated)
+   */
+  static Session* spawnvp(const char *file, char *const argv[]);
 };
 
 // Temporary
index d619a96..3d08678 100644 (file)
@@ -1044,6 +1044,9 @@ void read_dwarf_info(simgrid::mc::ObjectInformation* info, Dwarf* dwarf)
 static
 std::vector<char> get_build_id(Elf* elf)
 {
+  // Summary: the GNU build ID is stored in a ("GNU, NT_GNU_BUILD_ID) note
+  // found in a PT_NOTE entry in the program header table.
+
   size_t phnum;
   if (elf_getphdrnum (elf, &phnum) != 0)
     xbt_die("Could not read program headers");
@@ -1059,22 +1062,21 @@ std::vector<char> get_build_id(Elf* elf)
 
     // Iterate over the notes and find the NT_GNU_BUILD_ID one:
     size_t pos = 0;
-    while (1) {
+    while (pos < data->d_size) {
       GElf_Nhdr nhdr;
+      // Location of the name within Elf_Data:
       size_t name_pos;
       size_t desc_pos;
       pos = gelf_getnote(data, pos, &nhdr, &name_pos, &desc_pos);
-      // A note is identified by a name "GNU" and a integer type within
-      // the namespace defined by this name (here NT_GNU_BUILD_ID):
+      // A build ID note is identified by the pair ("GNU", NT_GNU_BUILD_ID)
+      // (a namespace and a type within this namespace):
       if (nhdr.n_type == NT_GNU_BUILD_ID
           && nhdr.n_namesz == sizeof("GNU")
           && memcmp((char*) data->d_buf + name_pos, "GNU", sizeof("GNU")) == 0) {
-
-        // Found the NT_GNU_BUILD_ID note:
+        XBT_DEBUG("Found GNU/NT_GNU_BUILD_ID note");
         char* start = (char*) data->d_buf + desc_pos;
         char* end = (char*) start + nhdr.n_descsz;
         return std::vector<char>(start, end);
-
       }
     }
 
@@ -1129,18 +1131,25 @@ const char* debug_paths[] = {
  *  This is one of the mechanisms used for
  *  [separate debug files](https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html).
  */
+// Example:
+// /usr/lib/debug/.build-id/0b/dc77f1c29aea2b14ff5acd9a19ab3175ffdeae.debug
 static
 std::string find_by_build_id(std::vector<char> id)
 {
   std::string filename;
+  std::string hex = to_hex(id);
   for (const char* debug_path : debug_paths) {
-    filename = debug_path;
-    filename += ".build-id/" + to_hex(id.data(), 1) + '/'
+    // Example:
+    filename = std::string(debug_path) + ".build-id/"
+      + to_hex(id.data(), 1) + '/'
       + to_hex(id.data() + 1, id.size() - 1) + ".debug";
     XBT_DEBUG("Checking debug file: %s", filename.c_str());
-    if (access(filename.c_str(), F_OK) == 0)
+    if (access(filename.c_str(), F_OK) == 0) {
+      XBT_DEBUG("Found debug file: %s\n", hex.c_str());
       return filename;
+    }
   }
+  XBT_DEBUG("Not debuf info found for build ID %s\n", hex.data());
   return std::string();
 }
 
@@ -1150,7 +1159,7 @@ std::string find_by_build_id(std::vector<char> id)
  *  lists of types, variables, functions.
  */
 static
-void MC_dwarf_get_variables(simgrid::mc::ObjectInformation* info)
+void MC_load_dwarf(simgrid::mc::ObjectInformation* info)
 {
   if (elf_version(EV_CURRENT) == EV_NONE)
     xbt_die("libelf initialization error");
@@ -1161,12 +1170,12 @@ void MC_dwarf_get_variables(simgrid::mc::ObjectInformation* info)
     xbt_die("Could not open file %s", info->file_name.c_str());
   Elf* elf = elf_begin(fd, ELF_C_READ, nullptr);
   if (elf == nullptr)
-    xbt_die("Not an ELF file 1");
+    xbt_die("Not an ELF file");
   Elf_Kind kind = elf_kind(elf);
   if (kind != ELF_K_ELF)
-    xbt_die("Not an ELF file 2");
+    xbt_die("Not an ELF file");
 
-  // Remember if this is a `ET_EXEC` (fixed location) or `ET_DYN` (relocatable):
+  // Remember if this is a `ET_EXEC` (fixed location) or `ET_DYN`:
   Elf64_Half type = get_type(elf);
   if (type == ET_EXEC)
     info->flags |= simgrid::mc::ObjectInformation::Executable;
@@ -1182,8 +1191,15 @@ void MC_dwarf_get_variables(simgrid::mc::ObjectInformation* info)
   }
   dwarf_end(dwarf);
 
-  // If there was no DWARF in the file, try to find it in a separate file
-  // with NT_GNU_BUILD_ID:
+  // If there was no DWARF in the file, try to find it in a separate file.
+  // Different methods might be used to store the DWARF informations:
+  //  * GNU NT_GNU_BUILD_ID;
+  //  * .gnu_debuglink.
+  // See https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html
+  // for reference of what we are doing.
+
+  // Try with NT_GNU_BUILD_ID: we find the build ID in the ELF file and then
+  // use this ID to find the file in some known locations in the filesystem.
   std::vector<char> build_id = get_build_id(elf);
   if (!build_id.empty()) {
     elf_end(elf);
@@ -1193,8 +1209,7 @@ void MC_dwarf_get_variables(simgrid::mc::ObjectInformation* info)
     std::string debug_file = find_by_build_id(build_id);
     if (debug_file.empty()) {
       std::string hex = to_hex(build_id);
-      xbt_die(
-        "Missing debug info for %s with build-id %s\n"
+      xbt_die("Missing debug info for %s with build-id %s\n"
         "You might want to install the suitable debugging package.\n",
         info->file_name.c_str(), hex.c_str());
     }
@@ -1215,9 +1230,10 @@ void MC_dwarf_get_variables(simgrid::mc::ObjectInformation* info)
     return;
   }
 
-  // TODO, try to find DWARF info using debug-link.
-  // Is this method really used anywhere?
+  // TODO, try to find DWARF info using .gnu_debuglink.
 
+  elf_end(elf);
+  close(fd);
   xbt_die("Debugging information not found for %s\n"
     "Try recompiling with -g\n",
     info->file_name.c_str());
@@ -1343,7 +1359,7 @@ std::shared_ptr<simgrid::mc::ObjectInformation> createObjectInformation(
     std::make_shared<simgrid::mc::ObjectInformation>();
   result->file_name = name;
   simgrid::mc::find_object_address(maps, result.get());
-  MC_dwarf_get_variables(result.get());
+  MC_load_dwarf(result.get());
   MC_post_process_variables(result.get());
   MC_post_process_types(result.get());
   for (auto& entry : result.get()->subprograms)
index 7901b67..ec24b70 100644 (file)
@@ -4,7 +4,8 @@
 /* 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. */
 
-/** \file
+/** \file mc_record.h
+ *
  *  This file contains the MC replay/record functionnality.
  *  A MC path may be recorded by using ``-cfg=model-check/record:1`'`.
  *  The path is written in the log output and an be replayed with MC disabled
index d92703c..f9324c8 100644 (file)
@@ -4,8 +4,6 @@
 /* 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. */
 
-/* simgrid/modelchecker.h - Formal Verification made possible in SimGrid    */
-
 #ifndef SIMGRID_MC_REPLAY_H
 #define SIMGRID_MC_REPLAY_H
 
index cf8a8bf..1feb6e8 100644 (file)
@@ -375,8 +375,7 @@ std::string simgrid::mc::request_to_string(smx_simcall_t req, int value, simgrid
       type = "TestAny";
       args =
           bprintf("(%d of %zu)", value + 1,
-                  read_length(mc_model_checker->process(),
-                    simcall_comm_testany__get__comms(req)));
+                    simcall_comm_testany__get__count(req));
     }
     break;
 
@@ -451,12 +450,9 @@ bool request_is_enabled_by_idx(smx_simcall_t req, unsigned int idx)
     }
     break;
 
-  case SIMCALL_COMM_TESTANY: {
-    read_element(
-      mc_model_checker->process(), &remote_act,
-      remote(simcall_comm_testany__get__comms(req)),
-      idx, sizeof(remote_act));
-    }
+  case SIMCALL_COMM_TESTANY:
+    remote_act = mc_model_checker->process().read(remote(
+      simcall_comm_testany__get__comms(req) + idx));
     break;
 
   default:
@@ -601,12 +597,12 @@ std::string request_get_dot_output(smx_simcall_t req, int value)
         label = simgrid::xbt::string_printf("[(%lu)%s] TestAny TRUE [%d of %lu]",
                     issuer->pid,
                     MC_smx_process_get_host_name(issuer), value + 1,
-                    xbt_dynar_length(simcall_comm_testany__get__comms(req)));
+                    simcall_comm_testany__get__count(req));
       else
         label = simgrid::xbt::string_printf("[(%lu)] TestAny TRUE [%d of %lu]",
                     issuer->pid,
                     value + 1,
-                    xbt_dynar_length(simcall_comm_testany__get__comms(req)));
+                    simcall_comm_testany__get__count(req));
     }
     break;
 
index a919c30..59a9de0 100644 (file)
@@ -106,8 +106,7 @@ static inline smx_simcall_t MC_state_get_request_for_process(
         unsigned start_count = procstate->interleave_count;
         state->transition.argument = -1;
         while (procstate->interleave_count <
-                read_length(mc_model_checker->process(),
-                  remote(simcall_comm_testany__get__comms(&process->simcall))))
+                simcall_comm_testany__get__count(&process->simcall))
           if (simgrid::mc::request_is_enabled_by_idx(&process->simcall,
               procstate->interleave_count++)) {
             state->transition.argument = procstate->interleave_count - 1;
@@ -115,8 +114,7 @@ static inline smx_simcall_t MC_state_get_request_for_process(
           }
 
         if (procstate->interleave_count >=
-            read_length(mc_model_checker->process(),
-              remote(simcall_comm_testany__get__comms(&process->simcall))))
+            simcall_comm_testany__get__count(&process->simcall))
           procstate->setDone();
 
         if (state->transition.argument != -1 || start_count == 0)
@@ -191,10 +189,8 @@ static inline smx_simcall_t MC_state_get_request_for_process(
     state->internal_req.issuer = req->issuer;
 
     if (state->transition.argument > 0) {
-      smx_synchro_t remote_comm;
-      read_element(mc_model_checker->process(),
-        &remote_comm, remote(simcall_comm_testany__get__comms(req)),
-        state->transition.argument, sizeof(remote_comm));
+      smx_synchro_t remote_comm = mc_model_checker->process().read(
+        remote(simcall_comm_testany__get__comms(req) + state->transition.argument));
       mc_model_checker->process().read(state->internal_comm, remote(
         static_cast<simgrid::simix::Comm*>(remote_comm)));
     }
index 9e0378e..4e12c2c 100644 (file)
@@ -282,27 +282,25 @@ static inline msg_comm_t MSG_task_isend_internal(msg_task_t task, const char *al
                                                      void *match_data, void_f_pvoid_t cleanup, int detached)
 {
   simdata_task_t t_simdata = nullptr;
-  msg_process_t process = MSG_process_self();
+  msg_process_t myself = SIMIX_process_self();
   msg_mailbox_t mailbox = MSG_mailbox_get_by_alias(alias);
   int call_end = TRACE_msg_task_put_start(task);
 
   /* Prepare the task to send */
   t_simdata = task->simdata;
-  t_simdata->sender = process;
+  t_simdata->sender = myself;
   t_simdata->source = ((simdata_process_t) SIMIX_process_self_get_data())->m_host;
   t_simdata->setUsed();
   t_simdata->comm = nullptr;
   msg_global->sent_msg++;
 
   /* Send it by calling SIMIX network layer */
-  smx_synchro_t act = simcall_comm_isend(SIMIX_process_self(), mailbox, t_simdata->bytes_amount, t_simdata->rate,
+  smx_synchro_t act = simcall_comm_isend(myself, mailbox, t_simdata->bytes_amount, t_simdata->rate,
                                          task, sizeof(void *), match_fun, cleanup, nullptr, match_data,detached);
-  t_simdata->comm = static_cast<simgrid::simix::Comm*>(act); /* FIXME: is the field t_simdata->comm still useful? */
+  t_simdata->comm = static_cast<simgrid::simix::Comm*>(act);
 
-  msg_comm_t comm;
-  if (detached) {
-    comm = nullptr;
-  } else {
+  msg_comm_t comm = nullptr;
+  if (! detached) {
     comm = xbt_new0(s_msg_comm_t, 1);
     comm->task_sent = task;
     comm->task_received = nullptr;
@@ -504,17 +502,18 @@ int MSG_comm_testany(xbt_dynar_t comms)
 {
   int finished_index = -1;
 
-  /* create the equivalent dynar with SIMIX objects */
-  xbt_dynar_t s_comms = xbt_dynar_new(sizeof(smx_synchro_t), nullptr);
+  /* Create the equivalent array with SIMIX objects: */
+  std::vector<simgrid::simix::Synchro*> s_comms;
+  s_comms.reserve(xbt_dynar_length(comms));
   msg_comm_t comm;
   unsigned int cursor;
   xbt_dynar_foreach(comms, cursor, comm) {
-    xbt_dynar_push(s_comms, &comm->s_comm);
+    s_comms.push_back(comm->s_comm);
   }
 
   msg_error_t status = MSG_OK;
   try {
-    finished_index = simcall_comm_testany(s_comms);
+    finished_index = simcall_comm_testany(s_comms.data(), s_comms.size());
   }
   catch (xbt_ex& e) {
     switch (e.category) {
@@ -530,7 +529,6 @@ int MSG_comm_testany(xbt_dynar_t comms)
         throw;
     }
   }
-  xbt_dynar_free(&s_comms);
 
   if (finished_index != -1) {
     comm = xbt_dynar_get_as(comms, finished_index, msg_comm_t);
@@ -627,7 +625,7 @@ int MSG_comm_waitany(xbt_dynar_t comms)
 
   msg_error_t status = MSG_OK;
   try {
-    finished_index = simcall_comm_waitany(s_comms);
+    finished_index = simcall_comm_waitany(s_comms, -1);
   }
   catch(xbt_ex& e) {
     switch (e.category) {
@@ -853,12 +851,13 @@ int MSG_task_listen(const char *alias)
  */
 int MSG_task_listen_from(const char *alias)
 {
-  msg_task_t task;
+  msg_mailbox_t mbox = MSG_mailbox_get_by_alias(alias);
+  simgrid::simix::Comm* comm = static_cast<simgrid::simix::Comm*>(simcall_mbox_front(mbox));
 
-  if (nullptr == (task = MSG_mailbox_front(MSG_mailbox_get_by_alias(alias))))
+  if (!comm)
     return -1;
 
-  return MSG_process_get_PID(task->simdata->sender);
+  return MSG_process_get_PID( static_cast<msg_task_t>(comm->src_data)->simdata->sender );
 }
 
 /** \ingroup msg_task_usage
index 4b0c1ce..3a2037d 100644 (file)
@@ -94,6 +94,9 @@ sg_size_t MSG_file_read(msg_file_t fd, sg_size_t size)
   msg_file_priv_t file_priv = MSG_file_priv(fd);
   sg_size_t read_size;
 
+  if (file_priv->size == 0) /* Nothing to read, return */
+    return 0;
+
   /* Find the host where the file is physically located and read it */
   msg_storage_t storage_src =(msg_storage_t) xbt_lib_get_elm_or_null(storage_lib, file_priv->storageId);
   msg_storage_priv_t storage_priv_src = MSG_storage_priv(storage_src);
@@ -108,7 +111,7 @@ sg_size_t MSG_file_read(msg_file_t fd, sg_size_t size)
 
     m_host_list[0] = MSG_host_self();
     m_host_list[1] = attached_host;
-    double flops_amount[] = { 0, 0 };
+    double flops_amount[] = { 0, 0};
     double bytes_amount[] = { 0, 0, (double)read_size, 0 };
 
     msg_task_t task = MSG_parallel_task_create("file transfer for read", 2, m_host_list, flops_amount, bytes_amount,
@@ -139,6 +142,9 @@ sg_size_t MSG_file_write(msg_file_t fd, sg_size_t size)
 {
   msg_file_priv_t file_priv = MSG_file_priv(fd);
 
+  if (size == 0) /* Nothing to write, return */
+    return 0;
+
   /* Find the host where the file is physically located (remote or local)*/
   msg_storage_t storage_src =(msg_storage_t) xbt_lib_get_elm_or_null(storage_lib, file_priv->storageId);
   msg_storage_priv_t storage_priv_src = MSG_storage_priv(storage_src);
index 470b4c6..6f5528b 100644 (file)
 
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(msg_mailbox, msg, "Logging specific to MSG (mailbox)");
 
-msg_mailbox_t MSG_mailbox_new(const char *alias)
-{
-  return simcall_mbox_create(alias);
-}
-
 int MSG_mailbox_is_empty(msg_mailbox_t mailbox)
 {
   return (nullptr == simcall_mbox_front(mailbox));
@@ -38,7 +33,7 @@ msg_mailbox_t MSG_mailbox_get_by_alias(const char *alias)
   msg_mailbox_t mailbox = simcall_mbox_get_by_name(alias);
 
   if (!mailbox)
-    mailbox = MSG_mailbox_new(alias);
+    mailbox = simcall_mbox_create(alias);
 
   return mailbox;
 }
@@ -56,7 +51,7 @@ void MSG_mailbox_set_async(const char *alias){
   msg_mailbox_t mailbox = MSG_mailbox_get_by_alias(alias);
 
   simcall_mbox_set_receiver(mailbox, SIMIX_process_self());
-  XBT_VERB("%s mailbox set to receive eagerly for process %p\n",alias, SIMIX_process_self());
+  XBT_VERB("%s mailbox set to receive eagerly for myself\n",alias);
 }
 
 /** \ingroup msg_mailbox_management
index ff5d328..fa46da9 100644 (file)
@@ -46,8 +46,8 @@ void MSG_sem_release(msg_sem_t sem) {
   simcall_sem_release(sem);
 }
 
-void MSG_sem_get_capacity(msg_sem_t sem) {
-  simcall_sem_get_capacity(sem);
+int MSG_sem_get_capacity(msg_sem_t sem) {
+  return simcall_sem_get_capacity(sem);
 }
 
 void MSG_sem_destroy(msg_sem_t sem) {
index a19d803..dee4345 100644 (file)
@@ -161,7 +161,7 @@ void MSG_task_set_copy_callback(void (*callback) (msg_task_t task, msg_process_t
 msg_process_t MSG_task_get_sender(msg_task_t task)
 {
   xbt_assert(task, "Invalid parameters");
-  return ((simdata_task_t) task->simdata)->sender;
+  return (static_cast<simdata_task_t> (task->simdata)->sender);
 }
 
 /** \ingroup m_task_management
@@ -172,7 +172,7 @@ msg_process_t MSG_task_get_sender(msg_task_t task)
 msg_host_t MSG_task_get_source(msg_task_t task)
 {
   xbt_assert(task, "Invalid parameters");
-  return ((simdata_task_t) task->simdata)->source;
+  return (static_cast<simdata_task_t> (task->simdata)->source);
 }
 
 /** \ingroup m_task_management
@@ -326,7 +326,7 @@ void MSG_task_set_bound(msg_task_t task, double bound)
   xbt_assert(task, "Invalid parameter");
   xbt_assert(task->simdata, "Invalid parameter");
 
-  if (bound == 0)
+  if (bound < 1e-12) /* close enough to 0 without any floating precision surprise */
     XBT_INFO("bound == 0 means no capping (i.e., unlimited).");
 
   task->simdata->bound = bound;
@@ -390,24 +390,19 @@ void MSG_task_set_affinity(msg_task_t task, msg_host_t host, unsigned long mask)
     return;
   }
 
-  {
-    simgrid::simix::Exec *compute = task->simdata->compute;
-    msg_host_t host_now = compute->host;  // simix_private.h is necessary
-    if (host_now != host) {
-      /* task is not yet executed on this host */
-      XBT_INFO("set affinity(0x%04lx@%s) for %s (not active now)", mask, MSG_host_get_name(host),
-               MSG_task_get_name(task));
-      return;
-    }
-
-    /* task is being executed on this host. so change the affinity now */
-    {
-      /* check it works. remove me if it works. */
-      xbt_assert((unsigned long)(uintptr_t) xbt_dict_get_or_null_ext(task->simdata->affinity_mask_db,
-                 (char *) host, sizeof(msg_host_t)) == mask);
-    }
-
-    XBT_INFO("set affinity(0x%04lx@%s) for %s", mask, MSG_host_get_name(host), MSG_task_get_name(task));
-    simcall_execution_set_affinity(task->simdata->compute, host, mask);
+  simgrid::simix::Exec *compute = task->simdata->compute;
+  msg_host_t host_now = compute->host;  // simix_private.h is necessary
+  if (host_now != host) {
+    /* task is not yet executed on this host */
+    XBT_INFO("set affinity(0x%04lx@%s) for %s (not active now)", mask, MSG_host_get_name(host),
+             MSG_task_get_name(task));
+    return;
   }
+
+  /* task is being executed on this host. so change the affinity now */
+  /* check it works. remove me if it works. */
+  xbt_assert(static_cast<unsigned long>((uintptr_t) xbt_dict_get_or_null_ext(task->simdata->affinity_mask_db,
+             (char*)(host), sizeof(msg_host_t))) == mask);
+  XBT_INFO("set affinity(0x%04lx@%s) for %s", mask, MSG_host_get_name(host), MSG_task_get_name(task));
+  simcall_execution_set_affinity(task->simdata->compute, host, mask);
 }
index c341322..0589041 100644 (file)
@@ -669,7 +669,7 @@ static int migration_tx_fun(int argc, char *argv[])
   if (ramsize == 0)
     XBT_WARN("migrate a VM, but ramsize is zero");
 
-  if (max_downtime == 0) {
+  if (max_downtime <= 0) {
     XBT_WARN("use the default max_downtime value 30ms");
     max_downtime = 0.03;
   }
similarity index 99%
rename from src/surf/AsCluster.cpp
rename to src/routing/AsCluster.cpp
index 100ff55..b885a6d 100644 (file)
@@ -3,7 +3,7 @@
 /* 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 "src/surf/AsCluster.hpp"
+#include "src/routing/AsCluster.hpp"
 #include "src/surf/network_interface.hpp"
 
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_route_cluster, surf, "Routing part of surf");
similarity index 97%
rename from src/surf/AsCluster.hpp
rename to src/routing/AsCluster.hpp
index 3e0493b..803524d 100644 (file)
@@ -6,7 +6,7 @@
 #ifndef SIMGRID_ROUTING_CLUSTER_HPP_
 #define SIMGRID_ROUTING_CLUSTER_HPP_
 
-#include "src/surf/AsImpl.hpp"
+#include "src/routing/AsImpl.hpp"
 
 namespace simgrid {
 namespace routing {
similarity index 83%
rename from src/surf/AsClusterDragonfly.cpp
rename to src/routing/AsClusterDragonfly.cpp
index e3eff8c..2c9453e 100644 (file)
@@ -3,7 +3,7 @@
 /* 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 "src/surf/AsClusterDragonfly.hpp"
+#include "src/routing/AsClusterDragonfly.hpp"
 #include "src/surf/network_interface.hpp"
 #include "src/surf/xml/platf.hpp" // FIXME: move that back to the parsing area
 
@@ -12,8 +12,6 @@
 
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_route_cluster_dragonfly, surf_route_cluster, "Dragonfly Routing part of surf");
 
-
-
 namespace simgrid {
 namespace routing {
 
@@ -22,10 +20,8 @@ AsClusterDragonfly::AsClusterDragonfly(const char*name)
 }
 
 AsClusterDragonfly::~AsClusterDragonfly() {
-
-  if(this->routers_!=nullptr){
-    unsigned int i;
-    for (i=0; i<this->numGroups_*this->numChassisPerGroup_*this->numBladesPerChassis_;i++)
+  if(this->routers_ != nullptr){
+    for (unsigned int i=0; i<this->numGroups_*this->numChassisPerGroup_*this->numBladesPerChassis_;i++)
         delete(routers_[i]);
     xbt_free(routers_);
   }
@@ -33,7 +29,6 @@ AsClusterDragonfly::~AsClusterDragonfly() {
 
 unsigned int *AsClusterDragonfly::rankId_to_coords(int rankId)
 {
-
   //coords : group, chassis, blade, node
   unsigned int *coords = (unsigned int *) malloc(4 * sizeof(unsigned int));
   coords[0] = rankId/ (numChassisPerGroup_*numBladesPerChassis_*numNodesPerBlade_);
@@ -42,7 +37,7 @@ unsigned int *AsClusterDragonfly::rankId_to_coords(int rankId)
   rankId=rankId%(numBladesPerChassis_*numNodesPerBlade_);
   coords[2] = rankId/ numNodesPerBlade_;
   coords[3]=rankId%numNodesPerBlade_;
-  
+
   return coords;
 }
 
@@ -102,11 +97,7 @@ void AsClusterDragonfly::seal(){
   this->generateLinks();
 }
 
-DragonflyRouter::DragonflyRouter(int group, int chassis, int blade){
-    this->group_=group;
-    this->chassis_=chassis;
-    this->blade_=blade;
-}
+DragonflyRouter::DragonflyRouter(int group, int chassis, int blade):group_(group),chassis_(chassis),blade_(blade){ }
 
 DragonflyRouter::~DragonflyRouter(){
   if(this->myNodes_!=nullptr)
@@ -121,23 +112,18 @@ DragonflyRouter::~DragonflyRouter(){
 
 
 void AsClusterDragonfly::generateRouters() {
+  this->routers_=static_cast<DragonflyRouter**>(xbt_malloc0(this->numGroups_*this->numChassisPerGroup_*this->numBladesPerChassis_*sizeof(DragonflyRouter*)));
 
-unsigned int i, j, k;
-
-this->routers_=(DragonflyRouter**)xbt_malloc0(this->numGroups_*this->numChassisPerGroup_*this->numBladesPerChassis_*sizeof(DragonflyRouter*));
-
-for(i=0;i<this->numGroups_;i++){
-  for(j=0;j<this->numChassisPerGroup_;j++){
-    for(k=0;k<this->numBladesPerChassis_;k++){
-      DragonflyRouter* router = new DragonflyRouter(i,j,k);
-      this->routers_[i*this->numChassisPerGroup_*this->numBladesPerChassis_+j*this->numBladesPerChassis_+k]=router;
+  for(unsigned int i=0;i<this->numGroups_;i++){
+    for(unsigned int j=0;j<this->numChassisPerGroup_;j++){
+      for(unsigned int k=0;k<this->numBladesPerChassis_;k++){
+        DragonflyRouter* router = new DragonflyRouter(i,j,k);
+        this->routers_[i*this->numChassisPerGroup_*this->numBladesPerChassis_+j*this->numBladesPerChassis_+k]=router;
+      }
     }
   }
 }
 
-}
-
-
 void AsClusterDragonfly::createLink(char* id, int numlinks, Link** linkup, Link** linkdown){
   *linkup=nullptr;
   *linkdown=nullptr;
@@ -171,25 +157,24 @@ void AsClusterDragonfly::createLink(char* id, int numlinks, Link** linkup, Link*
 
 void AsClusterDragonfly::generateLinks() {
 
-  unsigned int i, j, k, l;
   static int uniqueId = 0;
   char* id = nullptr;
-  Link* linkup, *linkdown;
+  Link* linkup;
+  Link *linkdown;
 
   unsigned int numRouters = this->numGroups_*this->numChassisPerGroup_*this->numBladesPerChassis_;
 
   if (this->cluster_->sharing_policy == SURF_LINK_FULLDUPLEX)
     numLinksperLink_=2;
 
-
   //Links from routers to their local nodes.
-  for(i=0; i<numRouters;i++){
+  for(unsigned int i=0; i<numRouters;i++){
   //allocate structures
-    this->routers_[i]->myNodes_=(Link**)xbt_malloc0(numLinksperLink_*this->numNodesPerBlade_*sizeof(Link*));
-    this->routers_[i]->greenLinks_=(Link**)xbt_malloc0(this->numBladesPerChassis_*sizeof(Link*));
-    this->routers_[i]->blackLinks_=(Link**)xbt_malloc0(this->numChassisPerGroup_*sizeof(Link*));
+    this->routers_[i]->myNodes_=static_cast<Link**>(xbt_malloc0(numLinksperLink_*this->numNodesPerBlade_*sizeof(Link*)));
+    this->routers_[i]->greenLinks_=static_cast<Link**>(xbt_malloc0(this->numBladesPerChassis_*sizeof(Link*)));
+    this->routers_[i]->blackLinks_=static_cast<Link**>(xbt_malloc0(this->numChassisPerGroup_*sizeof(Link*)));
 
-    for(j=0; j< numLinksperLink_*this->numNodesPerBlade_; j+=numLinksperLink_){
+    for(unsigned int j=0; j< numLinksperLink_*this->numNodesPerBlade_; j+=numLinksperLink_){
       id = bprintf("local_link_from_router_%d_to_node_%d_%d", i, j/numLinksperLink_, uniqueId);
       this->createLink(id, 1, &linkup, &linkdown);
       if (this->cluster_->sharing_policy == SURF_LINK_FULLDUPLEX) {
@@ -204,9 +189,9 @@ void AsClusterDragonfly::generateLinks() {
   }
 
   //Green links from routers to same chassis routers - alltoall
-  for(i=0; i<this->numGroups_*this->numChassisPerGroup_;i++){
-    for(j=0; j<this->numBladesPerChassis_;j++){
-      for(k=j+1;k<this->numBladesPerChassis_;k++){
+  for(unsigned int i=0; i<this->numGroups_*this->numChassisPerGroup_;i++){
+    for(unsigned int j=0; j<this->numBladesPerChassis_;j++){
+      for(unsigned int k=j+1;k<this->numBladesPerChassis_;k++){
         id = bprintf("green_link_in_chassis_%d_between_routers_%d_and_%d_%d", i%numChassisPerGroup_, j, k, uniqueId);
         this->createLink(id, this->numLinksGreen_, &linkup, &linkdown);
         this->routers_[i*numBladesPerChassis_+j]->greenLinks_[k] = linkup;
@@ -217,10 +202,10 @@ void AsClusterDragonfly::generateLinks() {
   }
 
   //Black links from routers to same group routers - alltoall
-  for(i=0; i<this->numGroups_;i++){
-    for(j=0; j<this->numChassisPerGroup_;j++){
-      for(k=j+1;k<this->numChassisPerGroup_;k++){
-        for(l=0;l<this->numBladesPerChassis_;l++){
+  for(unsigned int i=0; i<this->numGroups_;i++){
+    for(unsigned int j=0; j<this->numChassisPerGroup_;j++){
+      for(unsigned int k=j+1;k<this->numChassisPerGroup_;k++){
+        for(unsigned int l=0;l<this->numBladesPerChassis_;l++){
           id = bprintf("black_link_in_group_%d_between_chassis_%d_and_%d_blade_%d_%d", i, j, k,l, uniqueId);
           this->createLink(id, this->numLinksBlack_,&linkup, &linkdown);
           this->routers_[i*numBladesPerChassis_*numChassisPerGroup_+j*numBladesPerChassis_+l]->blackLinks_[k] = linkup;
@@ -232,14 +217,14 @@ void AsClusterDragonfly::generateLinks() {
   }
 
 
-  //Blue links betweeen groups - Not all routers involved, only one per group is linked to others. Let's say router n of each group is linked to group n. 
+  //Blue links between groups - Not all routers involved, only one per group is linked to others. Let's say router n of each group is linked to group n.
 //FIXME: in reality blue links may be attached to several different routers
-  for(i=0; i<this->numGroups_;i++){
-    for(j=i+1; j<this->numGroups_;j++){
+  for(unsigned int i=0; i<this->numGroups_;i++){
+    for(unsigned int j=i+1; j<this->numGroups_;j++){
       unsigned int routernumi=i*numBladesPerChassis_*numChassisPerGroup_+j;
       unsigned int routernumj=j*numBladesPerChassis_*numChassisPerGroup_+i;
-      this->routers_[routernumi]->blueLinks_=(Link**)xbt_malloc0(sizeof(Link*));
-      this->routers_[routernumj]->blueLinks_=(Link**)xbt_malloc0(sizeof(Link*));
+      this->routers_[routernumi]->blueLinks_=static_cast<Link**>(xbt_malloc0(sizeof(Link*)));
+      this->routers_[routernumj]->blueLinks_=static_cast<Link**>(xbt_malloc0(sizeof(Link*)));
         id = bprintf("blue_link_between_group_%d_and_%d_routers_%d_and_%d_%d", i, j, routernumi,routernumj, uniqueId);
         this->createLink(id, this->numLinksBlue_, &linkup, &linkdown);
         this->routers_[routernumi]->blueLinks_[0] = linkup;
@@ -249,17 +234,14 @@ void AsClusterDragonfly::generateLinks() {
   }
 }
 
-
 void AsClusterDragonfly::getRouteAndLatency(NetCard * src, NetCard * dst, sg_platf_route_cbarg_t route, double *latency) {
-
   //Minimal routing version.
   // TODO : non-minimal random one, and adaptive ?
 
   if (dst->isRouter() || src->isRouter())
     return;
 
-  XBT_VERB("dragonfly_get_route_and_latency from '%s'[%d] to '%s'[%d]",
-          src->name(), src->id(), dst->name(), dst->id());
+  XBT_VERB("dragonfly_get_route_and_latency from '%s'[%d] to '%s'[%d]", src->name(), src->id(), dst->name(), dst->id());
 
   if ((src->id() == dst->id()) && hasLoopback_) {
      s_surf_parsing_link_up_down_t info = xbt_dynar_get_as(privateLinks_, src->id() * linkCountPerNode_, s_surf_parsing_link_up_down_t);
@@ -270,9 +252,8 @@ void AsClusterDragonfly::getRouteAndLatency(NetCard * src, NetCard * dst, sg_pla
      return;
   }
 
-  unsigned int *myCoords, *targetCoords;
-  myCoords = rankId_to_coords(src->id());
-  targetCoords = rankId_to_coords(dst->id());
+  unsigned int *myCoords = rankId_to_coords(src->id());
+  unsigned int *targetCoords = rankId_to_coords(dst->id());
   XBT_DEBUG("src : %u group, %u chassis, %u blade, %u node", myCoords[0], myCoords[1], myCoords[2], myCoords[3]);
   XBT_DEBUG("dst : %u group, %u chassis, %u blade, %u node", targetCoords[0], targetCoords[1], targetCoords[2], targetCoords[3]);
 
similarity index 98%
rename from src/surf/AsClusterDragonfly.hpp
rename to src/routing/AsClusterDragonfly.hpp
index f587ae4..3e3c080 100644 (file)
@@ -6,7 +6,7 @@
 #ifndef SURF_ROUTING_CLUSTER_DRAGONFLY_HPP_
 #define SURF_ROUTING_CLUSTER_DRAGONFLY_HPP_
 
-#include "src/surf/AsCluster.hpp"
+#include "src/routing/AsCluster.hpp"
 
 namespace simgrid {
   namespace routing {
similarity index 99%
rename from src/surf/AsClusterFatTree.cpp
rename to src/routing/AsClusterFatTree.cpp
index 18df2ff..d6025d1 100644 (file)
@@ -6,7 +6,7 @@
 #include <fstream>
 #include <sstream>
 
-#include "src/surf/AsClusterFatTree.hpp"
+#include "src/routing/AsClusterFatTree.hpp"
 #include "src/surf/network_interface.hpp"
 
 #include "xbt/lib.h"
similarity index 99%
rename from src/surf/AsClusterFatTree.hpp
rename to src/routing/AsClusterFatTree.hpp
index 0b36185..31ef264 100644 (file)
@@ -6,7 +6,7 @@
 #ifndef SIMGRID_ROUTING_CLUSTER_FAT_TREE_HPP_
 #define SIMGRID_ROUTING_CLUSTER_FAT_TREE_HPP_
 
-#include "src/surf/AsCluster.hpp"
+#include "src/routing/AsCluster.hpp"
 
 namespace simgrid {
 namespace routing {
similarity index 99%
rename from src/surf/AsClusterTorus.cpp
rename to src/routing/AsClusterTorus.cpp
index acf6ebf..b5a9bcb 100644 (file)
@@ -3,7 +3,7 @@
 /* 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 "src/surf/AsClusterTorus.hpp"
+#include "src/routing/AsClusterTorus.hpp"
 #include "src/surf/network_interface.hpp"
 #include "src/surf/xml/platf.hpp" // FIXME: move that back to the parsing area
 
similarity index 96%
rename from src/surf/AsClusterTorus.hpp
rename to src/routing/AsClusterTorus.hpp
index 6571971..e3953fc 100644 (file)
@@ -6,7 +6,7 @@
 #ifndef SURF_ROUTING_CLUSTER_TORUS_HPP_
 #define SURF_ROUTING_CLUSTER_TORUS_HPP_
 
-#include "src/surf/AsCluster.hpp"
+#include "src/routing/AsCluster.hpp"
 
 namespace simgrid {
   namespace routing {
similarity index 99%
rename from src/surf/AsDijkstra.cpp
rename to src/routing/AsDijkstra.cpp
index 377d2d3..b30fc83 100644 (file)
@@ -3,7 +3,7 @@
 /* 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 "src/surf/AsDijkstra.hpp"
+#include "src/routing/AsDijkstra.hpp"
 #include "src/surf/network_interface.hpp"
 
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_route_dijkstra, surf, "Routing part of surf -- dijkstra routing logic");
similarity index 98%
rename from src/surf/AsDijkstra.hpp
rename to src/routing/AsDijkstra.hpp
index 7d315a7..e2e86d9 100644 (file)
@@ -6,7 +6,7 @@
 #ifndef SURF_ROUTING_DIJKSTRA_HPP_
 #define SURF_ROUTING_DIJKSTRA_HPP_
 
-#include "src/surf/AsRoutedGraph.hpp"
+#include "src/routing/AsRoutedGraph.hpp"
 
 typedef struct graph_node_data {
   int id;
similarity index 93%
rename from src/surf/AsFloyd.cpp
rename to src/routing/AsFloyd.cpp
index 7949cf2..b7af52b 100644 (file)
@@ -5,7 +5,7 @@
 
 #include "xbt/log.h"
 #include "xbt/dynar.h"
-#include "src/surf/AsFloyd.hpp"
+#include "src/routing/AsFloyd.hpp"
 #include "src/surf/network_interface.hpp"
 
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_route_floyd, surf, "Routing part of surf");
@@ -26,13 +26,12 @@ AsFloyd::AsFloyd(const char*name)
 }
 
 AsFloyd::~AsFloyd(){
-  int i, j;
-  int table_size = (int)xbt_dynar_length(vertices_);
+  int table_size = static_cast<int>(xbt_dynar_length(vertices_));
   if (linkTable_ == nullptr) // Dealing with a parse error in the file?
     return;
   /* Delete link_table */
-  for (i = 0; i < table_size; i++)
-    for (j = 0; j < table_size; j++)
+  for (int i = 0; i < table_size; i++)
+    for (int j = 0; j < table_size; j++)
       routing_route_free(TO_FLOYD_LINK(i, j));
   xbt_free(linkTable_);
 
@@ -85,7 +84,7 @@ void AsFloyd::getRouteAndLatency(NetCard *src, NetCard *dst, sg_platf_route_cbar
 void AsFloyd::addRoute(sg_platf_route_cbarg_t route)
 {
   /* set the size of table routing */
-  int table_size = (int)xbt_dynar_length(vertices_);
+  int table_size = static_cast<int>(xbt_dynar_length(vertices_));
 
   addRouteCheckParams(route);
 
@@ -187,11 +186,9 @@ void AsFloyd::seal(){
     for (unsigned int a = 0; a < table_size; a++) {
       for (unsigned int b = 0; b < table_size; b++) {
         if (TO_FLOYD_COST(a, c) < DBL_MAX && TO_FLOYD_COST(c, b) < DBL_MAX) {
-          if (TO_FLOYD_COST(a, b) == DBL_MAX ||
-              (TO_FLOYD_COST(a, c) + TO_FLOYD_COST(c, b) <
-                  TO_FLOYD_COST(a, b))) {
-            TO_FLOYD_COST(a, b) =
-                TO_FLOYD_COST(a, c) + TO_FLOYD_COST(c, b);
+          if (fabs(TO_FLOYD_COST(a, b) - DBL_MAX) < std::numeric_limits<double>::epsilon() ||
+              (TO_FLOYD_COST(a, c) + TO_FLOYD_COST(c, b) < TO_FLOYD_COST(a, b))) {
+            TO_FLOYD_COST(a, b) = TO_FLOYD_COST(a, c) + TO_FLOYD_COST(c, b);
             TO_FLOYD_PRED(a, b) = TO_FLOYD_PRED(c, b);
           }
         }
similarity index 95%
rename from src/surf/AsFloyd.hpp
rename to src/routing/AsFloyd.hpp
index 2cc4cf2..af0c5b7 100644 (file)
@@ -6,7 +6,7 @@
 #ifndef SURF_ROUTING_FLOYD_HPP_
 #define SURF_ROUTING_FLOYD_HPP_
 
-#include "src/surf/AsRoutedGraph.hpp"
+#include "src/routing/AsRoutedGraph.hpp"
 
 namespace simgrid {
 namespace routing {
similarity index 99%
rename from src/surf/AsFull.cpp
rename to src/routing/AsFull.cpp
index 3b931a3..339b45c 100644 (file)
@@ -3,7 +3,7 @@
 /* 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 "src/surf/AsFull.hpp"
+#include "src/routing/AsFull.hpp"
 #include "src/surf/network_interface.hpp"
 
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_route_full, surf, "Routing part of surf");
similarity index 95%
rename from src/surf/AsFull.hpp
rename to src/routing/AsFull.hpp
index cfd7e5e..5ea60ff 100644 (file)
@@ -6,7 +6,7 @@
 #ifndef SIMGRID_ROUTING_FULL_HPP_
 #define SIMGRID_ROUTING_FULL_HPP_
 
-#include "src/surf/AsRoutedGraph.hpp"
+#include "src/routing/AsRoutedGraph.hpp"
 
 namespace simgrid {
 namespace routing {
similarity index 99%
rename from src/surf/AsImpl.cpp
rename to src/routing/AsImpl.cpp
index 291a79b..c76003f 100644 (file)
@@ -5,7 +5,7 @@
 
 #include "xbt/log.h"
 
-#include "src/surf/AsImpl.hpp"
+#include "src/routing/AsImpl.hpp"
 #include "src/surf/network_interface.hpp" // Link FIXME: move to proper header
 
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(AsImpl,surf, "Implementation of S4U autonomous systems");
similarity index 100%
rename from src/surf/AsImpl.hpp
rename to src/routing/AsImpl.hpp
similarity index 95%
rename from src/surf/AsNone.cpp
rename to src/routing/AsNone.cpp
index 3683fa3..8213101 100644 (file)
@@ -7,7 +7,7 @@
 #include <xbt/graph.h>
 #include <xbt/log.h>
 
-#include "src/surf/AsNone.hpp"
+#include "src/routing/AsNone.hpp"
 
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_route_none, surf, "Routing part of surf");
 
similarity index 95%
rename from src/surf/AsNone.hpp
rename to src/routing/AsNone.hpp
index 30708f9..1490dd3 100644 (file)
@@ -6,7 +6,7 @@
 #ifndef SURF_ROUTING_NONE_HPP_
 #define SURF_ROUTING_NONE_HPP_
 
-#include "src/surf/AsImpl.hpp"
+#include "src/routing/AsImpl.hpp"
 
 namespace simgrid {
 namespace routing {
similarity index 99%
rename from src/surf/AsRoutedGraph.cpp
rename to src/routing/AsRoutedGraph.cpp
index c849af3..7117c1d 100644 (file)
@@ -9,7 +9,7 @@
 #include "xbt/dynar.h"
 #include "xbt/graph.h"
 
-#include "src/surf/AsRoutedGraph.hpp"
+#include "src/routing/AsRoutedGraph.hpp"
 #include "src/surf/network_interface.hpp"
 
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_routing_generic, surf_route, "Generic implementation of the surf routing");
similarity index 96%
rename from src/surf/AsRoutedGraph.hpp
rename to src/routing/AsRoutedGraph.hpp
index c5fb0ad..5e9b00f 100644 (file)
@@ -6,7 +6,7 @@
 #ifndef SIMGRID_ROUTING_GENERIC_HPP_
 #define SIMGRID_ROUTING_GENERIC_HPP_
 
-#include "src/surf/AsImpl.hpp"
+#include "src/routing/AsImpl.hpp"
 
 namespace simgrid {
 namespace routing {
similarity index 98%
rename from src/surf/AsVivaldi.cpp
rename to src/routing/AsVivaldi.cpp
index 9a3bf1a..d835dab 100644 (file)
@@ -7,7 +7,7 @@
 
 #include <simgrid/s4u/host.hpp>
 
-#include "src/surf/AsVivaldi.hpp"
+#include "src/routing/AsVivaldi.hpp"
 #include "src/surf/network_interface.hpp"
 
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_route_vivaldi, surf, "Routing part of surf");
similarity index 95%
rename from src/surf/AsVivaldi.hpp
rename to src/routing/AsVivaldi.hpp
index a2ba680..712db43 100644 (file)
@@ -6,7 +6,7 @@
 #ifndef SURF_ROUTING_VIVALDI_HPP_
 #define SURF_ROUTING_VIVALDI_HPP_
 
-#include "src/surf/AsCluster.hpp"
+#include "src/routing/AsCluster.hpp"
 
 namespace simgrid {
 namespace routing {
index 016e38e..24a6bb8 100644 (file)
@@ -7,7 +7,7 @@
 #include "xbt/log.h"
 #include "src/msg/msg_private.h"
 
-#include "simgrid/s4u/actor.hpp"
+#include "simgrid/s4u/Actor.hpp"
 #include "simgrid/s4u/comm.hpp"
 #include "simgrid/s4u/host.hpp"
 #include "simgrid/s4u/mailbox.hpp"
@@ -83,7 +83,7 @@ void Actor::kill(int pid) {
   }
 }
 
-smx_process_t Actor::getInferior() {
+smx_process_t Actor::getImpl() {
   return pimpl_;
 }
 
@@ -110,8 +110,17 @@ void Actor::killAll() {
 
 namespace this_actor {
 
-void sleep(double duration) {
-  simcall_process_sleep(duration);
+void sleep_for(double duration)
+{
+  if (duration > 0)
+    simcall_process_sleep(duration);
+}
+
+XBT_PUBLIC(void) sleep_until(double timeout)
+{
+  double now = SIMIX_get_clock();
+  if (timeout > now)
+    simcall_process_sleep(timeout - now);
 }
 
 e_smx_state_t execute(double flops) {
@@ -121,14 +130,14 @@ e_smx_state_t execute(double flops) {
 
 void* recv(Mailbox &chan) {
   void *res = nullptr;
-  Comm c = Comm::recv_init(chan);
+  Comm& c = Comm::recv_init(chan);
   c.setDstData(&res,sizeof(res));
   c.wait();
   return res;
 }
 
 void send(Mailbox &chan, void *payload, size_t simulatedSize) {
-  Comm c = Comm::send_init(chan);
+  Comm& c = Comm::send_init(chan);
   c.setRemains(simulatedSize);
   c.setSrcData(payload);
   // c.start() is optional.
index 5910405..7873e1d 100644 (file)
@@ -18,6 +18,8 @@ Comm::~Comm() {
 
 }
 
+
+
 s4u::Comm &Comm::send_init(s4u::Mailbox &chan) {
   s4u::Comm *res = new s4u::Comm();
   res->sender_ = SIMIX_process_self();
@@ -74,12 +76,12 @@ void Comm::start() {
   xbt_assert(state_ == inited);
 
   if (srcBuff_ != nullptr) { // Sender side
-    pimpl_ = simcall_comm_isend(sender_, mailbox_->getInferior(), remains_, rate_,
+    pimpl_ = simcall_comm_isend(sender_, mailbox_->getImpl(), remains_, rate_,
         srcBuff_, srcBuffSize_,
         matchFunction_, cleanFunction_, copyDataFunction_,
         userData_, detached_);
   } else if (dstBuff_ != nullptr) { // Receiver side
-    pimpl_ = simcall_comm_irecv(receiver_, mailbox_->getInferior(), dstBuff_, &dstBuffSize_,
+    pimpl_ = simcall_comm_irecv(receiver_, mailbox_->getImpl(), dstBuff_, &dstBuffSize_,
         matchFunction_, copyDataFunction_,
         userData_, rate_);
 
@@ -95,12 +97,12 @@ void Comm::wait() {
     simcall_comm_wait(pimpl_, -1/*timeout*/);
   else {// p_state == inited. Save a simcall and do directly a blocking send/recv
     if (srcBuff_ != nullptr) {
-      simcall_comm_send(sender_, mailbox_->getInferior(), remains_, rate_,
+      simcall_comm_send(sender_, mailbox_->getImpl(), remains_, rate_,
           srcBuff_, srcBuffSize_,
           matchFunction_, copyDataFunction_,
           userData_, -1 /*timeout*/);
     } else {
-      simcall_comm_recv(receiver_, mailbox_->getInferior(), dstBuff_, &dstBuffSize_,
+      simcall_comm_recv(receiver_, mailbox_->getImpl(), dstBuff_, &dstBuffSize_,
           matchFunction_, copyDataFunction_,
           userData_, -1/*timeout*/, rate_);
     }
@@ -118,12 +120,12 @@ void Comm::wait(double timeout) {
 
   // It's not started yet. Do it in one simcall
   if (srcBuff_ != nullptr) {
-    simcall_comm_send(sender_, mailbox_->getInferior(), remains_, rate_,
+    simcall_comm_send(sender_, mailbox_->getImpl(), remains_, rate_,
         srcBuff_, srcBuffSize_,
         matchFunction_, copyDataFunction_,
         userData_, timeout);
   } else { // Receiver
-    simcall_comm_recv(receiver_, mailbox_->getInferior(), dstBuff_, &dstBuffSize_,
+    simcall_comm_recv(receiver_, mailbox_->getImpl(), dstBuff_, &dstBuffSize_,
         matchFunction_, copyDataFunction_,
         userData_, timeout, rate_);
   }
@@ -146,5 +148,22 @@ s4u::Comm &Comm::recv_async(Mailbox &dest, void **data) {
   return res;
 }
 
+bool Comm::test() {
+  xbt_assert(state_ == inited || state_ == started || state_ == finished);
+  
+  if (state_ == finished) 
+    xbt_die("Don't call test on a finished comm.");
+  
+  if (state_ == inited) {
+    this->start();
+  }
+  
+  if(simcall_comm_test(pimpl_)){
+    state_ = finished;
+    return true;
+  }
+  return false;
+}
+
 }
 }
index 3200255..3074f12 100644 (file)
@@ -25,6 +25,10 @@ void ConditionVariable::wait(std::unique_lock<Mutex>& lock) {
 }
 
 std::cv_status s4u::ConditionVariable::wait_for(std::unique_lock<Mutex>& lock, double timeout) {
+  // The simcall uses -1 for "any timeout" but we don't want this:
+  if (timeout < 0)
+    timeout = 0.0;
+
   try {
     simcall_cond_wait_timeout(cond_, lock.mutex()->mutex_, timeout);
     return std::cv_status::no_timeout;
index 2f61275..1eabd4b 100644 (file)
@@ -6,7 +6,7 @@
 #include "xbt/log.h"
 #include "src/msg/msg_private.h"
 
-#include "simgrid/s4u/actor.hpp"
+#include "simgrid/s4u/Actor.hpp"
 #include "simgrid/s4u/comm.hpp"
 #include "simgrid/s4u/host.hpp"
 #include "simgrid/s4u/mailbox.hpp"
index d7f4869..e49465c 100644 (file)
@@ -31,7 +31,7 @@ MailboxPtr Mailbox::byName(const char*name) {
   smx_mailbox_t mbox = simcall_mbox_get_by_name(name);
   if (mbox == nullptr)
     mbox = simcall_mbox_create(name);
-  return MailboxPtr(&mbox->mbox_, true);
+  return MailboxPtr(&mbox->piface_, true);
 }
 
 bool Mailbox::empty() {
@@ -43,8 +43,9 @@ void Mailbox::setReceiver(Actor* actor) {
 }
 
 /** @brief get the receiver (process associated to the mailbox) */
-Actor& Mailbox::receiver() {
-  return pimpl_->permanent_receiver->actor();
+ActorPtr Mailbox::receiver() {
+  if(pimpl_->permanent_receiver == nullptr) return ActorPtr();
+  return ActorPtr(&pimpl_->permanent_receiver->actor());
 }
 
 }
@@ -61,6 +62,3 @@ int sg_mbox_is_empty(sg_mbox_t mbox) {
 void sg_mbox_setReceiver(sg_mbox_t mbox, smx_process_t process) {
   mbox->setReceiver(&process->actor());
 }
-smx_process_t sg_mbox_receiver(sg_mbox_t mbox) {
-  return mbox->receiver().getInferior();
-}
index 9d542db..2cbfc81 100644 (file)
@@ -25,58 +25,48 @@ extern "C" {
 
 void uniq_transfer_task_name(SD_task_t task)
 {
-  SD_task_t child;
-  SD_task_t parent;
-
-  xbt_dynar_t children = SD_task_get_children(task);
-  xbt_dynar_t parents = SD_task_get_parents(task);
-
-  xbt_dynar_get_cpy(children, 0, &child);
-  xbt_dynar_get_cpy(parents, 0, &parent);
+  SD_task_t child = *(task->successors->begin());
+  SD_task_t parent = *(task->predecessors->begin());
 
   char *new_name = bprintf("%s_%s_%s", SD_task_get_name(parent), SD_task_get_name(task), SD_task_get_name(child));
 
   SD_task_set_name(task, new_name);
 
-  xbt_dynar_free_container(&children);
-  xbt_dynar_free_container(&parents);
   free(new_name);
 }
 
 static bool children_are_marked(SD_task_t task){
-  SD_dependency_t depafter = nullptr;
-  unsigned int count;
-
-  xbt_dynar_foreach(task->tasks_after,count,depafter){
-    if(depafter->dst->marked == 0)
+  for (SD_task_t it : *task->successors)
+    if (it->marked == 0)
+      return false;
+  for (SD_task_t it : *task->outputs)
+    if (it->marked == 0)
       return false;
-  }
   return true;
 }
 
 static bool parents_are_marked(SD_task_t task){
-  SD_dependency_t depbefore = nullptr;
-  unsigned int count;
-  xbt_dynar_foreach(task->tasks_before,count,depbefore){
-    if(depbefore->src->marked == 0)
+  for (SD_task_t it : *task->predecessors)
+    if (it->marked == 0)
+      return false;
+  for (SD_task_t it : *task->inputs)
+    if (it->marked == 0)
       return false;
-  }
   return true;
 }
 
 bool acyclic_graph_detail(xbt_dynar_t dag){
   unsigned int count, count_current=0;
   bool all_marked = true;
-  SD_task_t task = nullptr, parent_task = nullptr, child_task = nullptr;
-  SD_dependency_t depbefore = nullptr, depafter = nullptr;
+  SD_task_t task = nullptr;
   xbt_dynar_t next = nullptr, current = xbt_dynar_new(sizeof(SD_task_t),nullptr);
 
   xbt_dynar_foreach(dag,count,task){
-    if(task->kind == SD_TASK_COMM_E2E) continue;
+    if(task->kind == SD_TASK_COMM_E2E)
+      continue;
     task->marked = 0;
-    if(xbt_dynar_is_empty(task->tasks_after)){
+    if(task->successors->empty() && task->outputs->empty())
       xbt_dynar_push(current, &task);
-    }
   }
   //test if something has to be done for the next iteration
   while(!xbt_dynar_is_empty(current)){
@@ -87,22 +77,16 @@ bool acyclic_graph_detail(xbt_dynar_t dag){
         continue;
       //push task in next
       task->marked = 1;
-      xbt_dynar_foreach(task->tasks_before,count,depbefore){
-        parent_task = depbefore->src;
-        if(parent_task->kind == SD_TASK_COMM_E2E){
-          unsigned int j=0;
-          parent_task->marked = 1;
-          SD_task_t parent_task_2 = nullptr;
-          xbt_dynar_foreach(parent_task->tasks_before,j,depbefore){
-            parent_task_2 = depbefore->src;
-            if(children_are_marked(parent_task_2))
-              xbt_dynar_push(next, &parent_task_2);
-          }
-        } else{
-          if(children_are_marked(parent_task))
-            xbt_dynar_push(next, &parent_task);
-        }
-        parent_task = nullptr;
+      for (SD_task_t it : *task->inputs){
+        it->marked = 1;
+        // Inputs are communication, hence they can have only one predecessor
+        SD_task_t input_pred = *(it->predecessors->begin());
+        if (children_are_marked(input_pred))
+          xbt_dynar_push(next, &input_pred);
+      }
+      for (SD_task_t it : *task->predecessors) {
+        if (children_are_marked(it))
+          xbt_dynar_push(next, &it);
       }
     }
     xbt_dynar_free(&current);
@@ -128,15 +112,15 @@ bool acyclic_graph_detail(xbt_dynar_t dag){
     xbt_dynar_foreach(dag,count,task){
       if(task->kind == SD_TASK_COMM_E2E)
         continue;
-      if(xbt_dynar_is_empty(task->tasks_before)){
+      if(task->predecessors->empty() && task->inputs->empty()){
         xbt_dynar_push(current, &task);
       }
     }
 
     xbt_dynar_foreach(dag,count,task){
       if(task->kind == SD_TASK_COMM_E2E)
-       continue;
-      if(xbt_dynar_is_empty(task->tasks_before)){
+        continue;
+      if(task->predecessors->empty() && task->inputs->empty()){
         task->marked = 1;
         xbt_dynar_push(current, &task);
       }
@@ -150,37 +134,31 @@ bool acyclic_graph_detail(xbt_dynar_t dag){
           continue;
         //push task in next
         task->marked = 1;
-        xbt_dynar_foreach(task->tasks_after,count,depafter){
-          child_task = depbefore->dst;
-          if(child_task->kind == SD_TASK_COMM_E2E){
-            unsigned int j=0;
-            child_task->marked = 1;
-            SD_task_t child_task_2 = nullptr;
-            xbt_dynar_foreach(child_task->tasks_after,j,depafter){
-              child_task_2 = depbefore->dst;
-              if(parents_are_marked(child_task_2))
-                xbt_dynar_push(next, &child_task_2);
-            }
-          } else{
-            if(parents_are_marked(child_task))
-              xbt_dynar_push(next, &child_task);
-          }
-          child_task = nullptr;
+        for (SD_task_t it : *task->outputs) {
+          it->marked = 1;
+          // outputs are communication, hence they can have only one successor
+          SD_task_t output_succ = *(it->successors->begin());
+          if (parents_are_marked(output_succ))
+            xbt_dynar_push(next, &output_succ);
         }
+        for (SD_task_t it : *task->predecessors) {
+          if (parents_are_marked(it))
+            xbt_dynar_push(next, &it);
+        }
+        xbt_dynar_free(&current);
+        current = next;
+        next = nullptr;
       }
       xbt_dynar_free(&current);
-      current = next;
-      next = nullptr;
-    }
-    xbt_dynar_free(&current);
-    all_marked = true;
-    xbt_dynar_foreach(dag,count,task){
-      if(task->kind == SD_TASK_COMM_E2E)
-        continue;
-      //test if all tasks are marked
-      if(task->marked == 0){
-        XBT_WARN("the task %s is in a cycle",task->name);
-        all_marked = false;
+      all_marked = true;
+      xbt_dynar_foreach(dag,count,task){
+        if(task->kind == SD_TASK_COMM_E2E)
+          continue;
+        //test if all tasks are marked
+        if(task->marked == 0){
+          XBT_WARN("the task %s is in a cycle",task->name);
+          all_marked = false;
+        }
       }
     }
   }
@@ -193,7 +171,8 @@ static xbt_dynar_t result;
 static xbt_dict_t jobs;
 static xbt_dict_t files;
 static SD_task_t current_job;
-static SD_task_t root_task, end_task;
+static SD_task_t root_task;
+static SD_task_t end_task;
 
 static void dax_task_free(void *task)
 {
@@ -240,36 +219,31 @@ xbt_dynar_t SD_daxload(const char *filename)
    */
 
   xbt_dict_foreach(files, cursor, name, file) {
-    unsigned int cpt1;
-    unsigned int cpt2;
     SD_task_t newfile;
-    SD_dependency_t depbefore;
-    SD_dependency_t depafter;
-    if (xbt_dynar_is_empty(file->tasks_before)) {
-      xbt_dynar_foreach(file->tasks_after, cpt2, depafter) {
+    if (file->predecessors->empty()) {
+      for (SD_task_t it : *file->successors) {
         newfile = SD_task_create_comm_e2e(file->name, nullptr, file->amount);
         SD_task_dependency_add(nullptr, nullptr, root_task, newfile);
-        SD_task_dependency_add(nullptr, nullptr, newfile, depafter->dst);
+        SD_task_dependency_add(nullptr, nullptr, newfile, it);
         xbt_dynar_push(result, &newfile);
       }
-    } else if (xbt_dynar_is_empty(file->tasks_after)) {
-      xbt_dynar_foreach(file->tasks_before, cpt2, depbefore) {
+    } else if (file->successors->empty()) {
+      for (SD_task_t it : *file->predecessors){
         newfile = SD_task_create_comm_e2e(file->name, nullptr, file->amount);
-        SD_task_dependency_add(nullptr, nullptr, depbefore->src, newfile);
+        SD_task_dependency_add(nullptr, nullptr, it, newfile);
         SD_task_dependency_add(nullptr, nullptr, newfile, end_task);
         xbt_dynar_push(result, &newfile);
       }
     } else {
-      xbt_dynar_foreach(file->tasks_before, cpt1, depbefore) {
-        xbt_dynar_foreach(file->tasks_after, cpt2, depafter) {
-          if (depbefore->src == depafter->dst) {
-            XBT_WARN
-                ("File %s is produced and consumed by task %s."
-                 "This loop dependency will prevent the execution of the task.", file->name, depbefore->src->name);
+      for (SD_task_t it : *file->predecessors) {
+        for (SD_task_t it2 : *file->successors) {
+          if (it == it2) {
+            XBT_WARN ("File %s is produced and consumed by task %s."
+                      "This loop dependency will prevent the execution of the task.", file->name, it->name);
           }
           newfile = SD_task_create_comm_e2e(file->name, nullptr, file->amount);
-          SD_task_dependency_add(nullptr, nullptr, depbefore->src, newfile);
-          SD_task_dependency_add(nullptr, nullptr, newfile, depafter->dst);
+          SD_task_dependency_add(nullptr, nullptr, it, newfile);
+          SD_task_dependency_add(nullptr, nullptr, newfile, it2);
           xbt_dynar_push(result, &newfile);
         }
       }
@@ -289,10 +263,10 @@ xbt_dynar_t SD_daxload(const char *filename)
       /* If some tasks do not take files as input, connect them to the root
        * if they don't produce files, connect them to the end node.
        */
-      if ((file != root_task) && xbt_dynar_is_empty(file->tasks_before))
-        SD_task_dependency_add(nullptr, nullptr, root_task, file);
-      if ((file != end_task) && xbt_dynar_is_empty(file->tasks_after))
-        SD_task_dependency_add(nullptr, nullptr, file, end_task);
+      if ((file != root_task) && file->inputs->empty())
+        SD_task_dependency_add(nullptr, nullptr, root_task, file);
+      if ((file != end_task) && file->outputs->empty())
+        SD_task_dependency_add(nullptr, nullptr, file, end_task);
     } else {
        THROW_IMPOSSIBLE;
     }
@@ -343,7 +317,7 @@ void STag_dax__uses(void)
     sd_global->initial_tasks->erase(file);
     xbt_dict_set(files, A_dax__uses_file, file, nullptr);
   } else {
-    if (SD_task_get_amount(file) != size) {
+    if (file->amount < size || file->amount > size) {
       XBT_WARN("Ignore file %s size redefinition from %.0f to %.0f", A_dax__uses_file, SD_task_get_amount(file), size);
     }
   }
@@ -351,7 +325,7 @@ void STag_dax__uses(void)
     SD_task_dependency_add(nullptr, nullptr, file, current_job);
   } else {
     SD_task_dependency_add(nullptr, nullptr, current_job, file);
-    if (xbt_dynar_length(file->tasks_before) > 1) {
+    if ((file->predecessors->size() + file->inputs->size()) > 1) {
       XBT_WARN("File %s created at more than one location...", file->name);
     }
   }
@@ -384,18 +358,18 @@ void ETag_dax__adag()
   XBT_DEBUG("See </adag>");
 }
 
-void ETag_dax__job(void)
+void ETag_dax__job()
 {
   current_job = nullptr;
   XBT_DEBUG("See </job>");
 }
 
-void ETag_dax__parent(void)
+void ETag_dax__parent()
 {
   XBT_DEBUG("See </parent>");
 }
 
-void ETag_dax__uses(void)
+void ETag_dax__uses()
 {
   XBT_DEBUG("See </uses>");
 }
index 98024df..2acf99c 100644 (file)
@@ -60,7 +60,9 @@ xbt_dynar_t SD_dotload_generic(const char * filename, seq_par_t seq_or_par, bool
   xbt_assert(in_file != nullptr, "Failed to open file: %s", filename);
 
   unsigned int i;
-  SD_task_t root, end, task;
+  SD_task_t root;
+  SD_task_t end;
+  SD_task_t task;
   xbt_dict_t computers;
   xbt_dynar_t computer = nullptr;
   xbt_dict_cursor_t dict_cursor;
@@ -78,9 +80,9 @@ xbt_dynar_t SD_dotload_generic(const char * filename, seq_par_t seq_or_par, bool
   Agnode_t *node = nullptr;
   for (node = agfstnode(dag_dot); node; node = agnxtnode(dag_dot, node)) {
     char *name = agnameof(node);
-    double amount = atof(agget(node, (char *) "size"));
-
-    if (!(task = (SD_task_t)xbt_dict_get_or_null(jobs, name))) {
+    double amount = atof(agget(node, (char*)"size"));
+    task = static_cast<SD_task_t>(xbt_dict_get_or_null(jobs, name));
+    if (task == nullptr) {
       if (seq_or_par == sequential){
         XBT_DEBUG("See <job id=%s amount =%.0f>", name, amount);
         task = SD_task_create_comp_seq(name, nullptr , amount);
@@ -107,12 +109,13 @@ xbt_dynar_t SD_dotload_generic(const char * filename, seq_par_t seq_or_par, bool
         if((performer != -1 && order != -1) && performer < (int) sg_host_count()){
           /* required parameters are given and less performers than hosts are required */
           XBT_DEBUG ("Task '%s' is scheduled on workstation '%d' in position '%d'", task->name, performer, order);
-          if(!(computer = (xbt_dynar_t) xbt_dict_get_or_null(computers, char_performer))){
+          computer = static_cast<xbt_dynar_t> (xbt_dict_get_or_null(computers, char_performer));
+          if(computer == nullptr){
             computer = xbt_dynar_new(sizeof(SD_task_t), nullptr);
             xbt_dict_set(computers, char_performer, computer, nullptr);
           }
 
-          if((unsigned int)order < xbt_dynar_length(computer)){
+          if(static_cast<unsigned int>(order) < xbt_dynar_length(computer)){
             SD_task_t *task_test = (SD_task_t *)xbt_dynar_get_ptr(computer,order);
             if(*task_test && *task_test != task){
               /* the user gave the same order to several tasks */
@@ -136,14 +139,16 @@ xbt_dynar_t SD_dotload_generic(const char * filename, seq_par_t seq_or_par, bool
   }
 
   /*Check if 'root' and 'end' nodes have been explicitly declared.  If not, create them. */
-  if (!(root = (SD_task_t)xbt_dict_get_or_null(jobs, "root")))
+  root = static_cast<SD_task_t>(xbt_dict_get_or_null(jobs, "root"));
+  if (root == nullptr)
     root = (seq_or_par == sequential?SD_task_create_comp_seq("root", nullptr, 0):
                                      SD_task_create_comp_par_amdahl("root", nullptr, 0, 0));
 
   SD_task_set_state(root, SD_SCHEDULABLE);   /* by design the root task is always SCHEDULABLE */
   xbt_dynar_insert_at(result, 0, &root);     /* Put it at the beginning of the dynar */
 
-  if (!(end = (SD_task_t)xbt_dict_get_or_null(jobs, "end")))
+  end = static_cast<SD_task_t>(xbt_dict_get_or_null(jobs, "end"));
+  if (end == nullptr)
     end = (seq_or_par == sequential?SD_task_create_comp_seq("end", nullptr, 0):
                                     SD_task_create_comp_par_amdahl("end", nullptr, 0, 0));
 
@@ -159,17 +164,18 @@ xbt_dynar_t SD_dotload_generic(const char * filename, seq_par_t seq_or_par, bool
     xbt_dynar_sort(edges, edge_compare);
 
     xbt_dynar_foreach(edges, i, edge) {
-      SD_task_t src, dst;
-      char *src_name=agnameof(agtail(edge)), *dst_name=agnameof(aghead(edge));
+      char *src_name=agnameof(agtail(edge));
+      char *dst_name=agnameof(aghead(edge));
       double size = atof(agget(edge, (char *) "size"));
 
-      src = (SD_task_t)xbt_dict_get_or_null(jobs, src_name);
-      dst = (SD_task_t)xbt_dict_get_or_null(jobs, dst_name);
+      SD_task_t src = static_cast<SD_task_t>(xbt_dict_get_or_null(jobs, src_name));
+      SD_task_t dst = static_cast<SD_task_t>(xbt_dict_get_or_null(jobs, dst_name));
 
       if (size > 0) {
         char *name = bprintf("%s->%s", src_name, dst_name);
         XBT_DEBUG("See <transfer id=%s amount = %.0f>", name, size);
-        if (!(task = (SD_task_t)xbt_dict_get_or_null(jobs, name))) {
+        task = static_cast<SD_task_t>(xbt_dict_get_or_null(jobs, name));
+        if (task == nullptr) {
           if (seq_or_par == sequential)
             task = SD_task_create_comm_e2e(name, nullptr , size);
           else
@@ -194,12 +200,12 @@ xbt_dynar_t SD_dotload_generic(const char * filename, seq_par_t seq_or_par, bool
 
   /* Connect entry tasks to 'root', and exit tasks to 'end'*/
   xbt_dynar_foreach (result, i, task){
-    if (xbt_dynar_is_empty(task->tasks_before) && task != root) {
+    if (task->predecessors->empty() && task->inputs->empty() && task != root) {
       XBT_DEBUG("Task '%s' has no source. Add dependency from 'root'", task->name);
       SD_task_dependency_add(nullptr, nullptr, root, task);
     }
 
-    if (xbt_dynar_is_empty(task->tasks_after) && task != end) {
+    if (task->successors->empty() && task->outputs->empty() && task != end) {
       XBT_DEBUG("Task '%s' has no destination. Add dependency to 'end'", task->name);
       SD_task_dependency_add(nullptr, nullptr, task, end);
     }
index bb652b3..66f3c61 100644 (file)
@@ -31,17 +31,15 @@ SD_global_t sd_global = nullptr;
  */
 void SD_init(int *argc, char **argv)
 {
-  TRACE_global_init(argc, argv);
-
   xbt_assert(sd_global == nullptr, "SD_init() already called");
 
   sd_global = xbt_new(s_SD_global_t, 1);
-  sd_global->watch_point_reached = 0;
+  sd_global->watch_point_reached = false;
 
   sd_global->task_mallocator=xbt_mallocator_new(65536, SD_task_new_f, SD_task_free_f, SD_task_recycle_f);
 
   sd_global->initial_tasks = new std::set<SD_task_t>();
-  sd_global->executable_tasks = new std::set<SD_task_t>();
+  sd_global->runnable_tasks = new std::set<SD_task_t>();
   sd_global->completed_tasks = new std::set<SD_task_t>();
   sd_global->return_set = xbt_dynar_new(sizeof(SD_task_t), nullptr);
 
@@ -116,32 +114,19 @@ void SD_create_environment(const char *platform_file)
  */
 
 xbt_dynar_t SD_simulate(double how_long) {
-  /* we stop the simulation when total_time >= how_long */
-  double total_time = 0.0;
-  SD_task_t task, dst;
-  SD_dependency_t dependency;
-  surf_action_t action;
-  unsigned int iter, depcnt;
-
   XBT_VERB("Run simulation for %f seconds", how_long);
-  sd_global->watch_point_reached = 0;
 
+  sd_global->watch_point_reached = false;
   xbt_dynar_reset(sd_global->return_set);
 
   /* explore the runnable tasks */
-  std::set<SD_task_t>::iterator it=sd_global->executable_tasks->begin();
-  while(it != sd_global->executable_tasks->end()){
-    task = *it;
-    it++;
-    XBT_VERB("Executing task '%s'", SD_task_get_name(task));
-    SD_task_run(task);
-    xbt_dynar_push(sd_global->return_set, &task);
-  }
+  while(!sd_global->runnable_tasks->empty())
+    SD_task_run(*(sd_global->runnable_tasks->begin()));
 
-  /* main loop */
   double elapsed_time = 0.0;
-  while (elapsed_time >= 0.0 && (how_long < 0.0 || 0.00001 < (how_long -total_time)) &&
-         !sd_global->watch_point_reached) {
+  double total_time = 0.0;
+  /* main loop */
+  while (elapsed_time >= 0 && (how_long < 0 || 0.00001 < (how_long -total_time)) && !sd_global->watch_point_reached) {
     surf_model_t model = nullptr;
 
     XBT_DEBUG("Total time: %f", total_time);
@@ -152,98 +137,76 @@ xbt_dynar_t SD_simulate(double how_long) {
       total_time += elapsed_time;
 
     /* let's see which tasks are done */
+    unsigned int iter;
     xbt_dynar_foreach(all_existing_models, iter, model) {
+      surf_action_t action;
       while ((action = surf_model_extract_done_action_set(model))) {
-        task = static_cast<SD_task_t>(action->getData());
-        task->start_time = task->surf_action->getStartTime();
-
-        task->finish_time = surf_get_clock();
+        SD_task_t task = static_cast<SD_task_t>(action->getData());
         XBT_VERB("Task '%s' done", SD_task_get_name(task));
         SD_task_set_state(task, SD_DONE);
-        task->surf_action->unref();
-        task->surf_action = nullptr;
 
         /* the state has changed. Add it only if it's the first change */
-        if (xbt_dynar_member(sd_global->return_set, &task) == 0) {
+        if (xbt_dynar_member(sd_global->return_set, &task) == 0)
           xbt_dynar_push(sd_global->return_set, &task);
-        }
 
         /* remove the dependencies after this task */
-        xbt_dynar_foreach(task->tasks_after, depcnt, dependency) {
-          dst = dependency->dst;
-          dst->unsatisfied_dependencies--;
-          if (dst->is_not_ready > 0)
-            dst->is_not_ready--;
-
-          XBT_DEBUG("Released a dependency on %s: %d remain(s). Became schedulable if %d=0",
-             SD_task_get_name(dst), dst->unsatisfied_dependencies, dst->is_not_ready);
-
-          if (dst->unsatisfied_dependencies == 0) {
-            if (SD_task_get_state(dst) == SD_SCHEDULED)
-              SD_task_set_state(dst, SD_RUNNABLE);
-            else
-              SD_task_set_state(dst, SD_SCHEDULABLE);
-          }
+        for (auto succ : *task->successors) {
+          succ->predecessors->erase(task);
+          succ->inputs->erase(task);
+          XBT_DEBUG("Release dependency on %s: %zu remain(s). Becomes schedulable if %zu=0", SD_task_get_name(succ),
+              succ->predecessors->size()+succ->inputs->size(), succ->predecessors->size());
 
-          if (SD_task_get_state(dst) == SD_NOT_SCHEDULED && dst->is_not_ready == 0) {
-            SD_task_set_state(dst, SD_SCHEDULABLE);
-          }
+          if (SD_task_get_state(succ) == SD_NOT_SCHEDULED && succ->predecessors->empty())
+            SD_task_set_state(succ, SD_SCHEDULABLE);
 
-          if (SD_task_get_kind(dst) == SD_TASK_COMM_E2E) {
-            SD_dependency_t comm_dep;
-            SD_task_t comm_dst;
-            xbt_dynar_get_cpy(dst->tasks_after, 0, &comm_dep);
-            comm_dst = comm_dep->dst;
-            if (SD_task_get_state(comm_dst) == SD_NOT_SCHEDULED && comm_dst->is_not_ready > 0) {
-              comm_dst->is_not_ready--;
-
-            XBT_DEBUG("%s is a transfer, %s may be ready now if %d=0",
-               SD_task_get_name(dst), SD_task_get_name(comm_dst), comm_dst->is_not_ready);
-
-              if (comm_dst->is_not_ready == 0) {
-                SD_task_set_state(comm_dst, SD_SCHEDULABLE);
-              }
-            }
-          }
+          if (SD_task_get_state(succ) == SD_SCHEDULED && succ->predecessors->empty() && succ->inputs->empty())
+            SD_task_set_state(succ, SD_RUNNABLE);
 
-          /* is dst runnable now? */
-          if (SD_task_get_state(dst) == SD_RUNNABLE && !sd_global->watch_point_reached) {
-            XBT_VERB("Executing task '%s'", SD_task_get_name(dst));
-            SD_task_run(dst);
-            xbt_dynar_push(sd_global->return_set, &dst);
+          if (SD_task_get_state(succ) == SD_RUNNABLE && !sd_global->watch_point_reached)
+            SD_task_run(succ);
+        }
+        task->successors->clear();
+
+        for (auto output : *task->outputs) {
+          output->start_time = task->finish_time;
+          output->predecessors->erase(task);
+          if (SD_task_get_state(output) == SD_SCHEDULED)
+             SD_task_set_state(output, SD_RUNNABLE);
+          else
+             SD_task_set_state(output, SD_SCHEDULABLE);
+
+          SD_task_t comm_dst = *(output->successors->begin());
+          if (SD_task_get_state(comm_dst) == SD_NOT_SCHEDULED && comm_dst->predecessors->empty()){
+            XBT_DEBUG("%s is a transfer, %s may be ready now if %zu=0",
+                SD_task_get_name(output), SD_task_get_name(comm_dst), comm_dst->predecessors->size());
+            SD_task_set_state(comm_dst, SD_SCHEDULABLE);
           }
+          if (SD_task_get_state(output) == SD_RUNNABLE && !sd_global->watch_point_reached)
+            SD_task_run(output);
         }
+        task->outputs->clear();
       }
 
       /* let's see which tasks have just failed */
       while ((action = surf_model_extract_failed_action_set(model))) {
-        task = static_cast<SD_task_t>(action->getData());
-        task->start_time = task->surf_action->getStartTime();
-        task->finish_time = surf_get_clock();
+        SD_task_t task = static_cast<SD_task_t>(action->getData());
         XBT_VERB("Task '%s' failed", SD_task_get_name(task));
         SD_task_set_state(task, SD_FAILED);
-        action->unref();
-        task->surf_action = nullptr;
-
         xbt_dynar_push(sd_global->return_set, &task);
       }
     }
   }
 
-  if (!sd_global->watch_point_reached && how_long<0 && !sd_global->initial_tasks->empty()) {
-    XBT_WARN("Simulation is finished but %zu tasks are still not done",
-             sd_global->initial_tasks->size());
+  if (!sd_global->watch_point_reached && how_long < 0 && !sd_global->initial_tasks->empty()) {
+    XBT_WARN("Simulation is finished but %zu tasks are still not done", sd_global->initial_tasks->size());
     static const char* state_names[] =
       { "SD_NOT_SCHEDULED", "SD_SCHEDULABLE", "SD_SCHEDULED", "SD_RUNNABLE", "SD_RUNNING", "SD_DONE","SD_FAILED" };
-    for (std::set<SD_task_t>::iterator it=sd_global->initial_tasks->begin();
-         it!=sd_global->initial_tasks->end(); ++it){
-      task = *it;
-      XBT_WARN("%s is in %s state", SD_task_get_name(task), state_names[SD_task_get_state(task)]);
-    }
+    for (auto t : *sd_global->initial_tasks)
+      XBT_WARN("%s is in %s state", SD_task_get_name(t), state_names[SD_task_get_state(t)]);
   }
 
   XBT_DEBUG("elapsed_time = %f, total_time = %f, watch_point_reached = %d",
-         elapsed_time, total_time, sd_global->watch_point_reached);
+             elapsed_time, total_time, sd_global->watch_point_reached);
   XBT_DEBUG("current time = %f", surf_get_clock());
 
   return sd_global->return_set;
@@ -256,9 +219,7 @@ double SD_get_clock() {
 
 /**
  * \brief Destroys all SD internal data
- *
  * This function should be called when the simulation is over. Don't forget to destroy too.
- *
  * \see SD_init(), SD_task_destroy()
  */
 void SD_exit()
@@ -272,7 +233,7 @@ void SD_exit()
 
   xbt_mallocator_free(sd_global->task_mallocator);
   delete sd_global->initial_tasks;
-  delete sd_global->executable_tasks;
+  delete sd_global->runnable_tasks;
   delete sd_global->completed_tasks;
   xbt_dynar_free_container(&(sd_global->return_set));
   xbt_free(sd_global);
index e90ce7d..a9cae7e 100644 (file)
 
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(sd_task, sd, "Logging specific to SimDag (task)");
 
-/* Destroys a dependency between two tasks. */
-static void __SD_task_dependency_destroy(void *dependency)
-{
-  xbt_free(((SD_dependency_t)dependency)->name);
-  xbt_free(dependency);
-}
-
-/* Remove all dependencies associated with a task. This function is called when the task is destroyed. */
-static void __SD_task_remove_dependencies(SD_task_t task)
-{
-  /* we must destroy the dependencies carefully (with SD_dependency_remove) because each one is stored twice */
-  SD_dependency_t dependency;
-  while (xbt_dynar_is_empty(task->tasks_before) == 0) {
-    xbt_dynar_get_cpy(task->tasks_before, 0, &dependency);
-    SD_task_dependency_remove(dependency->src, dependency->dst);
-  }
-
-  while (xbt_dynar_is_empty(task->tasks_after) == 0) {
-    xbt_dynar_get_cpy(task->tasks_after, 0, &dependency);
-    SD_task_dependency_remove(dependency->src, dependency->dst);
-  }
-}
-
 /* Destroys the data memorized by SD_task_schedule. Task state must be SD_SCHEDULED or SD_RUNNABLE. */
 static void __SD_task_destroy_scheduling_data(SD_task_t task)
 {
@@ -50,9 +27,11 @@ static void __SD_task_destroy_scheduling_data(SD_task_t task)
 void* SD_task_new_f()
 {
   SD_task_t task = xbt_new0(s_SD_task_t, 1);
-  task->tasks_before = xbt_dynar_new(sizeof(SD_dependency_t), nullptr);
-  task->tasks_after = xbt_dynar_new(sizeof(SD_dependency_t), nullptr);
 
+  task->inputs = new std::set<SD_task_t>();
+  task->outputs = new std::set<SD_task_t>();
+  task->predecessors = new std::set<SD_task_t>();
+  task->successors = new std::set<SD_task_t>();
   return task;
 }
 
@@ -73,10 +52,10 @@ void SD_task_recycle_f(void *t)
   task->watch_points = 0;
 
   /* dependencies */
-  xbt_dynar_reset(task->tasks_before);
-  xbt_dynar_reset(task->tasks_after);
-  task->unsatisfied_dependencies = 0;
-  task->is_not_ready = 0;
+  task->inputs->clear();
+  task->outputs->clear();
+  task->predecessors->clear();
+  task->successors->clear();
 
   /* scheduling parameters */
   task->host_count = 0;
@@ -90,8 +69,11 @@ void SD_task_free_f(void *t)
 {
   SD_task_t task = static_cast<SD_task_t>(t);
 
-  xbt_dynar_free(&task->tasks_before);
-  xbt_dynar_free(&task->tasks_after);
+  delete task->inputs;
+  delete task->outputs;
+  delete task->predecessors;
+  delete task->successors;
+
   xbt_free(task);
 }
 
@@ -108,8 +90,7 @@ SD_task_t SD_task_create(const char *name, void *data, double amount)
 {
   SD_task_t task = static_cast<SD_task_t>(xbt_mallocator_get(sd_global->task_mallocator));
 
-  /* general information */
-  task->data = data;            /* user data */
+  task->data = data;
   task->name = xbt_strdup(name);
   task->amount = amount;
   task->remains = amount;
@@ -228,7 +209,15 @@ void SD_task_destroy(SD_task_t task)
 {
   XBT_DEBUG("Destroying task %s...", SD_task_get_name(task));
 
-  __SD_task_remove_dependencies(task);
+  /* First Remove all dependencies associated with the task. */
+  while (!task->predecessors->empty())
+    SD_task_dependency_remove(*(task->predecessors->begin()), task);
+  while (!task->inputs->empty())
+    SD_task_dependency_remove(*(task->inputs->begin()), task);
+  while (!task->successors->empty())
+    SD_task_dependency_remove(task, *(task->successors->begin()));
+  while (!task->outputs->empty())
+   SD_task_dependency_remove(task, *(task->outputs->begin()));
 
   if (task->state == SD_SCHEDULED || task->state == SD_RUNNABLE)
     __SD_task_destroy_scheduling_data(task);
@@ -295,7 +284,7 @@ void SD_task_set_data(SD_task_t task, void *data)
 void SD_task_set_rate(SD_task_t task, double rate)
 {
   xbt_assert(task->kind == SD_TASK_COMM_E2E, "The rate can be modified for end-to-end communications only.");
-  if(task->start_time<0) {
+  if(task->state < SD_RUNNING) {
     task->rate = rate;
   } else {
     XBT_WARN("Task %p has started. Changing rate is ineffective.", task);
@@ -320,50 +309,48 @@ e_SD_task_state_t SD_task_get_state(SD_task_t task)
 void SD_task_set_state(SD_task_t task, e_SD_task_state_t new_state)
 {
   std::set<SD_task_t>::iterator idx;
-  switch (new_state) {
-  case SD_NOT_SCHEDULED:
-  case SD_SCHEDULABLE:
-    if (SD_task_get_state(task) == SD_FAILED){
-      sd_global->completed_tasks->erase(task);
-      sd_global->initial_tasks->insert(task);
-    }
-    break;
-  case SD_SCHEDULED:
-    if (SD_task_get_state(task) == SD_RUNNABLE){
-      sd_global->initial_tasks->insert(task);
-      sd_global->executable_tasks->erase(task);
-    }
-    break;
-  case SD_RUNNABLE:
-    idx = std::find(sd_global->initial_tasks->begin(), sd_global->initial_tasks->end(), task);
+  XBT_DEBUG("Set state of '%s' to %d", task->name, new_state);
+  if ((new_state == SD_NOT_SCHEDULED || new_state == SD_SCHEDULABLE) && task->state == SD_FAILED){
+    sd_global->completed_tasks->erase(task);
+    sd_global->initial_tasks->insert(task);
+  }
+
+  if (new_state == SD_SCHEDULED && task->state == SD_RUNNABLE){
+    sd_global->initial_tasks->insert(task);
+    sd_global->runnable_tasks->erase(task);
+  }
+
+  if (new_state == SD_RUNNABLE){
+    idx = sd_global->initial_tasks->find(task);
     if (idx != sd_global->initial_tasks->end()) {
-      sd_global->executable_tasks->insert(*idx);
+      sd_global->runnable_tasks->insert(*idx);
       sd_global->initial_tasks->erase(idx);
     }
-    break;
-  case SD_RUNNING:
-    sd_global->executable_tasks->erase(task);
-    break;
-  case SD_DONE:
+  }
+
+  if (new_state == SD_RUNNING)
+    sd_global->runnable_tasks->erase(task);
+
+  if (new_state == SD_DONE || new_state == SD_FAILED){
     sd_global->completed_tasks->insert(task);
-    task->finish_time = task->surf_action->getFinishTime();
-    task->remains = 0;
+    task->start_time = task->surf_action->getStartTime();
+    if (new_state == SD_DONE){
+      task->finish_time = task->surf_action->getFinishTime();
+      task->remains = 0;
 #if HAVE_JEDULE
-    jedule_log_sd_event(task);
+      jedule_log_sd_event(task);
 #endif
-    break;
-  case SD_FAILED:
-    sd_global->completed_tasks->insert(task);
-    break;
-  default:
-    xbt_die( "Invalid state");
+    } else
+      task->finish_time = surf_get_clock();
+    task->surf_action->unref();
+    task->surf_action = nullptr;
   }
 
   task->state = new_state;
 
   if (task->watch_points & new_state) {
     XBT_VERB("Watch point reached with task '%s'!", SD_task_get_name(task));
-    sd_global->watch_point_reached = 1;
+    sd_global->watch_point_reached = true;
     SD_task_unwatch(task, new_state);   /* remove the watch point */
   }
 }
@@ -394,13 +381,13 @@ void SD_task_set_name(SD_task_t task, const char *name)
 
 xbt_dynar_t SD_task_get_parents(SD_task_t task)
 {
-  unsigned int i;
-  SD_dependency_t dep;
-
   xbt_dynar_t parents = xbt_dynar_new(sizeof(SD_task_t), nullptr);
-  xbt_dynar_foreach(task->tasks_before, i, dep) {
-    xbt_dynar_push(parents, &(dep->src));
-  }
+
+  for (auto it : *task->predecessors)
+    xbt_dynar_push(parents, &it);
+  for (auto it : *task->inputs)
+    xbt_dynar_push(parents, &it);
+
   return parents;
 }
 
@@ -411,13 +398,13 @@ xbt_dynar_t SD_task_get_parents(SD_task_t task)
  */
 xbt_dynar_t SD_task_get_children(SD_task_t task)
 {
-  unsigned int i;
-  SD_dependency_t dep;
-
   xbt_dynar_t children = xbt_dynar_new(sizeof(SD_task_t), nullptr);
-  xbt_dynar_foreach(task->tasks_after, i, dep) {
-    xbt_dynar_push(children, &(dep->dst));
-  }
+
+  for (auto it : *task->successors)
+    xbt_dynar_push(children, &it);
+  for (auto it : *task->outputs)
+    xbt_dynar_push(children, &it);
+
   return children;
 }
 
@@ -507,9 +494,6 @@ e_SD_task_kind_t SD_task_get_kind(SD_task_t task)
 /** @brief Displays debugging information about a task */
 void SD_task_dump(SD_task_t task)
 {
-  unsigned int counter;
-  SD_dependency_t dependency;
-
   XBT_INFO("Displaying task %s", SD_task_get_name(task));
   char *statename = bprintf("%s%s%s%s%s%s%s",
                       (task->state == SD_NOT_SCHEDULED ? " not scheduled" : ""),
@@ -541,32 +525,31 @@ void SD_task_dump(SD_task_t task)
     }
   }
 
-  if (task->category)
-    XBT_INFO("  - tracing category: %s", task->category);
-
   XBT_INFO("  - amount: %.0f", SD_task_get_amount(task));
   if (task->kind == SD_TASK_COMP_PAR_AMDAHL)
     XBT_INFO("  - alpha: %.2f", task->alpha);
-  XBT_INFO("  - Dependencies to satisfy: %d", task->unsatisfied_dependencies);
-  if (xbt_dynar_is_empty(task->tasks_before) == 0) {
+  XBT_INFO("  - Dependencies to satisfy: %zu", task->inputs->size()+ task->predecessors->size());
+  if ((task->inputs->size()+ task->predecessors->size()) > 0) {
     XBT_INFO("  - pre-dependencies:");
-    xbt_dynar_foreach(task->tasks_before, counter, dependency) {
-      XBT_INFO("    %s", SD_task_get_name(dependency->src));
-    }
+    for (auto it : *task->predecessors)
+      XBT_INFO("    %s", SD_task_get_name(it));
+
+    for (auto it: *task->inputs)
+      XBT_INFO("    %s", SD_task_get_name(it));
   }
-  if (xbt_dynar_is_empty(task->tasks_after)== 0) {
+  if ((task->outputs->size() + task->successors->size()) > 0) {
     XBT_INFO("  - post-dependencies:");
-    xbt_dynar_foreach(task->tasks_after, counter, dependency) {
-      XBT_INFO("    %s", SD_task_get_name(dependency->dst));
-    }
+
+    for (auto it : *task->successors)
+      XBT_INFO("    %s", SD_task_get_name(it));
+    for (auto it : *task->outputs)
+      XBT_INFO("    %s", SD_task_get_name(it));
   }
 }
 
 /** @brief Dumps the task in dotty formalism into the FILE* passed as second argument */
 void SD_task_dotty(SD_task_t task, void *out)
 {
-  unsigned int counter;
-  SD_dependency_t dependency;
   FILE *fout = static_cast<FILE*>(out);
   fprintf(fout, "  T%p [label=\"%.20s\"", task, task->name);
   switch (task->kind) {
@@ -582,9 +565,10 @@ void SD_task_dotty(SD_task_t task, void *out)
     xbt_die("Unknown task type!");
   }
   fprintf(fout, "];\n");
-  xbt_dynar_foreach(task->tasks_before, counter, dependency) {
-    fprintf(fout, " T%p -> T%p;\n", dependency->src, dependency->dst);
-  }
+  for (auto it : *task->predecessors)
+    fprintf(fout, " T%p -> T%p;\n", it, task);
+  for (auto it : *task->inputs)
+    fprintf(fout, " T%p -> T%p;\n", it, task);
 }
 
 /**
@@ -601,73 +585,42 @@ void SD_task_dotty(SD_task_t task, void *out)
  */
 void SD_task_dependency_add(const char *name, void *data, SD_task_t src, SD_task_t dst)
 {
-  bool found = false;
-  SD_dependency_t dependency;
-
-  unsigned long length = xbt_dynar_length(src->tasks_after);
-
   if (src == dst)
     THROWF(arg_error, 0, "Cannot add a dependency between task '%s' and itself", SD_task_get_name(src));
 
-  e_SD_task_state_t state = SD_task_get_state(src);
-  if (state != SD_NOT_SCHEDULED && state != SD_SCHEDULABLE && state != SD_RUNNING && state != SD_SCHEDULED &&
-       state != SD_RUNNABLE)
+  if (src->state == SD_DONE || src->state == SD_FAILED)
     THROWF(arg_error, 0, "Task '%s' must be SD_NOT_SCHEDULED, SD_SCHEDULABLE, SD_SCHEDULED, SD_RUNNABLE, or SD_RUNNING",
-           SD_task_get_name(src));
+           src->name);
 
-  state = SD_task_get_state(dst);
-  if (state != SD_NOT_SCHEDULED && state != SD_SCHEDULABLE && state != SD_SCHEDULED && state != SD_RUNNABLE)
+  if (dst->state == SD_DONE || dst->state == SD_FAILED || dst->state == SD_RUNNING)
     THROWF(arg_error, 0, "Task '%s' must be SD_NOT_SCHEDULED, SD_SCHEDULABLE, SD_SCHEDULED, or SD_RUNNABLE",
-           SD_task_get_name(dst));
+           dst->name);
 
-  XBT_DEBUG("SD_task_dependency_add: src = %s, dst = %s", SD_task_get_name(src), SD_task_get_name(dst));
-  for (unsigned long i = 0; i < length && !found; i++) {
-    xbt_dynar_get_cpy(src->tasks_after, i, &dependency);
-    found = (dependency->dst == dst);
-    XBT_DEBUG("Dependency %lu: dependency->dst = %s", i, SD_task_get_name(dependency->dst));
-  }
-
-  if (found)
-    THROWF(arg_error, 0, "A dependency already exists between task '%s' and task '%s'",
-           SD_task_get_name(src), SD_task_get_name(dst));
-
-  dependency = xbt_new(s_SD_dependency_t, 1);
+  if (dst->inputs->find(src) != dst->inputs->end() || src->outputs->find(dst) != src->outputs->end() ||
+      src->successors->find(dst) != src->successors->end() || dst->predecessors->find(src) != dst->predecessors->end())
+    THROWF(arg_error, 0, "A dependency already exists between task '%s' and task '%s'", src->name, dst->name);
 
-  dependency->name = xbt_strdup(name);  /* xbt_strdup is cleaver enough to deal with nullptr args itself */
-  dependency->data = data;
-  dependency->src = src;
-  dependency->dst = dst;
+  XBT_DEBUG("SD_task_dependency_add: src = %s, dst = %s", src->name, dst->name);
 
-  /* src must be executed before dst */
-  xbt_dynar_push(src->tasks_after, &dependency);
-  xbt_dynar_push(dst->tasks_before, &dependency);
-
-  dst->unsatisfied_dependencies++;
-  dst->is_not_ready++;
-
-  /* if the task was runnable, then dst->tasks_before is not empty anymore, so we must go back to state SD_SCHEDULED */
-  if (SD_task_get_state(dst) == SD_RUNNABLE) {
-    XBT_DEBUG("SD_task_dependency_add: %s was runnable and becomes scheduled!", SD_task_get_name(dst));
-    SD_task_set_state(dst, SD_SCHEDULED);
+  if (src->kind == SD_TASK_COMM_E2E || src->kind == SD_TASK_COMM_PAR_MXN_1D_BLOCK){
+    if (dst->kind == SD_TASK_COMP_SEQ || dst->kind == SD_TASK_COMP_PAR_AMDAHL)
+        dst->inputs->insert(src);
+    else
+      dst->predecessors->insert(src);
+    src->successors->insert(dst);
+  } else {
+    if (dst->kind == SD_TASK_COMM_E2E|| dst->kind == SD_TASK_COMM_PAR_MXN_1D_BLOCK)
+      src->outputs->insert(dst);
+    else
+      src->successors->insert(dst);
+    dst->predecessors->insert(src);
   }
-}
 
-/**
- * \brief Returns the name given as input when dependency has been created.
- *
- * \param src a task
- * \param dst a task depending on \a src
- */
-const char *SD_task_dependency_get_name(SD_task_t src, SD_task_t dst)
-{
-  unsigned int i;
-  SD_dependency_t dependency;
-
-  xbt_dynar_foreach(src->tasks_after, i, dependency){
-    if (dependency->dst == dst)
-      return dependency->name;
+  /* if the task was runnable, the task goes back to SD_SCHEDULED because of the new dependency*/
+  if (dst->state == SD_RUNNABLE) {
+    XBT_DEBUG("SD_task_dependency_add: %s was runnable and becomes scheduled!", dst->name);
+    SD_task_set_state(dst, SD_SCHEDULED);
   }
-  return nullptr;
 }
 
 /**
@@ -685,17 +638,12 @@ int SD_task_dependency_exists(SD_task_t src, SD_task_t dst)
 
   if (src) {
     if (dst) {
-      unsigned int counter;
-      SD_dependency_t dependency;
-      xbt_dynar_foreach(src->tasks_after, counter, dependency) {
-        if (dependency->dst == dst)
-          return 1;
-      }
+      return (src->successors->find(dst) != src->successors->end() || src->outputs->find(dst) != src->outputs->end());
     } else {
-      return xbt_dynar_length(src->tasks_after);
+      return src->successors->size() + src->outputs->size();
     }
   } else {
-    return xbt_dynar_length(dst->tasks_before);
+    return dst->predecessors->size() + dst->inputs->size();
   }
   return 0;
 }
@@ -709,77 +657,29 @@ int SD_task_dependency_exists(SD_task_t src, SD_task_t dst)
  */
 void SD_task_dependency_remove(SD_task_t src, SD_task_t dst)
 {
-  unsigned long length;
-  bool found = false;
-  SD_dependency_t dependency;
-
-  /* remove the dependency from src->tasks_after */
-  length = xbt_dynar_length(src->tasks_after);
-
-  for (unsigned long i = 0; i < length && !found; i++) {
-    xbt_dynar_get_cpy(src->tasks_after, i, &dependency);
-    if (dependency->dst == dst) {
-      xbt_dynar_remove_at(src->tasks_after, i, nullptr);
-      found = true;
-    }
-  }
-  if (!found)
+  XBT_DEBUG("SD_task_dependency_remove: src = %s, dst = %s", SD_task_get_name(src), SD_task_get_name(dst));
+
+  if (src->successors->find(dst) == src->successors->end() && src->outputs->find(dst) == src->outputs->end())
     THROWF(arg_error, 0, "No dependency found between task '%s' and '%s': task '%s' is not a successor of task '%s'",
-           SD_task_get_name(src), SD_task_get_name(dst), SD_task_get_name(dst), SD_task_get_name(src));
-
-  /* remove the dependency from dst->tasks_before */
-  length = xbt_dynar_length(dst->tasks_before);
-  found = false;
-
-  for (unsigned long i = 0; i < length && !found; i++) {
-    xbt_dynar_get_cpy(dst->tasks_before, i, &dependency);
-    if (dependency->src == src) {
-      xbt_dynar_remove_at(dst->tasks_before, i, nullptr);
-      __SD_task_dependency_destroy(dependency);
-      dst->unsatisfied_dependencies--;
-      dst->is_not_ready--;
-      found = true;
-    }
-  }
-  /* should never happen... */
-  xbt_assert(found, "SimDag error: task '%s' is a successor of '%s' but task '%s' is not a predecessor of task '%s'",
-              SD_task_get_name(dst), SD_task_get_name(src), SD_task_get_name(src), SD_task_get_name(dst));
-
-  /* if the task was scheduled and dst->tasks_before is empty now, we can make it runnable */
-  if (dst->unsatisfied_dependencies == 0) {
-    if (SD_task_get_state(dst) == SD_SCHEDULED)
-      SD_task_set_state(dst, SD_RUNNABLE);
+           src->name, dst->name, dst->name, src->name);
+
+  if (src->kind == SD_TASK_COMM_E2E || src->kind == SD_TASK_COMM_PAR_MXN_1D_BLOCK){
+    if (dst->kind == SD_TASK_COMP_SEQ || dst->kind == SD_TASK_COMP_PAR_AMDAHL)
+      dst->inputs->erase(src);
     else
-      SD_task_set_state(dst, SD_SCHEDULABLE);
+      dst->predecessors->erase(src);
+    src->successors->erase(dst);
+  } else {
+    if (dst->kind == SD_TASK_COMM_E2E|| dst->kind == SD_TASK_COMM_PAR_MXN_1D_BLOCK)
+      src->outputs->erase(dst);
+    else
+      src->successors->erase(dst);
+    dst->predecessors->erase(src);
   }
 
-  if (dst->is_not_ready == 0)
-    SD_task_set_state(dst, SD_SCHEDULABLE);
-}
-
-/**
- * \brief Returns the user data associated with a dependency between two tasks
- *
- * \param src a task
- * \param dst a task depending on \a src
- * \return the user data associated with this dependency (can be \c nullptr)
- * \see SD_task_dependency_add()
- */
-void *SD_task_dependency_get_data(SD_task_t src, SD_task_t dst)
-{
-  bool found = false;
-  SD_dependency_t dependency;
-
-  unsigned long length = xbt_dynar_length(src->tasks_after);
-
-  for (unsigned long i = 0; i < length && !found; i++) {
-    xbt_dynar_get_cpy(src->tasks_after, i, &dependency);
-    found = (dependency->dst == dst);
-  }
-  if (!found)
-    THROWF(arg_error, 0, "No dependency found between task '%s' and '%s'",
-           SD_task_get_name(src), SD_task_get_name(dst));
-  return dependency->data;
+  /* if the task was scheduled and dependencies are satisfied, we can make it runnable */
+  if (dst->predecessors->empty() && dst->inputs->empty() && dst->state == SD_SCHEDULED)
+    SD_task_set_state(dst, SD_RUNNABLE);
 }
 
 /**
@@ -820,37 +720,32 @@ void SD_task_unwatch(SD_task_t task, e_SD_task_state_t state)
  * now and if it was the only task.
  *
  * \param task the task to evaluate
- * \param workstation_nb number of workstations on which the task would be executed
- * \param workstation_list the workstations on which the task would be executed
- * \param flops_amount computation amount for each workstation (i.e., an array of workstation_nb doubles)
- * \param bytes_amount communication amount between each pair of workstations (i.e., a matrix of
- *        workstation_nb*workstation_nb doubles)
+ * \param host_count number of hosts on which the task would be executed
+ * \param host_list the hosts on which the task would be executed
+ * \param flops_amount computation amount for each host(i.e., an array of host_count doubles)
+ * \param bytes_amount communication amount between each pair of hosts (i.e., a matrix of host_count*host_count doubles)
  * \see SD_schedule()
  */
-double SD_task_get_execution_time(SD_task_t task, int workstation_nb, const sg_host_t *workstation_list,
+double SD_task_get_execution_time(SD_task_t task, int host_count, const sg_host_t *host_list,
                                   const double *flops_amount, const double *bytes_amount)
 {
-  xbt_assert(workstation_nb > 0, "Invalid parameter");
+  xbt_assert(host_count > 0, "Invalid parameter");
   double max_time = 0.0;
 
   /* the task execution time is the maximum execution time of the parallel tasks */
-  for (int i = 0; i < workstation_nb; i++) {
+  for (int i = 0; i < host_count; i++) {
     double time = 0.0;
     if (flops_amount != nullptr)
-      time = flops_amount[i] / workstation_list[i]->speed();
+      time = flops_amount[i] / host_list[i]->speed();
 
     if (bytes_amount != nullptr)
-      for (int j = 0; j < workstation_nb; j++) {
-        if (bytes_amount[i * workstation_nb + j] !=0 ) {
-          time += (SD_route_get_latency(workstation_list[i], workstation_list[j]) +
-                   bytes_amount[i * workstation_nb + j] /
-                   SD_route_get_bandwidth(workstation_list[i], workstation_list[j]));
-        }
-      }
+      for (int j = 0; j < host_count; j++)
+        if (bytes_amount[i * host_count + j] != 0)
+          time += (SD_route_get_latency(host_list[i], host_list[j]) +
+                   bytes_amount[i * host_count + j] / SD_route_get_bandwidth(host_list[i], host_list[j]));
 
-    if (time > max_time) {
+    if (time > max_time)
       max_time = time;
-    }
   }
   return max_time;
 }
@@ -860,7 +755,7 @@ static inline void SD_task_do_schedule(SD_task_t task)
   if (SD_task_get_state(task) > SD_SCHEDULABLE)
     THROWF(arg_error, 0, "Task '%s' has already been scheduled", SD_task_get_name(task));
 
-  if (task->unsatisfied_dependencies == 0)
+  if (task->predecessors->empty() && task->inputs->empty())
     SD_task_set_state(task, SD_RUNNABLE);
   else
     SD_task_set_state(task, SD_SCHEDULED);
@@ -880,7 +775,7 @@ static inline void SD_task_do_schedule(SD_task_t task)
  * \param rate task execution speed rate
  * \see SD_task_unschedule()
  */
-void SD_task_schedule(SD_task_t task, int host_count, const sg_host_t * workstation_list,
+void SD_task_schedule(SD_task_t task, int host_count, const sg_host_t * host_list,
                       const double *flops_amount, const double *bytes_amount, double rate)
 {
   xbt_assert(host_count > 0, "workstation_nb must be positive");
@@ -906,7 +801,7 @@ void SD_task_schedule(SD_task_t task, int host_count, const sg_host_t * workstat
   }
 
   task->host_list =  static_cast<sg_host_t*>(xbt_realloc(task->host_list, sizeof(sg_host_t) * host_count));
-  memcpy(task->host_list, workstation_list, sizeof(sg_host_t) * host_count);
+  memcpy(task->host_list, host_list, sizeof(sg_host_t) * host_count);
 
   SD_task_do_schedule(task);
 }
@@ -923,13 +818,10 @@ void SD_task_schedule(SD_task_t task, int host_count, const sg_host_t * workstat
  */
 void SD_task_unschedule(SD_task_t task)
 {
-  if (task->state != SD_SCHEDULED && task->state != SD_RUNNABLE && task->state != SD_RUNNING &&
-      task->state != SD_FAILED)
-    THROWF(arg_error, 0, "Task %s: the state must be SD_SCHEDULED, SD_RUNNABLE, SD_RUNNING or SD_FAILED",
-           SD_task_get_name(task));
+  if (task->state == SD_NOT_SCHEDULED || task->state == SD_SCHEDULABLE)
+    THROWF(arg_error, 0, "Task %s: the state must be SD_SCHEDULED, SD_RUNNABLE, SD_RUNNING or SD_FAILED", task->name);
 
-  if ((task->state == SD_SCHEDULED || task->state == SD_RUNNABLE)
-      /* if the task is scheduled or runnable */
+  if ((task->state == SD_SCHEDULED || task->state == SD_RUNNABLE) /* if the task is scheduled or runnable */
       && ((task->kind == SD_TASK_COMP_PAR_AMDAHL) || (task->kind == SD_TASK_COMM_PAR_MXN_1D_BLOCK))) {
           /* Don't free scheduling data for typed tasks */
     __SD_task_destroy_scheduling_data(task);
@@ -942,7 +834,7 @@ void SD_task_unschedule(SD_task_t task)
     /* the task should become SD_FAILED */
     task->surf_action->cancel();
   else {
-    if (task->unsatisfied_dependencies == 0)
+    if (task->predecessors->empty() && task->inputs->empty())
       SD_task_set_state(task, SD_SCHEDULABLE);
     else
       SD_task_set_state(task, SD_NOT_SCHEDULED);
@@ -954,11 +846,10 @@ void SD_task_unschedule(SD_task_t task)
 /* Runs a task. */
 void SD_task_run(SD_task_t task)
 {
-  xbt_assert(SD_task_get_state(task) == SD_RUNNABLE, "Task '%s' is not runnable! Task state: %d",
-             SD_task_get_name(task), (int)SD_task_get_state(task));
-  xbt_assert(task->host_list != nullptr, "Task '%s': workstation_list is nullptr!", SD_task_get_name(task));
+  xbt_assert(task->state == SD_RUNNABLE, "Task '%s' is not runnable! Task state: %d", task->name, (int) task->state);
+  xbt_assert(task->host_list != nullptr, "Task '%s': workstation_list is nullptr!", task->name);
 
-  XBT_DEBUG("Running task '%s'", SD_task_get_name(task));
+  XBT_VERB("Executing task '%s'", task->name);
 
   /* Copy the elements of the task into the action */
   int host_nb = task->host_count;
@@ -981,11 +872,9 @@ void SD_task_run(SD_task_t task)
 
   XBT_DEBUG("surf_action = %p", task->surf_action);
 
-  if (task->category)
-    TRACE_surf_action(task->surf_action, task->category);
-
   __SD_task_destroy_scheduling_data(task);      /* now the scheduling data are not useful anymore */
   SD_task_set_state(task, SD_RUNNING);
+  xbt_dynar_push(sd_global->return_set, &task);
 }
 
 /**
@@ -1025,18 +914,17 @@ double SD_task_get_finish_time(SD_task_t task)
 void SD_task_distribute_comp_amdahl(SD_task_t task, int ws_count)
 {
   xbt_assert(task->kind == SD_TASK_COMP_PAR_AMDAHL, "Task %s is not a SD_TASK_COMP_PAR_AMDAHL typed task."
-              "Cannot use this function.", SD_task_get_name(task));
+              "Cannot use this function.", task->name);
   task->flops_amount = xbt_new0(double, ws_count);
   task->bytes_amount = xbt_new0(double, ws_count * ws_count);
   xbt_free(task->host_list);
   task->host_count = ws_count;
   task->host_list = xbt_new0(sg_host_t, ws_count);
-  
-  for(int i=0;i<ws_count;i++){
+
+  for (int i=0; i<ws_count; i++){
     task->flops_amount[i] = (task->alpha + (1 - task->alpha)/ws_count) * task->amount;
   }
-} 
-
+}
 
 /** @brief Auto-schedules a task.
  *
@@ -1051,14 +939,11 @@ void SD_task_distribute_comp_amdahl(SD_task_t task, int ws_count)
  *  - Point to point communication (done)
  *  - Sequential computation       (done)
  *  - group communication (redistribution, several kinds)
- *  - parallel tasks with no internal communication (one kind per speedup    model such as Amdahl)
+ *  - parallel tasks with no internal communication (one kind per speedup  model such as Amdahl)
  *  - idem+ internal communication. Task type not enough since we cannot store comm cost alongside to comp one)
  */
 void SD_task_schedulev(SD_task_t task, int count, const sg_host_t * list)
 {
-  int i, j;
-  SD_dependency_t dep;
-  unsigned int cpt;
   xbt_assert(task->kind != 0, "Task %s is not typed. Cannot automatically schedule it.", SD_task_get_name(task));
   switch (task->kind) {
   case SD_TASK_COMP_PAR_AMDAHL:
@@ -1067,7 +952,7 @@ void SD_task_schedulev(SD_task_t task, int count, const sg_host_t * list)
   case SD_TASK_COMM_E2E:
   case SD_TASK_COMP_SEQ:
     xbt_assert(task->host_count == count, "Got %d locations, but were expecting %d locations", count,task->host_count);
-    for (i = 0; i < count; i++)
+    for (int i=0; i<count; i++)
       task->host_list[i] = list[i];
     if (SD_task_get_kind(task)== SD_TASK_COMP_SEQ && !task->flops_amount){
       /*This task has failed and is rescheduled. Reset the flops_amount*/
@@ -1085,140 +970,130 @@ void SD_task_schedulev(SD_task_t task, int count, const sg_host_t * list)
           sg_host_get_name(task->host_list[0]), sg_host_get_name(task->host_list[1]), task->bytes_amount[2]);
   }
 
-  /* Iterate over all children and parents being COMM_E2E to say where I am located (and start them if runnable) */
+  /* Iterate over all inputs and outputs to say where I am located (and start them if runnable) */
   if (task->kind == SD_TASK_COMP_SEQ) {
     XBT_VERB("Schedule computation task %s on %s. It costs %.f flops", SD_task_get_name(task),
           sg_host_get_name(task->host_list[0]), task->flops_amount[0]);
 
-    xbt_dynar_foreach(task->tasks_before, cpt, dep) {
-      SD_task_t before = dep->src;
-      if (before->kind == SD_TASK_COMM_E2E) {
-        before->host_list[1] = task->host_list[0];
-
-        if (before->host_list[0] && (SD_task_get_state(before) < SD_SCHEDULED)) {
-          SD_task_do_schedule(before);
-          XBT_VERB ("Auto-Schedule comm task %s between %s -> %s. It costs %.f bytes", SD_task_get_name(before),
-               sg_host_get_name(before->host_list[0]), sg_host_get_name(before->host_list[1]), before->bytes_amount[2]);
-        }
+    for (auto input : *task->inputs){
+      input->host_list[1] = task->host_list[0];
+      if (input->host_list[0] && (SD_task_get_state(input) < SD_SCHEDULED)) {
+        SD_task_do_schedule(input);
+        XBT_VERB ("Auto-Schedule comm task %s between %s -> %s. It costs %.f bytes", SD_task_get_name(input),
+                  sg_host_get_name(input->host_list[0]), sg_host_get_name(input->host_list[1]), input->bytes_amount[2]);
       }
     }
-    xbt_dynar_foreach(task->tasks_after, cpt, dep) {
-      SD_task_t after = dep->dst;
-      if (after->kind == SD_TASK_COMM_E2E) {
-        after->host_list[0] = task->host_list[0];
-        if (after->host_list[1] && (SD_task_get_state(after) < SD_SCHEDULED)) {
-          SD_task_do_schedule(after);
-          XBT_VERB ("Auto-Schedule comm task %s between %s -> %s. It costs %.f bytes", SD_task_get_name(after),
-               sg_host_get_name(after->host_list[0]), sg_host_get_name(after->host_list[1]), after->bytes_amount[2]);
-        }
+
+    for (auto output : *task->outputs){
+      output->host_list[0] = task->host_list[0];
+      if (output->host_list[1] && (SD_task_get_state(output) < SD_SCHEDULED)) {
+        SD_task_do_schedule(output);
+        XBT_VERB ("Auto-Schedule comm task %s between %s -> %s. It costs %.f bytes", SD_task_get_name(output),
+                  sg_host_get_name(output->host_list[0]), sg_host_get_name(output->host_list[1]),
+                  output->bytes_amount[2]);
       }
     }
   }
+
   /* Iterate over all children and parents being MXN_1D_BLOCK to say where I am located (and start them if runnable) */
   if (task->kind == SD_TASK_COMP_PAR_AMDAHL) {
     XBT_VERB("Schedule computation task %s on %d workstations. %.f flops will be distributed following Amdahl's Law",
           SD_task_get_name(task), task->host_count, task->flops_amount[0]);
-    xbt_dynar_foreach(task->tasks_before, cpt, dep) {
-      SD_task_t before = dep->src;
-      if (before->kind == SD_TASK_COMM_PAR_MXN_1D_BLOCK){
-        if (!before->host_list){
-          XBT_VERB("Sender side of Task %s is not scheduled yet", SD_task_get_name(before));
-          before->host_list = xbt_new0(sg_host_t, count);
-          before->host_count = count;
-          XBT_VERB("Fill the workstation list with list of Task '%s'", SD_task_get_name(task));
-          for (i=0;i<count;i++)
-            before->host_list[i] = task->host_list[i];
-        } else {
-          XBT_VERB("Build communication matrix for task '%s'", SD_task_get_name(before));
-          int src_nb, dst_nb;
-          double src_start, src_end, dst_start, dst_end;
-          src_nb = before->host_count;
-          dst_nb = count;
-          before->host_list = static_cast<sg_host_t*>(xbt_realloc(before->host_list, (before->host_count+count)*sizeof(sg_host_t)));
-          for(i=0; i<count; i++)
-            before->host_list[before->host_count+i] = task->host_list[i];
-
-          before->host_count += count;
-          xbt_free(before->flops_amount);
-          xbt_free(before->bytes_amount);
-          before->flops_amount = xbt_new0(double, before->host_count);
-          before->bytes_amount = xbt_new0(double, before->host_count* before->host_count);
-
-          for(i=0;i<src_nb;i++){
-            src_start = i*before->amount/src_nb;
-            src_end = src_start + before->amount/src_nb;
-            for(j=0; j<dst_nb; j++){
-              dst_start = j*before->amount/dst_nb;
-              dst_end = dst_start + before->amount/dst_nb;
-              XBT_VERB("(%s->%s): (%.2f, %.2f)-> (%.2f, %.2f)", sg_host_get_name(before->host_list[i]),
-                  sg_host_get_name(before->host_list[src_nb+j]), src_start, src_end, dst_start, dst_end);
-              if ((src_end <= dst_start) || (dst_end <= src_start)) {
-                before->bytes_amount[i*(src_nb+dst_nb)+src_nb+j]=0.0;
-              } else {
-                before->bytes_amount[i*(src_nb+dst_nb)+src_nb+j] = MIN(src_end, dst_end) - MAX(src_start, dst_start);
-              }
-              XBT_VERB("==> %.2f", before->bytes_amount[i*(src_nb+dst_nb)+src_nb+j]);
+    for (auto input : *task->inputs){
+      if (!input->host_list){
+        XBT_VERB("Sender side of Task %s is not scheduled yet", SD_task_get_name(input));
+        input->host_list = xbt_new0(sg_host_t, count);
+        input->host_count = count;
+        XBT_VERB("Fill the workstation list with list of Task '%s'", SD_task_get_name(task));
+        for (int i=0; i<count; i++)
+          input->host_list[i] = task->host_list[i];
+      } else {
+        XBT_VERB("Build communication matrix for task '%s'", SD_task_get_name(input));
+        int src_nb, dst_nb;
+        double src_start, src_end, dst_start, dst_end;
+        src_nb = input->host_count;
+        dst_nb = count;
+        input->host_list = static_cast<sg_host_t*>(xbt_realloc(input->host_list, (input->host_count+count)*sizeof(sg_host_t)));
+        for (int i=0; i<count; i++)
+          input->host_list[input->host_count+i] = task->host_list[i];
+
+        input->host_count += count;
+        xbt_free(input->flops_amount);
+        xbt_free(input->bytes_amount);
+        input->flops_amount = xbt_new0(double, input->host_count);
+        input->bytes_amount = xbt_new0(double, input->host_count* input->host_count);
+
+        for (int i=0; i<src_nb; i++) {
+          src_start = i*input->amount/src_nb;
+          src_end = src_start + input->amount/src_nb;
+          for (int j=0; j<dst_nb; j++) {
+            dst_start = j*input->amount/dst_nb;
+            dst_end = dst_start + input->amount/dst_nb;
+            XBT_VERB("(%s->%s): (%.2f, %.2f)-> (%.2f, %.2f)", sg_host_get_name(input->host_list[i]),
+                sg_host_get_name(input->host_list[src_nb+j]), src_start, src_end, dst_start, dst_end);
+            if ((src_end <= dst_start) || (dst_end <= src_start)) {
+              input->bytes_amount[i*(src_nb+dst_nb)+src_nb+j]=0.0;
+            } else {
+              input->bytes_amount[i*(src_nb+dst_nb)+src_nb+j] = MIN(src_end, dst_end) - MAX(src_start, dst_start);
             }
+            XBT_VERB("==> %.2f", input->bytes_amount[i*(src_nb+dst_nb)+src_nb+j]);
           }
+        }
 
-          if (SD_task_get_state(before)< SD_SCHEDULED) {
-            SD_task_do_schedule(before);
-            XBT_VERB ("Auto-Schedule redistribution task %s. Send %.f bytes from %d hosts to %d hosts.",
-                  SD_task_get_name(before),before->amount, src_nb, dst_nb);
-            }
+        if (SD_task_get_state(input)< SD_SCHEDULED) {
+          SD_task_do_schedule(input);
+          XBT_VERB ("Auto-Schedule redistribution task %s. Send %.f bytes from %d hosts to %d hosts.",
+                    SD_task_get_name(input),input->amount, src_nb, dst_nb);
         }
       }
     }
-    xbt_dynar_foreach(task->tasks_after, cpt, dep) {
-      SD_task_t after = dep->dst;
-      if (after->kind == SD_TASK_COMM_PAR_MXN_1D_BLOCK){
-        if (!after->host_list){
-          XBT_VERB("Receiver side of Task '%s' is not scheduled yet", SD_task_get_name(after));
-          after->host_list = xbt_new0(sg_host_t, count);
-          after->host_count = count;
-          XBT_VERB("Fill the workstation list with list of Task '%s'", SD_task_get_name(task));
-          for (i=0;i<count;i++)
-            after->host_list[i] = task->host_list[i];
-        } else {
-          int src_nb, dst_nb;
-          double src_start, src_end, dst_start, dst_end;
-          src_nb = count;
-          dst_nb = after->host_count;
-          after->host_list = static_cast<sg_host_t*>(xbt_realloc(after->host_list, (after->host_count+count)*sizeof(sg_host_t)));
-          for(i=after->host_count - 1; i>=0; i--)
-            after->host_list[count+i] = after->host_list[i];
-          for(i=0; i<count; i++)
-            after->host_list[i] = task->host_list[i];
-
-          after->host_count += count;
-
-          xbt_free(after->flops_amount);
-          xbt_free(after->bytes_amount);
-
-          after->flops_amount = xbt_new0(double, after->host_count);
-          after->bytes_amount = xbt_new0(double, after->host_count* after->host_count);
-
-          for(i=0;i<src_nb;i++){
-            src_start = i*after->amount/src_nb;
-            src_end = src_start + after->amount/src_nb;
-            for(j=0; j<dst_nb; j++){
-              dst_start = j*after->amount/dst_nb;
-              dst_end = dst_start + after->amount/dst_nb;
-              XBT_VERB("(%d->%d): (%.2f, %.2f)-> (%.2f, %.2f)", i, j, src_start, src_end, dst_start, dst_end);
-              if ((src_end <= dst_start) || (dst_end <= src_start)) {
-                after->bytes_amount[i*(src_nb+dst_nb)+src_nb+j]=0.0;
-              } else {
-                after->bytes_amount[i*(src_nb+dst_nb)+src_nb+j] = MIN(src_end, dst_end)- MAX(src_start, dst_start);
-              }
-              XBT_VERB("==> %.2f", after->bytes_amount[i*(src_nb+dst_nb)+src_nb+j]);
+
+    for (auto output : *task->outputs) {
+      if (!output->host_list){
+        XBT_VERB("Receiver side of Task '%s' is not scheduled yet", SD_task_get_name(output));
+        output->host_list = xbt_new0(sg_host_t, count);
+        output->host_count = count;
+        XBT_VERB("Fill the workstation list with list of Task '%s'", SD_task_get_name(task));
+        for (int i=0; i<count; i++)
+          output->host_list[i] = task->host_list[i];
+      } else {
+        double src_start, src_end, dst_start, dst_end;
+        int src_nb = count;
+        int dst_nb = output->host_count;
+        output->host_list = static_cast<sg_host_t*>(xbt_realloc(output->host_list, (output->host_count+count)*sizeof(sg_host_t)));
+        for (int i=output->host_count - 1; i>=0; i--)
+          output->host_list[count+i] = output->host_list[i];
+        for (int i=0; i<count; i++)
+          output->host_list[i] = task->host_list[i];
+
+        output->host_count += count;
+
+        xbt_free(output->flops_amount);
+        xbt_free(output->bytes_amount);
+
+        output->flops_amount = xbt_new0(double, output->host_count);
+        output->bytes_amount = xbt_new0(double, output->host_count* output->host_count);
+
+        for (int i=0; i<src_nb; i++) {
+          src_start = i*output->amount/src_nb;
+          src_end = src_start + output->amount/src_nb;
+          for (int j=0; j<dst_nb; j++) {
+            dst_start = j*output->amount/dst_nb;
+            dst_end = dst_start + output->amount/dst_nb;
+            XBT_VERB("(%d->%d): (%.2f, %.2f)-> (%.2f, %.2f)", i, j, src_start, src_end, dst_start, dst_end);
+            if ((src_end <= dst_start) || (dst_end <= src_start)) {
+              output->bytes_amount[i*(src_nb+dst_nb)+src_nb+j]=0.0;
+            } else {
+              output->bytes_amount[i*(src_nb+dst_nb)+src_nb+j] = MIN(src_end, dst_end)- MAX(src_start, dst_start);
             }
+            XBT_VERB("==> %.2f", output->bytes_amount[i*(src_nb+dst_nb)+src_nb+j]);
           }
+        }
 
-          if (SD_task_get_state(after)< SD_SCHEDULED) {
-            SD_task_do_schedule(after);
-            XBT_VERB ("Auto-Schedule redistribution task %s. Send %.f bytes from %d hosts to %d hosts.",
-              SD_task_get_name(after),after->amount, src_nb, dst_nb);
-          }
+        if (SD_task_get_state(output)< SD_SCHEDULED) {
+          SD_task_do_schedule(output);
+          XBT_VERB ("Auto-Schedule redistribution task %s. Send %.f bytes from %d hosts to %d hosts.",
+              output->name, output->amount, src_nb, dst_nb);
         }
       }
     }
@@ -1236,7 +1111,7 @@ void SD_task_schedulel(SD_task_t task, int count, ...)
   va_list ap;
   sg_host_t *list = xbt_new(sg_host_t, count);
   va_start(ap, count);
-  for (int i = 0; i < count; i++) {
+  for (int i=0; i<count; i++) {
     list[i] = va_arg(ap, sg_host_t);
   }
   va_end(ap);
index ceeb8c1..2973da0 100644 (file)
@@ -25,9 +25,10 @@ SD_link_t *SD_route_get_list(sg_host_t src, sg_host_t dst)
 
   int cpt=0;
   SD_link_t *list = xbt_new(SD_link_t, route->size());
-  for (auto link : *route)
-    list[cpt++] = link;
-
+  for (auto link : *route){
+    list[cpt] = link;
+    cpt++;
+  }
   delete route;
   return list;
 }
@@ -85,7 +86,7 @@ double SD_route_get_bandwidth(sg_host_t src, sg_host_t dst)
 
   for (auto link : *route) {
     double bandwidth = sg_link_bandwidth(link);
-    if (bandwidth < min_bandwidth || min_bandwidth == -1.0)
+    if (bandwidth < min_bandwidth || min_bandwidth < 0.0)
       min_bandwidth = bandwidth;
   }
   delete route;
index d234556..906205e 100644 (file)
@@ -23,7 +23,7 @@ typedef struct SD_global {
   bool watch_point_reached;      /* has a task just reached a watch point? */
 
   std::set<SD_task_t> *initial_tasks;
-  std::set<SD_task_t> *executable_tasks;
+  std::set<SD_task_t> *runnable_tasks;
   std::set<SD_task_t> *completed_tasks;
 
   xbt_dynar_t return_set;
@@ -49,10 +49,10 @@ typedef struct SD_task {
   int marked;                   /* used to check if the task DAG has some cycle*/
 
   /* dependencies */
-  xbt_dynar_t tasks_before;
-  xbt_dynar_t tasks_after;
-  int unsatisfied_dependencies;
-  unsigned int is_not_ready;
+  std::set<SD_task_t> *inputs;
+  std::set<SD_task_t> *outputs;
+  std::set<SD_task_t> *predecessors;
+  std::set<SD_task_t> *successors;
 
   /* scheduling parameters (only exist in state SD_SCHEDULED) */
   int host_count;
@@ -60,20 +60,8 @@ typedef struct SD_task {
   double *flops_amount;
   double *bytes_amount;
   double rate;
-
-  long long int counter;        /* task unique identifier for instrumentation */
-  char *category;               /* sd task category for instrumentation */
 } s_SD_task_t;
 
-/* Task dependencies */
-typedef struct SD_dependency {
-  char *name;
-  void *data;
-  SD_task_t src;
-  SD_task_t dst;
-  /* src must be finished before dst can start */
-} s_SD_dependency_t, *SD_dependency_t;
-
 /* SimDag private functions */
 XBT_PRIVATE void SD_task_set_state(SD_task_t task, e_SD_task_state_t new_state);
 XBT_PRIVATE void SD_task_run(SD_task_t task);
@@ -81,7 +69,7 @@ XBT_PRIVATE bool acyclic_graph_detail(xbt_dynar_t dag);
 XBT_PRIVATE void uniq_transfer_task_name(SD_task_t task);
 
 /* Task mallocator functions */
-XBT_PRIVATE void* SD_task_new_f(void);
+XBT_PRIVATE void* SD_task_new_f();
 XBT_PRIVATE void SD_task_recycle_f(void *t);
 XBT_PRIVATE void SD_task_free_f(void *t);
 
index 29a8cba..466ae73 100644 (file)
@@ -413,31 +413,36 @@ void sg_config_init(int *argc, char **argv)
     describe_model(description,descsize, surf_vm_model_description, "model", "The model to use for the vm");
     xbt_cfg_register_string("vm/model", "default", &_sg_cfg_cb__vm_model, description);
 
-    simgrid::config::bindFlag(sg_tcp_gamma = 4194304.0,
-      { "network/TCP-gamma", "network/TCP_gamma" },
+    sg_tcp_gamma = 4194304.0;
+    simgrid::config::bindFlag(sg_tcp_gamma, { "network/TCP-gamma", "network/TCP_gamma" },
       "Size of the biggest TCP window (cat /proc/sys/net/ipv4/tcp_[rw]mem for recv/send window; Use the last given value, which is the max window size)");
-    simgrid::config::bindFlag(sg_surf_precision = 0.00001,
-      "surf/precision",
+
+    sg_surf_precision = 0.00001;
+    simgrid::config::bindFlag(sg_surf_precision, "surf/precision",
       "Numerical precision used when updating simulation times (in seconds)");
-    simgrid::config::bindFlag(sg_maxmin_precision = 0.00001,
-      "maxmin/precision",
+
+    sg_maxmin_precision = 0.00001;
+    simgrid::config::bindFlag(sg_maxmin_precision, "maxmin/precision",
       "Numerical precision used when computing resource sharing (in ops/sec or bytes/sec)");
 
     /* The parameters of network models */
 
     // real default for "network/sender-gap" is set in network_smpi.cpp:
-    simgrid::config::bindFlag(sg_sender_gap = NAN,
-      { "network/sender-gap", "network/sender_gap" },
+    sg_sender_gap = NAN;
+    simgrid::config::bindFlag(sg_sender_gap, { "network/sender-gap", "network/sender_gap" },
       "Minimum gap between two overlapping sends");
-    simgrid::config::bindFlag(sg_latency_factor = 1.0,
-      { "network/latency-factor", "network/latency_factor" },
+
+    sg_latency_factor = 1.0;
+    simgrid::config::bindFlag(sg_latency_factor, { "network/latency-factor", "network/latency_factor" },
       "Correction factor to apply to the provided latency (default value set by network model)");
-    simgrid::config::bindFlag(sg_bandwidth_factor = 1.0,
-      { "network/bandwidth-factor", "network/bandwidth_factor" },
+
+    sg_bandwidth_factor = 1.0;
+    simgrid::config::bindFlag(sg_bandwidth_factor, { "network/bandwidth-factor", "network/bandwidth_factor" },
       "Correction factor to apply to the provided bandwidth (default value set by network model)");
+
     // real default for "network/weight-S" is set in network_*.cpp:
-    simgrid::config::bindFlag(sg_weight_S_parameter = NAN,
-      { "network/weight-S", "network/weight_S" },
+    sg_weight_S_parameter = NAN;
+    simgrid::config::bindFlag(sg_weight_S_parameter, { "network/weight-S", "network/weight_S" },
       "Correction factor to apply to the weight of competing streams (default value set by network model)");
 
     /* Inclusion path */
index 8f41f62..8cf08c4 100644 (file)
@@ -765,19 +765,19 @@ void simcall_comm_cancel(smx_synchro_t synchro)
 /**
  * \ingroup simix_comm_management
  */
-unsigned int simcall_comm_waitany(xbt_dynar_t comms)
+unsigned int simcall_comm_waitany(xbt_dynar_t comms, double timeout)
 {
-  return simcall_BODY_comm_waitany(comms);
+  return simcall_BODY_comm_waitany(comms, timeout);
 }
 
 /**
  * \ingroup simix_comm_management
  */
-int simcall_comm_testany(xbt_dynar_t comms)
+int simcall_comm_testany(smx_synchro_t* comms, size_t count)
 {
-  if (xbt_dynar_is_empty(comms))
+  if (count == 0)
     return -1;
-  return simcall_BODY_comm_testany(comms);
+  return simcall_BODY_comm_testany(comms, count);
 }
 
 /**
index 32e906e..dede08b 100644 (file)
@@ -657,6 +657,12 @@ static inline xbt_dynar_t simcall_comm_waitany__get__comms(smx_simcall_t simcall
 static inline void simcall_comm_waitany__set__comms(smx_simcall_t simcall, xbt_dynar_t arg) {
     simgrid::simix::marshal<xbt_dynar_t>(simcall->args[0], arg);
 }
+static inline double simcall_comm_waitany__get__timeout(smx_simcall_t simcall) {
+  return simgrid::simix::unmarshal<double>(simcall->args[1]);
+}
+static inline void simcall_comm_waitany__set__timeout(smx_simcall_t simcall, double arg) {
+    simgrid::simix::marshal<double>(simcall->args[1], arg);
+}
 static inline int simcall_comm_waitany__get__result(smx_simcall_t simcall){
     return simgrid::simix::unmarshal<int>(simcall->result);
 }
@@ -690,11 +696,17 @@ static inline void simcall_comm_test__set__result(smx_simcall_t simcall, int res
     simgrid::simix::marshal<int>(simcall->result, result);
 }
 
-static inline xbt_dynar_t simcall_comm_testany__get__comms(smx_simcall_t simcall) {
-  return simgrid::simix::unmarshal<xbt_dynar_t>(simcall->args[0]);
+static inline smx_synchro_t* simcall_comm_testany__get__comms(smx_simcall_t simcall) {
+  return simgrid::simix::unmarshal<smx_synchro_t*>(simcall->args[0]);
 }
-static inline void simcall_comm_testany__set__comms(smx_simcall_t simcall, xbt_dynar_t arg) {
-    simgrid::simix::marshal<xbt_dynar_t>(simcall->args[0], arg);
+static inline void simcall_comm_testany__set__comms(smx_simcall_t simcall, smx_synchro_t* arg) {
+    simgrid::simix::marshal<smx_synchro_t*>(simcall->args[0], arg);
+}
+static inline size_t simcall_comm_testany__get__count(smx_simcall_t simcall) {
+  return simgrid::simix::unmarshal<size_t>(simcall->args[1]);
+}
+static inline void simcall_comm_testany__set__count(smx_simcall_t simcall, size_t arg) {
+    simgrid::simix::marshal<size_t>(simcall->args[1], arg);
 }
 static inline int simcall_comm_testany__get__result(smx_simcall_t simcall){
     return simgrid::simix::unmarshal<int>(simcall->result);
@@ -1179,10 +1191,10 @@ XBT_PRIVATE void simcall_HANDLER_comm_send(smx_simcall_t simcall, smx_process_t
 XBT_PRIVATE smx_synchro_t simcall_HANDLER_comm_isend(smx_simcall_t simcall, smx_process_t sender, smx_mailbox_t mbox, double task_size, double rate, void* src_buff, size_t src_buff_size, simix_match_func_t match_fun, simix_clean_func_t clean_fun, simix_copy_data_func_t copy_data_fun, void* data, int detached);
 XBT_PRIVATE void simcall_HANDLER_comm_recv(smx_simcall_t simcall, smx_process_t receiver, smx_mailbox_t mbox, void* dst_buff, size_t* dst_buff_size, simix_match_func_t match_fun, simix_copy_data_func_t copy_data_fun, void* data, double timeout, double rate);
 XBT_PRIVATE smx_synchro_t simcall_HANDLER_comm_irecv(smx_simcall_t simcall, smx_process_t receiver, smx_mailbox_t mbox, void* dst_buff, size_t* dst_buff_size, simix_match_func_t match_fun, simix_copy_data_func_t copy_data_fun, void* data, double rate);
-XBT_PRIVATE void simcall_HANDLER_comm_waitany(smx_simcall_t simcall, xbt_dynar_t comms);
+XBT_PRIVATE void simcall_HANDLER_comm_waitany(smx_simcall_t simcall, xbt_dynar_t comms, double timeout);
 XBT_PRIVATE void simcall_HANDLER_comm_wait(smx_simcall_t simcall, smx_synchro_t comm, double timeout);
 XBT_PRIVATE void simcall_HANDLER_comm_test(smx_simcall_t simcall, smx_synchro_t comm);
-XBT_PRIVATE void simcall_HANDLER_comm_testany(smx_simcall_t simcall, xbt_dynar_t comms);
+XBT_PRIVATE void simcall_HANDLER_comm_testany(smx_simcall_t simcall, smx_synchro_t* comms, size_t count);
 XBT_PRIVATE smx_mutex_t simcall_HANDLER_mutex_init(smx_simcall_t simcall);
 XBT_PRIVATE void simcall_HANDLER_mutex_lock(smx_simcall_t simcall, smx_mutex_t mutex);
 XBT_PRIVATE int simcall_HANDLER_mutex_trylock(smx_simcall_t simcall, smx_mutex_t mutex);
index ba83d70..1910808 100644 (file)
@@ -221,10 +221,10 @@ inline static smx_synchro_t simcall_BODY_comm_irecv(smx_process_t receiver, smx_
     return simcall<smx_synchro_t, smx_process_t, smx_mailbox_t, void*, size_t*, simix_match_func_t, simix_copy_data_func_t, void*, double>(SIMCALL_COMM_IRECV, receiver, mbox, dst_buff, dst_buff_size, match_fun, copy_data_fun, data, rate);
   }
   
-inline static int simcall_BODY_comm_waitany(xbt_dynar_t comms) {
+inline static int simcall_BODY_comm_waitany(xbt_dynar_t comms, double timeout) {
     /* Go to that function to follow the code flow through the simcall barrier */
-    if (0) simcall_HANDLER_comm_waitany(&SIMIX_process_self()->simcall, comms);
-    return simcall<int, xbt_dynar_t>(SIMCALL_COMM_WAITANY, comms);
+    if (0) simcall_HANDLER_comm_waitany(&SIMIX_process_self()->simcall, comms, timeout);
+    return simcall<int, xbt_dynar_t, double>(SIMCALL_COMM_WAITANY, comms, timeout);
   }
   
 inline static void simcall_BODY_comm_wait(smx_synchro_t comm, double timeout) {
@@ -239,10 +239,10 @@ inline static int simcall_BODY_comm_test(smx_synchro_t comm) {
     return simcall<int, smx_synchro_t>(SIMCALL_COMM_TEST, comm);
   }
   
-inline static int simcall_BODY_comm_testany(xbt_dynar_t comms) {
+inline static int simcall_BODY_comm_testany(smx_synchro_t* comms, size_t count) {
     /* Go to that function to follow the code flow through the simcall barrier */
-    if (0) simcall_HANDLER_comm_testany(&SIMIX_process_self()->simcall, comms);
-    return simcall<int, xbt_dynar_t>(SIMCALL_COMM_TESTANY, comms);
+    if (0) simcall_HANDLER_comm_testany(&SIMIX_process_self()->simcall, comms, count);
+    return simcall<int, smx_synchro_t*, size_t>(SIMCALL_COMM_TESTANY, comms, count);
   }
   
 inline static smx_mutex_t simcall_BODY_mutex_init() {
index 1ba8754..3e13053 100644 (file)
@@ -254,7 +254,7 @@ case SIMCALL_COMM_IRECV:
       break;
 
 case SIMCALL_COMM_WAITANY:
-      simcall_HANDLER_comm_waitany(simcall, simgrid::simix::unmarshal<xbt_dynar_t>(simcall->args[0]));
+      simcall_HANDLER_comm_waitany(simcall, simgrid::simix::unmarshal<xbt_dynar_t>(simcall->args[0]), simgrid::simix::unmarshal<double>(simcall->args[1]));
       break;
 
 case SIMCALL_COMM_WAIT:
@@ -266,7 +266,7 @@ case SIMCALL_COMM_TEST:
       break;
 
 case SIMCALL_COMM_TESTANY:
-      simcall_HANDLER_comm_testany(simcall, simgrid::simix::unmarshal<xbt_dynar_t>(simcall->args[0]));
+      simcall_HANDLER_comm_testany(simcall, simgrid::simix::unmarshal<smx_synchro_t*>(simcall->args[0]), simgrid::simix::unmarshal<size_t>(simcall->args[1]));
       break;
 
 case SIMCALL_MUTEX_INIT:
index d6a3a57..d532dbd 100644 (file)
@@ -45,6 +45,7 @@ union u_smx_scalar {
 struct s_smx_simcall {
   e_smx_simcall_t call;
   smx_process_t issuer;
+  smx_timer_t timer;
   int mc_value;
   union u_smx_scalar args[11];
   union u_smx_scalar result;
index 55858b2..476dd57 100644 (file)
@@ -72,10 +72,10 @@ void          comm_send(smx_process_t sender, smx_mailbox_t mbox, double task_si
 smx_synchro_t comm_isend(smx_process_t sender, smx_mailbox_t mbox, double task_size, double rate, void* src_buff, size_t src_buff_size, simix_match_func_t match_fun, simix_clean_func_t clean_fun, simix_copy_data_func_t copy_data_fun, void* data, int detached);
 void          comm_recv(smx_process_t receiver, smx_mailbox_t mbox, void* dst_buff, size_t* dst_buff_size, simix_match_func_t match_fun, simix_copy_data_func_t copy_data_fun, void* data, double timeout, double rate) [[block]];
 smx_synchro_t comm_irecv(smx_process_t receiver, smx_mailbox_t mbox, void* dst_buff, size_t* dst_buff_size, simix_match_func_t match_fun, simix_copy_data_func_t copy_data_fun, void* data, double rate);
-int           comm_waitany(xbt_dynar_t comms) [[block]];
+int           comm_waitany(xbt_dynar_t comms, double timeout) [[block]];
 void          comm_wait(smx_synchro_t comm, double timeout) [[block]];
 int           comm_test(smx_synchro_t comm) [[block]];
-int           comm_testany(xbt_dynar_t comms) [[block]];
+int           comm_testany(smx_synchro_t* comms, size_t count) [[block]];
 
 smx_mutex_t mutex_init();
 void        mutex_lock(smx_mutex_t mutex) [[block]];
index 1e04e86..a995c45 100644 (file)
@@ -357,12 +357,12 @@ static void SIMIX_wake_processes()
   surf_action_t action;
 
   xbt_dynar_foreach(all_existing_models, iter, model) {
-    XBT_DEBUG("Handling process whose action failed");
+    XBT_DEBUG("Handling the processes whose action failed (if any)");
     while ((action = surf_model_extract_failed_action_set(model))) {
       XBT_DEBUG("   Handling Action %p",action);
       SIMIX_simcall_exit((smx_synchro_t) action->getData());
     }
-    XBT_DEBUG("Handling process whose action terminated normally");
+    XBT_DEBUG("Handling the processes whose action terminated normally (if any)");
     while ((action = surf_model_extract_done_action_set(model))) {
       XBT_DEBUG("   Handling Action %p",action);
       if (action->getData() == nullptr)
index db3b4fd..25783eb 100644 (file)
@@ -3,6 +3,8 @@
 /* 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 <algorithm>
+
 #include <boost/range/algorithm.hpp>
 
 #include <xbt/ex.hpp>
@@ -443,10 +445,9 @@ void simcall_HANDLER_comm_test(smx_simcall_t simcall, smx_synchro_t synchro)
   }
 }
 
-void simcall_HANDLER_comm_testany(smx_simcall_t simcall, xbt_dynar_t synchros)
+void simcall_HANDLER_comm_testany(
+  smx_simcall_t simcall, simgrid::simix::Synchro* comms[], size_t count)
 {
-  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);
@@ -456,7 +457,7 @@ void simcall_HANDLER_comm_testany(smx_simcall_t simcall, xbt_dynar_t synchros)
     if(idx == -1){
       SIMIX_simcall_answer(simcall);
     }else{
-      synchro = xbt_dynar_get_as(synchros, idx, smx_synchro_t);
+      simgrid::simix::Synchro* synchro = comms[idx];
       simcall_comm_testany__set__result(simcall, idx);
       synchro->simcalls.push_back(simcall);
       synchro->state = SIMIX_DONE;
@@ -465,9 +466,10 @@ void simcall_HANDLER_comm_testany(smx_simcall_t simcall, xbt_dynar_t synchros)
     return;
   }
 
-  xbt_dynar_foreach(simcall_comm_testany__get__comms(simcall), cursor,synchro) {
+  for (std::size_t i = 0; i != count; ++i) {
+    simgrid::simix::Synchro* synchro = comms[i];
     if (synchro->state != SIMIX_WAITING && synchro->state != SIMIX_RUNNING) {
-      simcall_comm_testany__set__result(simcall, cursor);
+      simcall_comm_testany__set__result(simcall, i);
       synchro->simcalls.push_back(simcall);
       SIMIX_comm_finish(synchro);
       return;
@@ -476,12 +478,14 @@ void simcall_HANDLER_comm_testany(smx_simcall_t simcall, xbt_dynar_t synchros)
   SIMIX_simcall_answer(simcall);
 }
 
-void simcall_HANDLER_comm_waitany(smx_simcall_t simcall, xbt_dynar_t synchros)
+void simcall_HANDLER_comm_waitany(smx_simcall_t simcall, xbt_dynar_t synchros, double timeout)
 {
   smx_synchro_t synchro;
   unsigned int cursor = 0;
 
   if (MC_is_active() || MC_record_replay_is_active()){
+    if (timeout != -1)
+      xbt_die("Timeout not implemented for waitany in the model-checker"); 
     int idx = SIMCALL_GET_MC_VALUE(simcall);
     synchro = xbt_dynar_get_as(synchros, idx, smx_synchro_t);
     synchro->simcalls.push_back(simcall);
@@ -490,7 +494,17 @@ void simcall_HANDLER_comm_waitany(smx_simcall_t simcall, xbt_dynar_t synchros)
     SIMIX_comm_finish(synchro);
     return;
   }
-
+  
+  if (timeout == -1 ){
+    simcall->timer = NULL;
+  } else {
+    simcall->timer = SIMIX_timer_set(timeout, [simcall]() {
+      SIMIX_waitany_remove_simcall_from_actions(simcall);
+      simcall_comm_waitany__set__result(simcall, -1);
+      SIMIX_simcall_answer(simcall);
+    });
+  }
+  
   xbt_dynar_foreach(synchros, cursor, synchro){
     /* associate this simcall to the the synchro */
     synchro->simcalls.push_back(simcall);
@@ -582,6 +596,10 @@ void SIMIX_comm_finish(smx_synchro_t synchro)
       continue; // if process handling comm is killed
     if (simcall->call == SIMCALL_COMM_WAITANY) {
       SIMIX_waitany_remove_simcall_from_actions(simcall);
+      if (simcall->timer) {
+        SIMIX_timer_remove(simcall->timer);
+        simcall->timer = nullptr;
+      }
       if (!MC_is_active() && !MC_record_replay_is_active())
         simcall_comm_waitany__set__result(simcall, xbt_dynar_search(simcall_comm_waitany__get__comms(simcall), &synchro));
     }
@@ -669,7 +687,14 @@ void SIMIX_comm_finish(smx_synchro_t synchro)
           e.value = xbt_dynar_search(simcall_comm_waitany__get__comms(simcall), &synchro);
         }
         else if (simcall->call == SIMCALL_COMM_TESTANY) {
-          e.value = xbt_dynar_search(simcall_comm_testany__get__comms(simcall), &synchro);
+          e.value = -1;
+          auto comms = simcall_comm_testany__get__comms(simcall);
+          auto count = simcall_comm_testany__get__count(simcall);
+          auto element = std::find(comms, comms + count, synchro);
+          if (element == comms + count)
+            e.value = -1;
+          else
+            e.value = element - comms;
         }
         simcall->issuer->exception = std::make_exception_ptr(e);
       }
index ca85abf..fb1e1cf 100644 (file)
@@ -27,12 +27,12 @@ namespace simix {
 
 class Mailbox {
 public:
-  Mailbox(const char* name) : mbox_(this), name(xbt_strdup(name)) {}
+  Mailbox(const char* name) : piface_(this), name(xbt_strdup(name)) {}
   ~Mailbox() {
     xbt_free(name);
   }
 
-  simgrid::s4u::Mailbox mbox_;
+  simgrid::s4u::Mailbox piface_; // Our interface
   char* name;
   std::deque<smx_synchro_t> comm_queue;
   boost::intrusive_ptr<simgrid::simix::Process> permanent_receiver; //process which the mailbox is attached to
index 7fd1843..c067fa8 100644 (file)
@@ -15,7 +15,7 @@
 #include <xbt/string.hpp>
 
 #include <simgrid/simix.hpp>
-#include <simgrid/s4u/actor.hpp>
+#include <simgrid/s4u/Actor.hpp>
 
 #include "simgrid/simix.h"
 #include "popping_private.h"
index f7b6c3e..073a9fb 100644 (file)
@@ -147,10 +147,9 @@ void SIMIX_vm_migratefrom_resumeto(sg_host_t vm, sg_host_t src_pm, sg_host_t dst
  *
  * @param host the vm host to get_phys_host (a sg_host_t)
  */
-void *SIMIX_vm_get_pm(sg_host_t ind_vm)
+void *SIMIX_vm_get_pm(sg_host_t host)
 {
-  /* jump to vm_ws_get_pm(). this will return the vm name. */
-  return surf_vm_get_pm(ind_vm);
+  return surf_vm_get_pm(host);
 }
 
 /**
@@ -159,10 +158,9 @@ void *SIMIX_vm_get_pm(sg_host_t ind_vm)
  * @param host the vm host (a sg_host_t)
  * @param bound bound (a double)
  */
-void SIMIX_vm_set_bound(sg_host_t ind_vm, double bound)
+void SIMIX_vm_set_bound(sg_host_t host, double bound)
 {
-  /* jump to vm_ws_set_vm_bound(). */
-  surf_vm_set_bound(ind_vm, bound);
+  surf_vm_set_bound(host, bound);
 }
 
 /**
@@ -177,7 +175,6 @@ void SIMIX_vm_set_affinity(sg_host_t ind_vm, sg_host_t ind_pm, unsigned long mas
   /* make sure this at the MSG layer. */
   xbt_assert(SIMIX_vm_get_pm(ind_vm) == ind_pm);
 
-  /* jump to vm_ws_set_vm_affinity(). */
   surf_vm_set_affinity(ind_vm, ind_pm, mask);
 }
 
index 0170851..d60b2bf 100644 (file)
@@ -773,16 +773,18 @@ int smpi_mpi_test(MPI_Request * request, MPI_Status * status) {
 
 int smpi_mpi_testany(int count, MPI_Request requests[], int *index, MPI_Status * status)
 {
-  xbt_dynar_t comms;
+  std::vector<simgrid::simix::Synchro*> comms;
+  comms.reserve(count);
+
   int i;
   int flag = 0;
 
   *index = MPI_UNDEFINED;
-  comms = xbt_dynar_new(sizeof(smx_synchro_t), nullptr);
+
   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);
+       comms.push_back(requests[i]->action);
        map.push_back(i);
     }
   }
@@ -792,7 +794,7 @@ int smpi_mpi_testany(int count, MPI_Request requests[], int *index, MPI_Status *
     if(smpi_test_sleep > 0) 
       simcall_process_sleep(nsleeps*smpi_test_sleep);
 
-    i = simcall_comm_testany(comms); // The i-th element in comms matches!
+    i = simcall_comm_testany(comms.data(), comms.size()); // 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);
@@ -809,7 +811,6 @@ int smpi_mpi_testany(int count, MPI_Request requests[], int *index, MPI_Status *
       flag = 1;
       smpi_empty_status(status);
   }
-  xbt_dynar_free(&comms);
 
   return flag;
 }
@@ -945,7 +946,7 @@ int smpi_mpi_waitany(int count, MPI_Request requests[], MPI_Status * status)
       }
     }
     if(size > 0) {
-      i = simcall_comm_waitany(comms);
+      i = simcall_comm_waitany(comms, -1);
 
       // not MPI_UNDEFINED, as this is a simix return code
       if (i != -1) {
index 9d83d4b..c893a4f 100644 (file)
@@ -151,10 +151,10 @@ HostImpl::~HostImpl()
 
 void HostImpl::attach(simgrid::s4u::Host* host)
 {
-  if (p_host != nullptr)
+  if (piface != nullptr)
     xbt_die("Already attached to host %s", host->name().c_str());
   host->extension_set(this);
-  p_host = host;
+  piface = host;
 }
 
 bool HostImpl::isOn() const {
@@ -166,13 +166,13 @@ bool HostImpl::isOff() const {
 void HostImpl::turnOn(){
   if (isOff()) {
     p_cpu->turnOn();
-    simgrid::s4u::Host::onStateChange(*this->p_host);
+    simgrid::s4u::Host::onStateChange(*this->piface);
   }
 }
 void HostImpl::turnOff(){
   if (isOn()) {
     p_cpu->turnOff();
-    simgrid::s4u::Host::onStateChange(*this->p_host);
+    simgrid::s4u::Host::onStateChange(*this->piface);
   }
 }
 
index da9970b..0849c43 100644 (file)
@@ -229,7 +229,7 @@ public:
 public:
   xbt_dynar_t p_storage;
   Cpu *p_cpu;
-  simgrid::s4u::Host* p_host = nullptr;
+  simgrid::s4u::Host* piface = nullptr;
 
   /** @brief Get the list of virtual machines on the current Host */
   xbt_dynar_t getVms();
@@ -240,7 +240,7 @@ public:
   void getParams(vm_params_t params);
   /** @brief Sets the params of that VM/PM */
   void setParams(vm_params_t params);
-  simgrid::s4u::Host* getHost() { return p_host; }
+  simgrid::s4u::Host* getHost() { return piface; }
 private:
   s_vm_params_t p_params;
 };
index c52abda..84c9590 100644 (file)
@@ -6,7 +6,7 @@
 
 #include "src/instr/instr_private.h"
 
-#include "src/surf/AsImpl.hpp"
+#include "src/routing/AsImpl.hpp"
 #include "simgrid/s4u/engine.hpp"
 #include "surf/surf.h"
 #include "src/surf/xml/platf_private.hpp"
index 1efd8ac..90a51f7 100644 (file)
@@ -5,8 +5,7 @@
  * under the terms of the license (GNU LGPL) which comes with this package. */
 
 /*
- * Modelling the proportional fairness using the Lagrange Optimization 
- * Approach. For a detailed description see:
+ * Modeling the proportional fairness using the Lagrangian Optimization Approach. For a detailed description see:
  * "ssh://username@scm.gforge.inria.fr/svn/memo/people/pvelho/lagrange/ppf.ps".
  */
 #include "xbt/log.h"
 #include <math.h>
 #endif
 
-XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_lagrange, surf,
-                                "Logging specific to SURF (lagrange)");
-XBT_LOG_NEW_SUBCATEGORY(surf_lagrange_dichotomy, surf_lagrange,
-                        "Logging specific to SURF (lagrange dichotomy)");
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_lagrange, surf, "Logging specific to SURF (lagrange)");
+XBT_LOG_NEW_SUBCATEGORY(surf_lagrange_dichotomy, surf_lagrange, "Logging specific to SURF (lagrange dichotomy)");
 
 #define SHOW_EXPR(expr) XBT_CDEBUG(surf_lagrange,#expr " = %g",expr);
 
@@ -30,18 +27,16 @@ double (*func_fp_def) (lmm_variable_t, double);
 double (*func_fpi_def) (lmm_variable_t, double);
 
 /*
- * Local prototypes to implement the lagrangian optimization with optimal step, also called dichotomy.
+ * Local prototypes to implement the Lagrangian optimization with optimal step, also called dichotomy.
  */
-//solves the proportional fairness using a lagrange optimizition with dichotomy step
+//solves the proportional fairness using a Lagrangian optimization with dichotomy step
 void lagrange_solve(lmm_system_t sys);
 //computes the value of the dichotomy using a initial values, init, with a specific variable or constraint
-static double dichotomy(double init, double diff(double, void *),
-                        void *var_cnst, double min_error);
+static double dichotomy(double init, double diff(double, void *), void *var_cnst, double min_error);
 //computes the value of the differential of constraint param_cnst applied to lambda  
 static double partial_diff_lambda(double lambda, void *param_cnst);
 
-static int __check_feasible(xbt_swag_t cnst_list, xbt_swag_t var_list,
-                            int warn)
+static int __check_feasible(xbt_swag_t cnst_list, xbt_swag_t var_list, int warn)
 {
   void *_cnst, *_elem, *_var;
   xbt_swag_t elem_list = nullptr;
@@ -52,11 +47,11 @@ static int __check_feasible(xbt_swag_t cnst_list, xbt_swag_t var_list,
   double tmp;
 
   xbt_swag_foreach(_cnst, cnst_list) {
-  cnst = (lmm_constraint_t)_cnst;
+  cnst = static_cast<lmm_constraint_t>(_cnst);
     tmp = 0;
     elem_list = &(cnst->enabled_element_set);
     xbt_swag_foreach(_elem, elem_list) {
-      elem = (lmm_element_t)_elem;
+      elem = static_cast<lmm_element_t>(_elem);
       var = elem->variable;
       xbt_assert(var->weight > 0);
       tmp += var->value;
@@ -64,30 +59,24 @@ static int __check_feasible(xbt_swag_t cnst_list, xbt_swag_t var_list,
 
     if (double_positive(tmp - cnst->bound, sg_maxmin_precision)) {
       if (warn)
-        XBT_WARN
-            ("The link (%p) is over-used. Expected less than %f and got %f",
-             cnst, cnst->bound, tmp);
+        XBT_WARN ("The link (%p) is over-used. Expected less than %f and got %f", cnst, cnst->bound, tmp);
       return 0;
     }
-    XBT_DEBUG
-        ("Checking feasability for constraint (%p): sat = %f, lambda = %f ",
-         cnst, tmp - cnst->bound, cnst->lambda);
+    XBT_DEBUG ("Checking feasability for constraint (%p): sat = %f, lambda = %f ", cnst, tmp - cnst->bound,
+               cnst->lambda);
   }
 
   xbt_swag_foreach(_var, var_list) {
-  var = (lmm_variable_t)_var;
+    var = static_cast<lmm_variable_t>(_var);
     if (!var->weight)
       break;
     if (var->bound < 0)
       continue;
-    XBT_DEBUG("Checking feasability for variable (%p): sat = %f mu = %f", var,
-           var->value - var->bound, var->mu);
+    XBT_DEBUG("Checking feasability for variable (%p): sat = %f mu = %f", var, var->value - var->bound, var->mu);
 
     if (double_positive(var->value - var->bound, sg_maxmin_precision)) {
       if (warn)
-        XBT_WARN
-            ("The variable (%p) is too large. Expected less than %f and got %f",
-             var, var->bound, var->value);
+        XBT_WARN ("The variable (%p) is too large. Expected less than %f and got %f", var, var->bound, var->value);
       return 0;
     }
   }
@@ -97,15 +86,13 @@ static int __check_feasible(xbt_swag_t cnst_list, xbt_swag_t var_list,
 static double new_value(lmm_variable_t var)
 {
   double tmp = 0;
-  int i;
 
-  for (i = 0; i < var->cnsts_number; i++) {
+  for (int i = 0; i < var->cnsts_number; i++) {
     tmp += (var->cnsts[i].constraint)->lambda;
   }
   if (var->bound > 0)
     tmp += var->mu;
-  XBT_DEBUG("\t Working on var (%p). cost = %e; Weight = %e", var, tmp,
-         var->weight);
+  XBT_DEBUG("\t Working on var (%p). cost = %e; Weight = %e", var, tmp, var->weight);
   //uses the partial differential inverse function
   return var->func_fpi(var, tmp);
 }
@@ -114,9 +101,8 @@ static double new_mu(lmm_variable_t var)
 {
   double mu_i = 0.0;
   double sigma_i = 0.0;
-  int j;
 
-  for (j = 0; j < var->cnsts_number; j++) {
+  for (int j = 0; j < var->cnsts_number; j++) {
     sigma_i += (var->cnsts[j].constraint)->lambda;
   }
   mu_i = var->func_fp(var, var->bound) - sigma_i;
@@ -127,21 +113,21 @@ static double new_mu(lmm_variable_t var)
 
 static double dual_objective(xbt_swag_t var_list, xbt_swag_t cnst_list)
 {
-  void *_cnst, *_var;
+  void *_cnst;
+  void *_var;
   lmm_constraint_t cnst = nullptr;
   lmm_variable_t var = nullptr;
 
   double obj = 0.0;
 
   xbt_swag_foreach(_var, var_list) {
-  var = (lmm_variable_t)_var;
+    var = static_cast<lmm_variable_t>(_var);
     double sigma_i = 0.0;
-    int j;
 
     if (!var->weight)
       break;
 
-    for (j = 0; j < var->cnsts_number; j++)
+    for (int j = 0; j < var->cnsts_number; j++)
       sigma_i += (var->cnsts[j].constraint)->lambda;
 
     if (var->bound > 0)
@@ -149,16 +135,15 @@ static double dual_objective(xbt_swag_t var_list, xbt_swag_t cnst_list)
 
     XBT_DEBUG("var %p : sigma_i = %1.20f", var, sigma_i);
 
-    obj += var->func_f(var, var->func_fpi(var, sigma_i)) -
-        sigma_i * var->func_fpi(var, sigma_i);
+    obj += var->func_f(var, var->func_fpi(var, sigma_i)) - sigma_i * var->func_fpi(var, sigma_i);
 
     if (var->bound > 0)
       obj += var->mu * var->bound;
   }
 
   xbt_swag_foreach(_cnst, cnst_list) {
-      cnst = (lmm_constraint_t)_cnst;
-      obj += cnst->lambda * cnst->bound;
+    cnst = static_cast<lmm_constraint_t>(_cnst);
+    obj += cnst->lambda * cnst->bound;
   }
 
   return obj;
@@ -166,18 +151,13 @@ static double dual_objective(xbt_swag_t var_list, xbt_swag_t cnst_list)
 
 void lagrange_solve(lmm_system_t sys)
 {
-  /*
-   * Lagrange Variables.
-   */
+  /* Lagrange Variables. */
   int max_iterations = 100;
   double epsilon_min_error = 0.00001; /* this is the precision on the objective function so it's none of the configurable values and this value is the legacy one */
   double dichotomy_min_error = 1e-14;
   double overall_modification = 1;
 
-  /*
-   * Variables to manipulate the data structure proposed to model the maxmin
-   * fairness. See docummentation for more details.
-   */
+  /* Variables to manipulate the data structure proposed to model the maxmin fairness. See documentation for details. */
   xbt_swag_t cnst_list = nullptr;
   void *_cnst;
   lmm_constraint_t cnst = nullptr;
@@ -186,20 +166,17 @@ void lagrange_solve(lmm_system_t sys)
   void *_var;
   lmm_variable_t var = nullptr;
 
-  /*
-   * Auxiliary variables.
-   */
+  /* Auxiliary variables. */
   int iteration = 0;
   double tmp = 0;
   int i;
-  double obj, new_obj;
+  double obj;
+  double new_obj;
 
   XBT_DEBUG("Iterative method configuration snapshot =====>");
-  XBT_DEBUG("#### Maximum number of iterations       : %d", max_iterations);
-  XBT_DEBUG("#### Minimum error tolerated            : %e",
-         epsilon_min_error);
-  XBT_DEBUG("#### Minimum error tolerated (dichotomy) : %e",
-         dichotomy_min_error);
+  XBT_DEBUG("#### Maximum number of iterations        : %d", max_iterations);
+  XBT_DEBUG("#### Minimum error tolerated             : %e", epsilon_min_error);
+  XBT_DEBUG("#### Minimum error tolerated (dichotomy) : %e", dichotomy_min_error);
 
   if (XBT_LOG_ISENABLED(surf_lagrange, xbt_log_priority_debug)) {
     lmm_print(sys);
@@ -208,10 +185,7 @@ void lagrange_solve(lmm_system_t sys)
   if (!(sys->modified))
     return;
 
-
-  /* 
-   * Initialize lambda.
-   */
+  /* Initialize lambda. */
   cnst_list = &(sys->active_constraint_set);
   xbt_swag_foreach(_cnst, cnst_list) {
   cnst = (lmm_constraint_t)_cnst;
@@ -227,7 +201,7 @@ void lagrange_solve(lmm_system_t sys)
   var_list = &(sys->variable_set);
   i = 0;
   xbt_swag_foreach(_var, var_list) {
-  var = (lmm_variable_t)_var;
+  var = static_cast<lmm_variable_t>(_var);
     if (!var->weight)
       var->value = 0.0;
     else {
@@ -246,7 +220,7 @@ void lagrange_solve(lmm_system_t sys)
       XBT_DEBUG("#### var(%p) ->weight: %e", var, var->weight);
       XBT_DEBUG("#### var(%p) ->bound: %e", var, var->bound);
       for (i = 0; i < var->cnsts_number; i++) {
-        if (var->cnsts[i].value == 0.0)
+        if (var->cnsts[i].value ==   0.0)
           nb++;
       }
       if (nb == var->cnsts_number)
@@ -254,27 +228,18 @@ void lagrange_solve(lmm_system_t sys)
     }
   }
 
-  /* 
-   * Compute dual objective.
-   */
+  /*  Compute dual objective. */
   obj = dual_objective(var_list, cnst_list);
 
-  /*
-   * While doesn't reach a minimun error or a number maximum of iterations.
-   */
-  while (overall_modification > epsilon_min_error
-         && iteration < max_iterations) {
-/*     int dual_updated=0; */
-
+  /* While doesn't reach a minimum error or a number maximum of iterations. */
+  while (overall_modification > epsilon_min_error && iteration < max_iterations) {
     iteration++;
     XBT_DEBUG("************** ITERATION %d **************", iteration);
     XBT_DEBUG("-------------- Gradient Descent ----------");
 
-    /*                       
-     * Improve the value of mu_i
-     */
+    /* Improve the value of mu_i */
     xbt_swag_foreach(_var, var_list) {
-      var = (lmm_variable_t)_var;
+      var = static_cast<lmm_variable_t>(_var);
       if (!var->weight)
         break;
       if (var->bound >= 0) {
@@ -282,69 +247,53 @@ void lagrange_solve(lmm_system_t sys)
         var->new_mu = new_mu(var);
 /*   dual_updated += (fabs(var->new_mu-var->mu)>dichotomy_min_error); */
 /*   XBT_DEBUG("dual_updated (%d) : %1.20f",dual_updated,fabs(var->new_mu-var->mu)); */
-        XBT_DEBUG("Updating mu : var->mu (%p) : %1.20f -> %1.20f", var,
-               var->mu, var->new_mu);
+        XBT_DEBUG("Updating mu : var->mu (%p) : %1.20f -> %1.20f", var, var->mu, var->new_mu);
         var->mu = var->new_mu;
 
         new_obj = dual_objective(var_list, cnst_list);
-        XBT_DEBUG("Improvement for Objective (%g -> %g) : %g", obj, new_obj,
-               obj - new_obj);
-        xbt_assert(obj - new_obj >= -epsilon_min_error,
-                    "Our gradient sucks! (%1.20f)", obj - new_obj);
+        XBT_DEBUG("Improvement for Objective (%g -> %g) : %g", obj, new_obj, obj - new_obj);
+        xbt_assert(obj - new_obj >= -epsilon_min_error, "Our gradient sucks! (%1.20f)", obj - new_obj);
         obj = new_obj;
       }
     }
 
-    /*
-     * Improve the value of lambda_i
-     */
+    /* Improve the value of lambda_i */
     xbt_swag_foreach(_cnst, cnst_list) {
-      cnst = (lmm_constraint_t)_cnst;
+      cnst = static_cast<lmm_constraint_t>(_cnst);
       XBT_DEBUG("Working on cnst (%p)", cnst);
-      cnst->new_lambda =
-          dichotomy(cnst->lambda, partial_diff_lambda, cnst,
-                    dichotomy_min_error);
+      cnst->new_lambda = dichotomy(cnst->lambda, partial_diff_lambda, cnst, dichotomy_min_error);
 /*       dual_updated += (fabs(cnst->new_lambda-cnst->lambda)>dichotomy_min_error); */
 /*       XBT_DEBUG("dual_updated (%d) : %1.20f",dual_updated,fabs(cnst->new_lambda-cnst->lambda)); */
-      XBT_DEBUG("Updating lambda : cnst->lambda (%p) : %1.20f -> %1.20f",
-             cnst, cnst->lambda, cnst->new_lambda);
+      XBT_DEBUG("Updating lambda : cnst->lambda (%p) : %1.20f -> %1.20f", cnst, cnst->lambda, cnst->new_lambda);
       cnst->lambda = cnst->new_lambda;
 
       new_obj = dual_objective(var_list, cnst_list);
-      XBT_DEBUG("Improvement for Objective (%g -> %g) : %g", obj, new_obj,
-             obj - new_obj);
-      xbt_assert(obj - new_obj >= -epsilon_min_error,
-                  "Our gradient sucks! (%1.20f)", obj - new_obj);
+      XBT_DEBUG("Improvement for Objective (%g -> %g) : %g", obj, new_obj, obj - new_obj);
+      xbt_assert(obj - new_obj >= -epsilon_min_error, "Our gradient sucks! (%1.20f)", obj - new_obj);
       obj = new_obj;
     }
 
-    /*
-     * Now computes the values of each variable (\rho) based on
-     * the values of \lambda and \mu.
-     */
+    /* Now computes the values of each variable (\rho) based on the values of \lambda and \mu. */
     XBT_DEBUG("-------------- Check convergence ----------");
     overall_modification = 0;
     xbt_swag_foreach(_var, var_list) {
-      var = (lmm_variable_t)_var;
+      var = static_cast<lmm_variable_t>(_var);
       if (var->weight <= 0)
         var->value = 0.0;
       else {
         tmp = new_value(var);
 
-        overall_modification =
-            MAX(overall_modification, fabs(var->value - tmp));
+        overall_modification = MAX(overall_modification, fabs(var->value - tmp));
 
         var->value = tmp;
-        XBT_DEBUG("New value of var (%p)  = %e, overall_modification = %e",
-               var, var->value, overall_modification);
+        XBT_DEBUG("New value of var (%p)  = %e, overall_modification = %e", var, var->value, overall_modification);
       }
     }
 
     XBT_DEBUG("-------------- Check feasability ----------");
     if (!__check_feasible(cnst_list, var_list, 0))
       overall_modification = 1.0;
-    XBT_DEBUG("Iteration %d: overall_modification : %f", iteration,
-           overall_modification);
+    XBT_DEBUG("Iteration %d: overall_modification : %f", iteration, overall_modification);
 /*     if(!dual_updated) { */
 /*       XBT_WARN("Could not improve the convergence at iteration %d. Drop it!",iteration); */
 /*       break; */
@@ -357,11 +306,8 @@ void lagrange_solve(lmm_system_t sys)
     XBT_DEBUG("The method converges in %d iterations.", iteration);
   }
   if (iteration >= max_iterations) {
-    XBT_DEBUG
-        ("Method reach %d iterations, which is the maximum number of iterations allowed.",
-         iteration);
+    XBT_DEBUG ("Method reach %d iterations, which is the maximum number of iterations allowed.", iteration);
   }
-/*   XBT_INFO("Method converged after %d iterations", iteration); */
 
   if (XBT_LOG_ISENABLED(surf_lagrange, xbt_log_priority_debug)) {
     lmm_print(sys);
@@ -369,48 +315,47 @@ void lagrange_solve(lmm_system_t sys)
 }
 
 /*
- * Returns a double value corresponding to the result of a dichotomy proccess with
- * respect to a given variable/constraint (\mu in the case of a variable or \lambda in
- * case of a constraint) and a initial value init. 
+ * Returns a double value corresponding to the result of a dichotomy process with respect to a given
+ * variable/constraint (\mu in the case of a variable or \lambda in case of a constraint) and a initial value init.
  *
  * @param init initial value for \mu or \lambda
  * @param diff a function that computes the differential of with respect a \mu or \lambda
  * @param var_cnst a pointer to a variable or constraint 
- * @param min_erro a minimun error tolerated
+ * @param min_erro a minimum error tolerated
  *
- * @return a double correponding to the result of the dichotomyal process
+ * @return a double corresponding to the result of the dichotomy process
  */
-static double dichotomy(double init, double diff(double, void *),
-                        void *var_cnst, double min_error)
+static double dichotomy(double init, double diff(double, void *), void *var_cnst, double min_error)
 {
-  double min, max;
+  double min =init;
+  double max= init;
   double overall_error;
   double middle;
-  double min_diff, max_diff, middle_diff;
+  double middle_diff;
   double diff_0 = 0.0;
-  min = max = init;
 
   XBT_IN();
 
-  if (init == 0.0) {
-    min = max = 0.5;
+  if (fabs(init) < 1e-20) {
+    min = 0.5;
+    max = 0.5;
   }
 
   overall_error = 1;
 
-  if ((diff_0 = diff(1e-16, var_cnst)) >= 0) {
+  diff_0 = diff(1e-16, var_cnst);
+  if (diff_0 >= 0) {
     XBT_CDEBUG(surf_lagrange_dichotomy, "returning 0.0 (diff = %e)", diff_0);
     XBT_OUT();
     return 0.0;
   }
 
-  min_diff = diff(min, var_cnst);
-  max_diff = diff(max, var_cnst);
+  double min_diff = diff(min, var_cnst);
+  double max_diff = diff(max, var_cnst);
 
   while (overall_error > min_error) {
-    XBT_CDEBUG(surf_lagrange_dichotomy,
-            "[min, max] = [%1.20f, %1.20f] || diffmin, diffmax = %1.20f, %1.20f",
-            min, max, min_diff, max_diff);
+    XBT_CDEBUG(surf_lagrange_dichotomy, "[min, max] = [%1.20f, %1.20f] || diffmin, diffmax = %1.20f, %1.20f",
+               min, max, min_diff, max_diff);
 
     if (min_diff > 0 && max_diff > 0) {
       if (min == max) {
@@ -434,14 +379,12 @@ static double dichotomy(double init, double diff(double, void *),
       }
     } else if (min_diff < 0 && max_diff > 0) {
       middle = (max + min) / 2.0;
-      XBT_CDEBUG(surf_lagrange_dichotomy, "Trying (max+min)/2 : %1.20f",
-              middle);
-
-      if ((min == middle) || (max == middle)) {
-        XBT_CWARN(surf_lagrange_dichotomy,
-               "Cannot improve the convergence! min=max=middle=%1.20f, diff = %1.20f."
-               " Reaching the 'double' limits. Maybe scaling your function would help ([%1.20f,%1.20f]).",
-               min, max - min, min_diff, max_diff);
+      XBT_CDEBUG(surf_lagrange_dichotomy, "Trying (max+min)/2 : %1.20f", middle);
+
+      if ((fabs(min - middle) < 1e-20) || (fabs(max - middle) < 1e-20)){
+        XBT_CWARN(surf_lagrange_dichotomy, "Cannot improve the convergence! min=max=middle=%1.20f, diff = %1.20f."
+                  " Reaching the 'double' limits. Maybe scaling your function would help ([%1.20f,%1.20f]).",
+                  min, max - min, min_diff, max_diff);
         break;
       }
       middle_diff = diff(middle, var_cnst);
@@ -462,17 +405,16 @@ static double dichotomy(double init, double diff(double, void *),
         overall_error = 0;
 /*   SHOW_EXPR(overall_error); */
       }
-    } else if (min_diff == 0) {
+    } else if (fabs(min_diff) < 1e-20) {
       max = min;
       overall_error = 0;
 /*       SHOW_EXPR(overall_error); */
-    } else if (max_diff == 0) {
+    } else if (fabs(max_diff) < 1e-20) {
       min = max;
       overall_error = 0;
 /*       SHOW_EXPR(overall_error); */
     } else if (min_diff > 0 && max_diff < 0) {
-      XBT_CWARN(surf_lagrange_dichotomy,
-             "The impossible happened, partial_diff(min) > 0 && partial_diff(max) < 0");
+      XBT_CWARN(surf_lagrange_dichotomy, "The impossible happened, partial_diff(min) > 0 && partial_diff(max) < 0");
       xbt_abort();
     } else {
       XBT_CWARN(surf_lagrange_dichotomy,
@@ -489,13 +431,12 @@ static double dichotomy(double init, double diff(double, void *),
 
 static double partial_diff_lambda(double lambda, void *param_cnst)
 {
-
   int j;
   void *_elem;
   xbt_swag_t elem_list = nullptr;
   lmm_element_t elem = nullptr;
   lmm_variable_t var = nullptr;
-  lmm_constraint_t cnst = (lmm_constraint_t) param_cnst;
+  lmm_constraint_t cnst = static_cast<lmm_constraint_t>(param_cnst);
   double diff = 0.0;
   double sigma_i = 0.0;
 
@@ -505,11 +446,10 @@ static double partial_diff_lambda(double lambda, void *param_cnst)
   XBT_CDEBUG(surf_lagrange_dichotomy, "Computing diff of cnst (%p)", cnst);
 
   xbt_swag_foreach(_elem, elem_list) {
-  elem = (lmm_element_t)_elem;
+  elem = static_cast<lmm_element_t>(_elem);
     var = elem->variable;
     xbt_assert(var->weight > 0);
-    XBT_CDEBUG(surf_lagrange_dichotomy, "Computing sigma_i for var (%p)",
-            var);
+    XBT_CDEBUG(surf_lagrange_dichotomy, "Computing sigma_i for var (%p)", var);
     // Initialize the summation variable
     sigma_i = 0.0;
 
@@ -528,12 +468,9 @@ static double partial_diff_lambda(double lambda, void *param_cnst)
     diff += -var->func_fpi(var, sigma_i);
   }
 
-
   diff += cnst->bound;
 
-  XBT_CDEBUG(surf_lagrange_dichotomy,
-          "d D/d lambda for cnst (%p) at %1.20f = %1.20f", cnst, lambda,
-          diff);
+  XBT_CDEBUG(surf_lagrange_dichotomy, "d D/d lambda for cnst (%p) at %1.20f = %1.20f", cnst, lambda, diff);
   XBT_OUT();
   return diff;
 }
@@ -542,33 +479,21 @@ static double partial_diff_lambda(double lambda, void *param_cnst)
  * 
  *  \param func_fpi  inverse of the partial differential of f (f prime inverse, (f')^{-1})
  * 
- *  Set default functions to the ones passed as parameters. This is a polimorfism in C pure, enjoy the roots of programming.
+ *  Set default functions to the ones passed as parameters. This is a polymorphism in C pure, enjoy the roots of
+ *  programming.
  *
  */
-void lmm_set_default_protocol_function(double (*func_f)
-
-
-
-
-
-
-                                        (lmm_variable_t var, double x),
-                                       double (*func_fp) (lmm_variable_t
-                                                          var, double x),
-                                       double (*func_fpi) (lmm_variable_t
-                                                           var, double x))
+void lmm_set_default_protocol_function(double (*func_f) (lmm_variable_t var, double x),
+                                       double (*func_fp) (lmm_variable_t var, double x),
+                                       double (*func_fpi) (lmm_variable_t var, double x))
 {
   func_f_def = func_f;
   func_fp_def = func_fp;
   func_fpi_def = func_fpi;
 }
 
-
 /**************** Vegas and Reno functions *************************/
-/*
- * NOTE for Reno: all functions consider the network
- * coeficient (alpha) equal to 1.
- */
+/* NOTE for Reno: all functions consider the network coefficient (alpha) equal to 1. */
 
 /*
  * For Vegas: $f(x) = \alpha D_f\ln(x)$
@@ -605,14 +530,12 @@ double func_reno_f(lmm_variable_t var, double x)
 {
   xbt_assert(var->weight > 0.0, "Don't call me with stupid values!");
 
-  return RENO_SCALING * sqrt(3.0 / 2.0) / var->weight *
-      atan(sqrt(3.0 / 2.0) * var->weight * x);
+  return RENO_SCALING * sqrt(3.0 / 2.0) / var->weight * atan(sqrt(3.0 / 2.0) * var->weight * x);
 }
 
 double func_reno_fp(lmm_variable_t var, double x)
 {
-  return RENO_SCALING * 3.0 / (3.0 * var->weight * var->weight * x * x +
-                               2.0);
+  return RENO_SCALING * 3.0 / (3.0 * var->weight * var->weight * x * x + 2.0);
 }
 
 double func_reno_fpi(lmm_variable_t var, double x)
@@ -622,16 +545,13 @@ double func_reno_fpi(lmm_variable_t var, double x)
   xbt_assert(var->weight > 0.0, "Don't call me with stupid values!");
   xbt_assert(x > 0.0, "Don't call me with stupid values!");
 
-  res_fpi =
-      1.0 / (var->weight * var->weight * (x / RENO_SCALING)) -
-      2.0 / (3.0 * var->weight * var->weight);
+  res_fpi = 1.0 / (var->weight * var->weight * (x / RENO_SCALING)) - 2.0 / (3.0 * var->weight * var->weight);
   if (res_fpi <= 0.0)
     return 0.0;
 /*   xbt_assert(res_fpi>0.0,"Don't call me with stupid values!"); */
   return sqrt(res_fpi);
 }
 
-
 /* Implementing new Reno-2
  * For Reno-2:  $f(x)   = U_f(x_f) = \frac{{2}{D_f}}*ln(2+x*D_f)$
  * Therefore:   $fp(x)  = 2/(Weight*x + 2)
@@ -641,25 +561,19 @@ double func_reno_fpi(lmm_variable_t var, double x)
 double func_reno2_f(lmm_variable_t var, double x)
 {
   xbt_assert(var->weight > 0.0, "Don't call me with stupid values!");
-  return RENO2_SCALING * (1.0 / var->weight) * log((x * var->weight) /
-                                                   (2.0 * x * var->weight +
-                                                    3.0));
+  return RENO2_SCALING * (1.0 / var->weight) * log((x * var->weight) / (2.0 * x * var->weight + 3.0));
 }
 
 double func_reno2_fp(lmm_variable_t var, double x)
 {
-  return RENO2_SCALING * 3.0 / (var->weight * x *
-                                (2.0 * var->weight * x + 3.0));
+  return RENO2_SCALING * 3.0 / (var->weight * x * (2.0 * var->weight * x + 3.0));
 }
 
 double func_reno2_fpi(lmm_variable_t var, double x)
 {
-  double res_fpi;
-  double tmp;
-
   xbt_assert(x > 0.0, "Don't call me with stupid values!");
-  tmp = x * var->weight * var->weight;
-  res_fpi = tmp * (9.0 * x + 24.0);
+  double tmp = x * var->weight * var->weight;
+  double res_fpi = tmp * (9.0 * x + 24.0);
 
   if (res_fpi <= 0.0)
     return 0.0;
index d457bce..c333364 100644 (file)
@@ -219,7 +219,7 @@ static void onActionStateChange(simgrid::surf::CpuAction *action, simgrid::surf:
     if (vm) // If it's a VM, take the corresponding PM
       host = vm->getPm()->extension<simgrid::surf::HostImpl>();
 
-    HostEnergy *host_energy = host->p_host->extension<HostEnergy>();
+    HostEnergy *host_energy = host->piface->extension<HostEnergy>();
 
     if(host_energy->last_updated < surf_get_clock())
       host_energy->update();
index d85bc7d..1a90883 100644 (file)
 #include "src/surf/network_interface.hpp"
 #include "surf/surf_routing.h" // FIXME: brain dead public header
 
-#include "src/surf/AsImpl.hpp"
-#include "src/surf/AsCluster.hpp"
-#include "src/surf/AsClusterTorus.hpp"
-#include "src/surf/AsClusterFatTree.hpp"
-#include "src/surf/AsClusterDragonfly.hpp"
-#include "src/surf/AsDijkstra.hpp"
-#include "src/surf/AsFloyd.hpp"
-#include "src/surf/AsFull.hpp"
-#include "src/surf/AsNone.hpp"
-#include "src/surf/AsVivaldi.hpp"
+#include "src/routing/AsImpl.hpp"
+#include "src/routing/AsCluster.hpp"
+#include "src/routing/AsClusterTorus.hpp"
+#include "src/routing/AsClusterFatTree.hpp"
+#include "src/routing/AsClusterDragonfly.hpp"
+#include "src/routing/AsDijkstra.hpp"
+#include "src/routing/AsFloyd.hpp"
+#include "src/routing/AsFull.hpp"
+#include "src/routing/AsNone.hpp"
+#include "src/routing/AsVivaldi.hpp"
 
 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(surf_parse);
 
index 313b39d..233e665 100644 (file)
@@ -15,7 +15,7 @@
 #include "simgrid/sg_config.h"
 #include "storage_interface.hpp"
 
-#include "src/surf/AsImpl.hpp"
+#include "src/routing/AsImpl.hpp"
 #include "src/surf/xml/platf.hpp" // FIXME: move that back to the parsing area
 
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_route, surf, "Routing part of surf");
@@ -90,7 +90,7 @@ namespace routing {
  * \param route where to store the list of links.
  *              If *route=nullptr, create a short lived dynar. Else, fill the provided dynar
  * \param latency where to store the latency experienced on the path (or nullptr if not interested)
- *                It is the caller responsability to initialize latency to 0 (we add to provided route)
+ *                It is the caller responsibility to initialize latency to 0 (we add to provided route)
  * \pre route!=nullptr
  *
  * walk through the routing components tree and find a route between hosts
index 274ff24..61983b4 100644 (file)
@@ -12,7 +12,7 @@
 
 #include "surf_interface.hpp"
 #include "src/surf/xml/platf_private.hpp" // FIXME: including this here is pure madness. KILKILKIL XML.
-#include "src/surf/AsImpl.hpp"
+#include "src/routing/AsImpl.hpp"
 
 #include <float.h>
 #include <vector>
index 6e9cf0c..230e330 100644 (file)
@@ -4,9 +4,15 @@
 /* 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 <cstdlib>
+
+#include <atomic>
 #include <exception>
+#include <string>
 #include <typeinfo>
+#include <vector>
 #include <memory>
+#include <mutex>
 
 #include <xbt/backtrace.hpp>
 #include <xbt/exception.hpp>
@@ -68,5 +74,66 @@ void logException(
   }
 }
 
+static void showBacktrace(std::vector<xbt_backtrace_location_t>& bt)
+{
+  std::vector<std::string> res = resolveBacktrace(&bt[0], bt.size());
+  XBT_LOG(xbt_log_priority_critical, "Current backtrace:");
+  for (std::string const& s : res)
+    XBT_LOG(xbt_log_priority_critical, "  -> %s", s.c_str());
 }
+
+static std::terminate_handler previous_terminate_handler = nullptr;
+
+static void handler()
+{
+  // Avoid doing crazy things if we get an uncaught exception inside
+  // an uncaught exception
+  static std::atomic_flag lock = ATOMIC_FLAG_INIT;
+  if (lock.test_and_set()) {
+    XBT_ERROR("Multiple uncaught exceptions");
+    std::abort();
+  }
+
+  // Get the current backtrace and exception
+  auto e = std::current_exception();
+  auto bt = backtrace();
+  try {
+    std::rethrow_exception(e);
+  }
+
+  // We manage C++ exception ourselves
+  catch (std::exception& e) {
+    logException(xbt_log_priority_critical, "Uncaught exception", e);
+    showBacktrace(bt);
+    std::abort();
+  }
+
+  // We don't know how to manage other exceptions
+  catch (...) {
+    // If there was another handler let's delegate to it
+    if (previous_terminate_handler)
+      previous_terminate_handler();
+    else {
+      XBT_ERROR("Unknown uncaught exception");
+      showBacktrace(bt);
+      std::abort();
+    }
+  }
+
+}
+
+void installExceptionHandler()
+{
+  static std::once_flag handler_flag;
+  std::call_once(handler_flag, [] {
+    previous_terminate_handler = std::set_terminate(handler);
+  });
+}
+
+}
+}
+
+void xbt_set_terminate()
+{
+  simgrid::xbt::installExceptionHandler();
 }
index 9e022d7..8cd20e0 100644 (file)
@@ -48,9 +48,13 @@ void xbt_fifo_free(xbt_fifo_t l)
  */
 void xbt_fifo_reset(xbt_fifo_t l)
 {
-  xbt_fifo_item_t b, tmp;
+  xbt_fifo_item_t b = xbt_fifo_get_first_item(l);
 
-  for (b = xbt_fifo_get_first_item(l); b; tmp = b, b = b->next, xbt_fifo_free_item(tmp));
+  while (b) {
+    xbt_fifo_item_t tmp = b;
+    b = b->next;
+    xbt_fifo_free_item(tmp);
+  }
   l->head = NULL;
   l->tail = NULL;
 }
index 3451b60..13ec9e3 100644 (file)
@@ -137,6 +137,8 @@ static void xbt_postexit(void)
 /** @brief Initialize the xbt mechanisms. */
 void xbt_init(int *argc, char **argv)
 {
+  xbt_set_terminate();
+
   if (xbt_initialized++) {
     XBT_DEBUG("XBT was initialized %d times.", xbt_initialized);
     return;