Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'issue105' into 'master'
authorBruno Donassolo <bruno.donassolo@inria.fr>
Mon, 28 Mar 2022 08:17:16 +0000 (08:17 +0000)
committerBruno Donassolo <bruno.donassolo@inria.fr>
Mon, 28 Mar 2022 08:17:16 +0000 (08:17 +0000)
Fix #105 - Unify expand and expand_add

Closes #105

See merge request simgrid/simgrid!92

137 files changed:
CMakeLists.txt
ChangeLog
MANIFEST.in
NEWS
README.md
doc/doxygen/inside_release.doc
docs/source/Configuring_SimGrid.rst
docs/source/Doxyfile
docs/source/Release_Notes.rst
docs/source/Tutorial_Model-checking.rst
docs/source/_ext/javasphinx/javasphinx/apidoc.py
docs/source/_ext/javasphinx/javasphinx/compiler.py
docs/source/_ext/javasphinx/javasphinx/domain.py
docs/source/_ext/javasphinx/javasphinx/formatter.py
docs/source/_ext/javasphinx/javasphinx/htmlrst.py
docs/source/_ext/javasphinx/javasphinx/util.py
docs/source/app_s4u.rst
docs/source/app_smpi.rst
docs/source/conf.py
examples/c/actor-exiting/actor-exiting.tesh
examples/cpp/actor-exiting/s4u-actor-exiting.tesh
examples/cpp/synchro-barrier/s4u-mc-synchro-barrier.tesh
examples/cpp/synchro-mutex/s4u-mc-synchro-mutex.tesh
examples/cpp/synchro-mutex/s4u-synchro-mutex.cpp
examples/cpp/synchro-mutex/s4u-synchro-mutex.tesh
examples/cpp/synchro-semaphore/s4u-mc-synchro-semaphore.tesh
examples/platforms/ns3-big-cluster.xml
examples/python/synchro-mutex/synchro-mutex.py
examples/python/synchro-mutex/synchro-mutex.tesh
include/simgrid/s4u/Activity.hpp
include/simgrid/s4u/Barrier.hpp
include/simgrid/s4u/Comm.hpp
include/simgrid/s4u/Exec.hpp
include/simgrid/s4u/NetZone.hpp
include/simgrid/s4u/Semaphore.hpp
include/simgrid/s4u/VirtualMachine.hpp
include/simgrid/simix.h
include/xbt/base.h
setup.py
sonar-project.properties
src/bindings/python/simgrid_python.cpp
src/kernel/EngineImpl.cpp
src/kernel/EngineImpl.hpp
src/kernel/activity/ActivityImpl.cpp
src/kernel/activity/ActivityImpl.hpp
src/kernel/activity/BarrierImpl.hpp
src/kernel/actor/ActorImpl.cpp
src/kernel/actor/ActorImpl.hpp
src/kernel/resource/DiskImpl.hpp
src/kernel/resource/VirtualMachineImpl.cpp
src/kernel/resource/profile/Profile.cpp
src/kernel/resource/profile/Profile.hpp
src/kernel/resource/profile/ProfileBuilder.cpp
src/kernel/routing/RoutedZone.cpp
src/mc/ModelChecker.hpp
src/mc/VisitedState.cpp
src/mc/api.cpp
src/mc/api.hpp
src/mc/api/State.hpp
src/mc/explo/CommunicationDeterminismChecker.cpp
src/mc/explo/DFSExplorer.cpp
src/mc/explo/LivenessChecker.cpp
src/mc/mc_global.cpp
src/mc/mc_record.cpp
src/mc/remote/AppSide.cpp
src/mc/transition/TransitionAny.cpp
src/mc/transition/TransitionComm.cpp
src/s4u/s4u_Activity.cpp
src/s4u/s4u_Actor.cpp
src/s4u/s4u_Barrier.cpp
src/s4u/s4u_Comm.cpp
src/s4u/s4u_Engine.cpp
src/s4u/s4u_Mutex.cpp
src/s4u/s4u_Netzone.cpp
src/s4u/s4u_Semaphore.cpp
src/smpi/bindings/smpi_pmpi.cpp
src/smpi/bindings/smpi_pmpi_coll.cpp
src/smpi/bindings/smpi_pmpi_comm.cpp
src/smpi/bindings/smpi_pmpi_file.cpp
src/smpi/bindings/smpi_pmpi_topo.cpp
src/smpi/bindings/smpi_pmpi_win.cpp
src/smpi/colls/alltoall/alltoall-pair.cpp
src/smpi/colls/barrier/barrier-mvapich2-pair.cpp
src/smpi/colls/barrier/barrier-ompi.cpp
src/smpi/include/private.hpp
src/smpi/include/smpi_actor.hpp
src/smpi/include/smpi_comm.hpp
src/smpi/include/smpi_op.hpp
src/smpi/include/smpi_utils.hpp
src/smpi/include/smpi_win.hpp
src/smpi/internals/smpi_actor.cpp
src/smpi/internals/smpi_config.cpp
src/smpi/internals/smpi_utils.cpp
src/smpi/mpi/smpi_comm.cpp
src/smpi/mpi/smpi_file.cpp
src/smpi/mpi/smpi_op.cpp
src/smpi/mpi/smpi_request.cpp
src/smpi/mpi/smpi_win.cpp
src/smpi/smpirun.in
src/surf/disk_s19.cpp
teshsuite/mc/random-bug/random-bug-nocrash.tesh
teshsuite/mc/random-bug/random-bug.tesh
teshsuite/s4u/monkey-masterworkers/monkey-masterworkers.py
teshsuite/smpi/MBI/CMakeLists.txt
teshsuite/smpi/MBI/CollArgGenerator.py [new file with mode: 0755]
teshsuite/smpi/MBI/CollComGenerator.py [new file with mode: 0755]
teshsuite/smpi/MBI/CollLocalConcurrencyGenerator.py [new file with mode: 0755]
teshsuite/smpi/MBI/CollMatchingGenerator.py
teshsuite/smpi/MBI/CollP2PMatchingGenerator.py [new file with mode: 0755]
teshsuite/smpi/MBI/CollP2PMessageRaceGenerator.py [new file with mode: 0755]
teshsuite/smpi/MBI/CollTopoGenerator.py [new file with mode: 0755]
teshsuite/smpi/MBI/MBI.py
teshsuite/smpi/MBI/MBIutils.py
teshsuite/smpi/MBI/MissingWaitandStartGenerator.py [new file with mode: 0755]
teshsuite/smpi/MBI/P2PArgGenerator.py [new file with mode: 0755]
teshsuite/smpi/MBI/P2PComGenerator.py [new file with mode: 0755]
teshsuite/smpi/MBI/P2PInvalidComGenerator.py [new file with mode: 0755]
teshsuite/smpi/MBI/P2PLocalConcurrencyGenerator.py [new file with mode: 0755]
teshsuite/smpi/MBI/P2PMatchingANYSRCGenerator.py [new file with mode: 0755]
teshsuite/smpi/MBI/P2PMatchingGenerator.py [new file with mode: 0755]
teshsuite/smpi/MBI/P2PProbeGenerator.py [new file with mode: 0755]
teshsuite/smpi/MBI/RMAArgGenerator.py [new file with mode: 0755]
teshsuite/smpi/MBI/RMAInvalidArgGenerator.py [new file with mode: 0755]
teshsuite/smpi/MBI/RMALocalLocalConcurrencyGenerator.py [new file with mode: 0755]
teshsuite/smpi/MBI/RMAP2PGlobalConcurrencyGenerator.py [new file with mode: 0755]
teshsuite/smpi/MBI/RMARemoteLocalConcurrencyGenerator.py [new file with mode: 0755]
teshsuite/smpi/MBI/RMARemoteRemoteConcurrencyGenerator.py [new file with mode: 0755]
teshsuite/smpi/MBI/RMAReqLifecycleGenerator.py [new file with mode: 0755]
teshsuite/smpi/MBI/RMAWinBufferGenerator.py [new file with mode: 0755]
teshsuite/smpi/MBI/ResleakGenerator.py
teshsuite/smpi/MBI/generator_utils.py
teshsuite/smpi/MBI/simgrid.py
teshsuite/smpi/coll-allreduce-with-leaks/coll-allreduce-with-leaks.tesh
teshsuite/smpi/coll-allreduce-with-leaks/mc-coll-allreduce-with-leaks.tesh
teshsuite/smpi/mpich3-test/runtests
tools/jenkins/Coverage.sh
tools/simgrid-monkey

index eb7d618..1dce9a7 100644 (file)
@@ -1,7 +1,7 @@
 # Build the version number
 
 set(SIMGRID_VERSION_MAJOR "3")
-set(SIMGRID_VERSION_MINOR "30")
+set(SIMGRID_VERSION_MINOR "31")
 set(SIMGRID_VERSION_PATCH "1") # odd => git branch; even => stable release or released snapshot
 
 if(${SIMGRID_VERSION_PATCH} EQUAL "0")
index ce0caeb..1c5f22d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,12 @@
-SimGrid (3.30.1) NOT RELEASED YET (v3.31 expected March 20. 2022, 15:33 UTC)
+SimGrid (3.31.1) NOT RELEASED YET (v3.32 expected June 21. 2022, 09:13 UTC)
+
+----------------------------------------------------------------------------
+
+S4U:
+ - kill signal Comm::on_completion that was not working anyway.
+ - Expose signals Activity::on_suspend and Activity::on_resume
+
+SimGrid (3.31) March 22. 2022.
 
 The ненасильство release. We stand against war.
 
@@ -23,6 +31,9 @@ SMPI:
  - tracing: ensure that we dump the TI traces continuously during execution and
    not just at the end, reducing memory cost and performance hit.
  - Update OpenMPI collectives selection logic to match current one (4.1.2)
+ - Add a coherence check for collective operation order and root/MPI_Op
+   coherence. Potentially costly so not activated unless smpi:pendantic is set
+   or -analyze is given.
 
 S4U:
  - New signal: Engine::on_simulation_start_cb()
index 28e33cb..ffbad75 100644 (file)
@@ -865,9 +865,31 @@ include teshsuite/s4u/wait-all-for/wait-all-for.cpp
 include teshsuite/s4u/wait-all-for/wait-all-for.tesh
 include teshsuite/s4u/wait-any-for/wait-any-for.cpp
 include teshsuite/s4u/wait-any-for/wait-any-for.tesh
+include teshsuite/smpi/MBI/CollArgGenerator.py
+include teshsuite/smpi/MBI/CollComGenerator.py
+include teshsuite/smpi/MBI/CollLocalConcurrencyGenerator.py
 include teshsuite/smpi/MBI/CollMatchingGenerator.py
+include teshsuite/smpi/MBI/CollP2PMatchingGenerator.py
+include teshsuite/smpi/MBI/CollP2PMessageRaceGenerator.py
+include teshsuite/smpi/MBI/CollTopoGenerator.py
 include teshsuite/smpi/MBI/MBI.py
 include teshsuite/smpi/MBI/MBIutils.py
+include teshsuite/smpi/MBI/MissingWaitandStartGenerator.py
+include teshsuite/smpi/MBI/P2PArgGenerator.py
+include teshsuite/smpi/MBI/P2PComGenerator.py
+include teshsuite/smpi/MBI/P2PInvalidComGenerator.py
+include teshsuite/smpi/MBI/P2PLocalConcurrencyGenerator.py
+include teshsuite/smpi/MBI/P2PMatchingANYSRCGenerator.py
+include teshsuite/smpi/MBI/P2PMatchingGenerator.py
+include teshsuite/smpi/MBI/P2PProbeGenerator.py
+include teshsuite/smpi/MBI/RMAArgGenerator.py
+include teshsuite/smpi/MBI/RMAInvalidArgGenerator.py
+include teshsuite/smpi/MBI/RMALocalLocalConcurrencyGenerator.py
+include teshsuite/smpi/MBI/RMAP2PGlobalConcurrencyGenerator.py
+include teshsuite/smpi/MBI/RMARemoteLocalConcurrencyGenerator.py
+include teshsuite/smpi/MBI/RMARemoteRemoteConcurrencyGenerator.py
+include teshsuite/smpi/MBI/RMAReqLifecycleGenerator.py
+include teshsuite/smpi/MBI/RMAWinBufferGenerator.py
 include teshsuite/smpi/MBI/ResleakGenerator.py
 include teshsuite/smpi/MBI/generator_utils.py
 include teshsuite/smpi/MBI/simgrid.py
diff --git a/NEWS b/NEWS
index 5c25d2a..f610e53 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,12 +1,23 @@
+                    _               _____  _________
+__   _____ _ __ ___(_) ___  _ __   |___ / |___ /___ \
+\ \ / / _ \ '__/ __| |/ _ \| '_ \    |_ \   |_ \ __) |
+ \ V /  __/ |  \__ \ | (_) | | | |  ___) | ___) / __/
+  \_/ \___|_|  |___/_|\___/|_| |_| |____(_)____/_____|
+               (unreleased)
+
                     _               _____  _____ _
 __   _____ _ __ ___(_) ___  _ __   |___ / |___ // |
 \ \ / / _ \ '__/ __| |/ _ \| '_ \    |_ \   |_ \| |
  \ V /  __/ |  \__ \ | (_) | | | |  ___) | ___) | |
   \_/ \___|_|  |___/_|\___/|_| |_| |____(_)____/|_|
-               (unreleased)
+               March 22. 2022
 
 The ненасильство release. We stand against war.
 
+  * Refactoring the model-checker, enabling synchronization objects and future improvements
+  * Introducing BMF sharing, enabling ptasks in regular models (experimental)
+  * Further complete Python bindings (Mutex, Semaphore and Barrier)
+ * (+ internal refactoring, many bug fixes and documentation improvement)
                     _               _____  _____  ___
 __   _____ _ __ ___(_) ___  _ __   |___ / |___ / / _ \
 \ \ / / _ \ '__/ __| |/ _ \| '_ \    |_ \   |_ \| | | |
index 49369d4..8c81d3e 100644 (file)
--- a/README.md
+++ b/README.md
@@ -34,13 +34,11 @@ or on the #simgrid IRC channel of the oftc network.
 Last, the main development of SimGrid is done on [Framagit](https://framagit.org/simgrid/simgrid/),
 but we also maintain a [GitHub mirror](https://github.com/simgrid/simgrid/) and an [Inria GitLab mirror](https://gitlab.inria.fr/simgrid/simgrid),
 
-Thanks for using our software. Please do great things with it and tell
-the world about it. Tell us, too, because we love to have positive
-feedback. Welcome to our community.
+Thanks for using our software. Please do great things with it and tell the world about it.
+Tell us, too, because we love to have positive feedback. Welcome to our community.
 
 Cheers,
 Da SimGrid Team.
 
 [license-badge]: https://img.shields.io/badge/License-LGPL%20v2.1-blue.svg
 [release-badge]: https://img.shields.io/github/release/simgrid/simgrid.svg
-[release-link]:  https://gforge.inria.fr/frs/?group_id=12
index fd87aeb..1620515 100644 (file)
@@ -23,6 +23,7 @@ Please apply the following checklist before releasing.
 - Release notes in the documentation
   - The content of the future mail is part of the documentation, since
     we won't send mails once gforge is definitly turned off.
+  - The date of the release is marked in the title
 - Tests
   - The "make distcheck" target works (tested by jenkins)
   - All tests pass on everything on ci + AppVeyor
@@ -73,7 +74,7 @@ Please apply the following checklist before releasing.
 @subsection inside_release_c_publishing Publishing the release if it's a stable one (3.XX not 3.XX.Y)
 
 - Announce the release
- - Mail the simgrid-user mailing list
+ - Mail the https://sympa.inria.fr/sympa/review/simgrid-community mailing list
     - the NEWS chunk in the mail;
     - Hall of Fame in the mail
       git shortlog -se v3.29..
@@ -106,6 +107,7 @@ Please apply the following checklist before releasing.
   - Kill the one for the current release and remove all code that were
     mandated by the deprecated functions (both in source and headers).
   - Do the possible cleanups now that these features are gone.
+- Regenerate the unstable docker with this new version
 
 Release numbering semantic:
   - 3.X is a named release.
index f8d9242..f907c9d 100644 (file)
@@ -84,6 +84,9 @@ Existing Configuration Items
   option. For example, ``--cfg=plugin:help`` will give you the list
   of plugins available in your installation of SimGrid.
 
+- **bmf/max-iterations:** :ref:`cfg=bmf/max-iterations`
+- **bmf/precision:** :ref:`cfg=bmf/precision`
+
 - **contexts/factory:** :ref:`cfg=contexts/factory`
 - **contexts/guard-size:** :ref:`cfg=contexts/guard-size`
 - **contexts/nthreads:** :ref:`cfg=contexts/nthreads`
@@ -311,14 +314,16 @@ configurations.
     the dependency induced by the backbone), but through a complicated
     and slow pattern that follows the actual dependencies.
 
+.. _cfg=bmf/precision:
 .. _cfg=maxmin/precision:
 .. _cfg=surf/precision:
 
 Numerical Precision
 ...................
 
-**Option** ``maxmin/precision`` **Default:** 0.00001 (in flops or bytes) |br|
-**Option** ``surf/precision`` **Default:** 0.00001 (in seconds)
+**Option** ``maxmin/precision`` **Default:** 1e-5 (in flops or bytes) |br|
+**Option** ``surf/precision`` **Default:** 1e-9 (in seconds) |br|
+**Option** ``bmf/precision`` **Default:** 1e-12 (no unit)
 
 The analytical models handle a lot of floating point values. It is
 possible to change the epsilon used to update and compare them through
@@ -347,6 +352,17 @@ Such limitations help both to the simulation speed and simulation accuracy
 on highly constrained scenarios, but the simulation speed suffers of this
 setting on regular (less constrained) scenarios so it is off by default.
 
+.. _cfg=bmf/max-iterations:
+
+BMF settings
+............
+
+**Option** ``bmf/max-iterations`` **Default:** 1000
+
+It may happen in some settings that the BMF solver fails to converge to
+a solution, so there is a hard limit on the amount of iteration count to
+avoid infinite loops.
+
 .. _options_model_network:
 
 Configuring the Network Model
index 35eefa0..c9ea8a3 100644 (file)
@@ -69,7 +69,7 @@ PREDEFINED             += \
     XBT_ATTRIB_NORETURN= \
     XBT_ATTRIB_UNUSED= \
     XBT_LOG_NEW_DEFAULT_SUBCATEGORY(cname,parent,desc)= \
-    XBT_ATTRIB_DEPRECATED_v332(mesg)= \
     XBT_ATTRIB_DEPRECATED_v333(mesg)= \
     XBT_ATTRIB_DEPRECATED_v334(mesg)= \
-    XBT_ATTRIB_DEPRECATED_v335(mesg)=
+    XBT_ATTRIB_DEPRECATED_v335(mesg)= \
+    XBT_ATTRIB_DEPRECATED_v336(mesg)=
index 400c1c9..6dfa36e 100644 (file)
@@ -468,10 +468,8 @@ Also, the algorithm tutorial can now be taken in Python, for those of you allerg
 Finally, on the SMPI front, we introduced a :ref:`new documentation section <models_calibration>` on calibrating the SMPI models from your
 measurements and fixed some issues with the replay mechanism.
 
-Version 3.31 (not released yet)
--------------------------------
-
-Expected: spring 2022
+Version 3.31 (March 22. 2022)
+-----------------------------
 
 **On the model checking front**, the long awaited big bang finally occurred, greatly simplifying future evolution.
 
@@ -528,6 +526,7 @@ several threads, and thus capable of utilizing more cores than a classical :cpp:
 it straightforward to model multithreaded computational kernels, and it comes with an illustrating example. It can be seen as a simplified ptask, but
 since it does not mix bytes and flops and has a homogeneous consumption over a single CPU, it perfectly fits with the classical SimGrid model.
 
+This release also introduces steadily progress **on the bindings front**, introducing in particular the Mutex, Barrier and Semaphore to your python scripts.
 
 .. |br| raw:: html
 
index 9bf4535..0a5f1ca 100644 (file)
@@ -187,16 +187,16 @@ now read it together. It can be split in several parts:
     .. code-block:: console
 
        [0.000000] [mc_ModelChecker/INFO] Counter-example execution trace:
-       [0.000000] [mc_ModelChecker/INFO]   [(1)Tremblay (server)] iRecv(dst=(1)Tremblay (server), buff=(verbose only), size=(verbose only))
-       [0.000000] [mc_ModelChecker/INFO]   [(2)Jupiter (client)] iSend(src=(2)Jupiter (client), buff=(verbose only), size=(verbose only))
-       [0.000000] [mc_ModelChecker/INFO]   [(1)Tremblay (server)] Wait(comm=(verbose only) [(2)Jupiter (client)-> (1)Tremblay (server)])
-       [0.000000] [mc_ModelChecker/INFO]   [(1)Tremblay (server)] iRecv(dst=(1)Tremblay (server), buff=(verbose only), size=(verbose only))
-       [0.000000] [mc_ModelChecker/INFO]   [(2)Jupiter (client)] Wait(comm=(verbose only) [(2)Jupiter (client)-> (1)Tremblay (server)])
-       [0.000000] [mc_ModelChecker/INFO]   [(4)Ginette (client)] iSend(src=(4)Ginette (client), buff=(verbose only), size=(verbose only))
-       [0.000000] [mc_ModelChecker/INFO]   [(1)Tremblay (server)] Wait(comm=(verbose only) [(4)Ginette (client)-> (1)Tremblay (server)])
-       [0.000000] [mc_ModelChecker/INFO]   [(1)Tremblay (server)] iRecv(dst=(1)Tremblay (server), buff=(verbose only), size=(verbose only))
-       [0.000000] [mc_ModelChecker/INFO]   [(3)Bourassa (client)] iSend(src=(3)Bourassa (client), buff=(verbose only), size=(verbose only))
-       [0.000000] [mc_ModelChecker/INFO]   [(1)Tremblay (server)] Wait(comm=(verbose only) [(3)Bourassa (client)-> (1)Tremblay (server)])
+       [0.000000] [mc_ModelChecker/INFO]   1: iRecv(mbox=0)
+       [0.000000] [mc_ModelChecker/INFO]   2: iSend(mbox=0)
+       [0.000000] [mc_ModelChecker/INFO]   1: WaitComm(from 2 to 1, mbox=0, no timeout)
+       [0.000000] [mc_ModelChecker/INFO]   1: iRecv(mbox=0)
+       [0.000000] [mc_ModelChecker/INFO]   2: WaitComm(from 2 to 1, mbox=0, no timeout)
+       [0.000000] [mc_ModelChecker/INFO]   4: iSend(mbox=0)
+       [0.000000] [mc_ModelChecker/INFO]   1: WaitComm(from 4 to 1, mbox=0, no timeout)
+       [0.000000] [mc_ModelChecker/INFO]   1: iRecv(mbox=0)
+       [0.000000] [mc_ModelChecker/INFO]   3: iSend(mbox=0)
+       [0.000000] [mc_ModelChecker/INFO]   1: WaitComm(from 3 to 1, mbox=0, no timeout)
 
   - Then, the execution path is given.
 
@@ -237,9 +237,7 @@ now read it together. It can be split in several parts:
 
     .. code-block:: console
 
-       [0.000000] [mc_safety/INFO] Expanded states = 22
-       [0.000000] [mc_safety/INFO] Visited states = 56
-       [0.000000] [mc_safety/INFO] Executed transitions = 52
+       [0.000000] [mc_dfs/INFO] DFS exploration ended. 22 unique states visited; 4 backtracks (56 transition replays, 30 states visited overall)
 
   - Finally, the application stack trace is displayed as the model-checker sees it. It should be the same as the one displayed from the
     application side, unless you found a bug our tools.
index b0de46f..c4eca15 100755 (executable)
@@ -18,7 +18,7 @@ from __future__ import print_function, unicode_literals
 
 try:
    import cPickle as pickle
-except:
+except ImportError:
    import pickle
 
 import hashlib
@@ -37,8 +37,7 @@ import javasphinx.util as util
 def encode_output(s):
    if isinstance(s, str):
       return s
-   else:
-      return s.encode('utf-8')
+   return s.encode('utf-8')
 
 def find_source_files(input_path, excludes):
     """ Get a list of filenames for all Java source files within the given
index 807d027..e4fe623 100644 (file)
@@ -98,12 +98,12 @@ class JavadocRestCompiler(object):
         if see.startswith('<a href'):
             # HTML link -- <a href="...">...</a>
             return self.__html_to_rst(see)
-        elif '"' in see:
+        if '"' in see:
             # Plain text
             return see
-        else:
-            # Type reference (default)
-            return ':java:ref:`%s`' % (see.replace('#', '.').replace(' ', ''),)
+
+        # Type reference (default)
+        return ':java:ref:`%s`' % (see.replace('#', '.').replace(' ', ''),)
 
     def compile_type(self, declaration):
         signature = util.StringBuilder()
index 275f6c8..3784d8a 100644 (file)
@@ -132,9 +132,9 @@ class JavaObject(ObjectDescription):
                     parts.append(nodes.Text(dim, dim))
 
             return parts
-        else:
-            type_repr = formatter.output_type(typ).build()
-            return [nodes.Text(type_repr, type_repr)]
+
+        type_repr = formatter.output_type(typ).build()
+        return [nodes.Text(type_repr, type_repr)]
 
     def _build_type_node_list(self, types):
         parts = self._build_type_node(types[0])
@@ -149,10 +149,9 @@ class JavaObject(ObjectDescription):
 
         if handle:
             return handle(sig, signode)
-        else:
-            raise NotImplementedError
+        raise NotImplementedError
 
-    def get_index_text(self, package, type, name):
+    def get_index_text(self, package, typ, name):
         raise NotImplementedError
 
     def get_package(self):
@@ -163,9 +162,9 @@ class JavaObject(ObjectDescription):
 
     def add_target_and_index(self, name, sig, signode):
         package = self.get_package()
-        type = self.get_type();
+        typ = self.get_type()
 
-        fullname = '.'.join(filter(None, (package, type, name)))
+        fullname = '.'.join(filter(None, (package, typ, name)))
         basename = fullname.partition('(')[0]
 
         # note target
@@ -185,7 +184,7 @@ class JavaObject(ObjectDescription):
 
             objects[fullname] = (self.env.docname, self.objtype, basename)
 
-        indextext = self.get_index_text(package, type, name)
+        indextext = self.get_index_text(package, typ, name)
         if indextext:
             self.indexnode['entries'].append(_create_indexnode(indextext, fullname))
 
@@ -249,7 +248,7 @@ class JavaMethod(JavaObject):
         param_reprs = [formatter.output_type(param.type, with_generics=False).build() for param in member.parameters]
         return member.name + '(' + ', '.join(param_reprs) + ')'
 
-    def get_index_text(self, package, type, name):
+    def get_index_text(self, package, typ, name):
         return _('%s (Java method)' % (name,))
 
 class JavaConstructor(JavaObject):
@@ -289,7 +288,7 @@ class JavaConstructor(JavaObject):
         param_reprs = [formatter.output_type(param.type, with_generics=False).build() for param in member.parameters]
         return '%s(%s)' % (member.name, ', '.join(param_reprs))
 
-    def get_index_text(self, package, type, name):
+    def get_index_text(self, package, typ, name):
         return _('%s (Java constructor)' % (name,))
 
 class JavaType(JavaObject):
@@ -356,7 +355,7 @@ class JavaType(JavaObject):
 
         return member.name
 
-    def get_index_text(self, package, type, name):
+    def get_index_text(self, package, typ, name):
         return _('%s (Java %s)' % (name, self.declaration_type))
 
 class JavaField(JavaObject):
@@ -392,7 +391,7 @@ class JavaField(JavaObject):
 
         return declarator.name
 
-    def get_index_text(self, package, type, name):
+    def get_index_text(self, package, typ, name):
         return _('%s (Java field)' % (name,))
 
 class JavaPackage(Directive):
@@ -557,7 +556,7 @@ class JavaDomain(Domain):
         for fullname, (_, _, basename) in objects.items():
             if fullname.endswith(suffix):
                 return make_ref(fullname)
-            elif basename.endswith(basename_suffix):
+            if basename.endswith(basename_suffix):
                 basename_match = fullname
 
         if basename_match:
@@ -578,17 +577,15 @@ class JavaDomain(Domain):
         if ref:
             ref.append(contnode)
             return ref
-        else:
-            return None
+        return None
 
     def get_objects(self):
-        for refname, (docname, type, _) in self.data['objects'].items():
-            yield (refname, refname, type, docname, refname, 1)
+        for refname, (docname, typ, _) in self.data['objects'].items():
+            yield (refname, refname, typ, docname, refname, 1)
 
 
 def _create_indexnode(indextext, fullname):
     # See https://github.com/sphinx-doc/sphinx/issues/2673
     if version_info < (1, 4):
         return ('single', indextext, fullname, '')
-    else:
-        return ('single', indextext, fullname, '', None)
+    return ('single', indextext, fullname, '', None)
index 51b4ce7..ce6f6f5 100644 (file)
@@ -50,28 +50,28 @@ def output_annotation(annotation, output):
     output.append(' ')
 
 @formatter
-def output_type(type, output, with_generics=True):
-    if not type:
+def output_type(typ, output, with_generics=True):
+    if not typ:
         output.append('void')
         return
 
-    if type.dimensions:
-        dim = '[]' * len(type.dimensions)
+    if typ.dimensions:
+        dim = '[]' * len(typ.dimensions)
     else:
         dim = ''
 
-    if isinstance(type, javalang.tree.BasicType):
-        output.append(type.name)
+    if isinstance(typ, javalang.tree.BasicType):
+        output.append(typ.name)
     else:
-        while type:
-            output.append(type.name)
+        while typ:
+            output.append(typ.name)
 
             if with_generics:
-                output_type_args(type.arguments, output)
+                output_type_args(typ.arguments, output)
 
-            type = type.sub_type
+            typ = typ.sub_type
 
-            if type:
+            if typ:
                 output.append('.')
     output.append(dim)
 
index b34f1f2..687a034 100644 (file)
@@ -47,8 +47,7 @@ class Converter(object):
     def _unicode(self, s):
         if isinstance(s, unicode):
             return s
-        else:
-            return unicode(s, 'utf8')
+        return unicode(s, 'utf8')
 
     def _separate(self, s):
         return u'\n\n' + s + u'\n\n'
@@ -72,16 +71,14 @@ class Converter(object):
     def _role(self, role, s, label=None):
         if label:
             return self._escape_inline(':%s:`%s <%s>`' % (role, label, s))
-        else:
-            return self._escape_inline(':%s:`%s`' % (role, s))
+        return self._escape_inline(':%s:`%s`' % (role, s))
 
     def _directive(self, directive, body=None):
         header = '\n\n.. %s::\n\n' % (directive,)
 
         if body:
             return header + self._left_justify(body, 3) + '\n\n'
-        else:
-            return header + '\n'
+        return header + '\n'
 
     def _hyperlink(self, target, label):
         return self._escape_inline('`%s <%s>`_' % (label, target))
@@ -102,15 +99,14 @@ class Converter(object):
 
         if shift < 0:
             return '\n'.join(l[-shift:] for l in lines)
-        else:
-            prefix = ' ' * shift
-            return '\n'.join(prefix + l for l in lines)
+
+        prefix = ' ' * shift
+        return '\n'.join(prefix + l for l in lines)
 
     def _compress_whitespace(self, s, replace=' ', newlines=True):
         if newlines:
             return self._whitespace_with_newline.sub(replace, s)
-        else:
-            return self._whitespace.sub(replace, s)
+        return self._whitespace.sub(replace, s)
 
     # --------------------------------------------------------------------------
     # ---- DOM Tree Processing ----
@@ -269,16 +265,15 @@ class Converter(object):
         if node.name == 'a':
             if 'name' in node.attrs:
                 return self._separate('.. _' + node['name'] + ':')
-            elif 'href' in node.attrs:
+            if 'href' in node.attrs:
                 target = node['href']
                 label = self._compress_whitespace(self._process_text(node).strip('\n'))
 
                 if target.startswith('#'):
                     return self._role('ref', target[1:], label)
-                elif target.startswith('@'):
+                if target.startswith('@'):
                     return self._role('java:ref', target[1:], label)
-                else:
-                    return self._hyperlink(target, label)
+                return self._hyperlink(target, label)
 
         if node.name == 'ul':
             items = [self._process(n) for n in node.find_all('li', recursive=False)]
index 2de85d5..8e5f2a8 100644 (file)
@@ -30,8 +30,8 @@ class StringBuilder(list):
 
 class Directive(object):
 
-    def __init__(self, type, argument=''):
-        self.type = type
+    def __init__(self, typ, argument=''):
+        self.type = typ
         self.argument = argument
 
         self.options = []
index 2047854..ededc62 100644 (file)
@@ -2123,6 +2123,17 @@ Suspending and resuming an activity
       .. doxygenfunction:: simgrid::s4u::Activity::resume
       .. doxygenfunction:: simgrid::s4u::Activity::is_suspended
 
+Signals
+-------
+
+.. tabs::
+
+   .. group-tab:: C++
+
+      .. doxygenfunction:: simgrid::s4u::Activity::on_completion_cb
+      .. doxygenfunction:: simgrid::s4u::Activity::on_suspend_cb
+      .. doxygenfunction:: simgrid::s4u::Activity::on_resume_cb
+
 .. _API_s4u_Comm:
 
 =============
index 1a3a186..7e43c5d 100644 (file)
@@ -458,7 +458,8 @@ can't be done, so algorithms have to be changed to use smpi version of
 the calls instead (MPI_Send will become smpi_mpi_send). Some functions
 may have different signatures than their MPI counterpart, please check
 the other algorithms or contact us using the `>SimGrid
-developers mailing list <http://lists.gforge.inria.fr/mailman/listinfo/simgrid-devel>`_.
+user mailing list <https://sympa.inria.fr/sympa/info/simgrid-community>`_,
+or on `>Mattermost <https://framateam.org/simgrid/channels/town-square>`_.
 
 Example: adding a "pair" version of the Alltoall collective.
 
index 2be4218..0b1a27c 100644 (file)
@@ -36,7 +36,7 @@ copyright = u'2002-2022, The SimGrid Team'
 author = u'The SimGrid Team'
 
 # The short X.Y version
-version = u'3.30.1'
+version = u'3.31.1'
 
 # -- General configuration ---------------------------------------------------
 
index 0c05238..2fb10ee 100644 (file)
@@ -5,7 +5,7 @@ $ ${bindir:=.}/c-actor-exiting ${platfdir}/small_platform.xml "--log=root.fmt:[%
 > [  3.000000] (C@Ginette) And now, induce a deadlock by waiting for a message that will never come
 >
 >
-> [  3.000000] (maestro@) Oops! Deadlock or code not perfectly clean.
+> [  3.000000] (maestro@) Oops! Deadlock detected, some activities are still around but will never complete. This usually happens when the user code is not perfectly clean.
 > [  3.000000] (maestro@) 1 actors are still running, waiting for something.
 > [  3.000000] (maestro@) Legend of the following listing: "Actor <pid> (<name>@<host>): <status>"
 > [  3.000000] (maestro@) Actor 3 (C@Ginette): waiting for communication activity 0xdeadbeef () in state WAITING to finish
index c46a118..cb81951 100644 (file)
@@ -9,7 +9,7 @@ $ ${bindir:=.}/s4u-actor-exiting ${platfdir}/small_platform.xml "--log=root.fmt:
 > [  3.000000] (C@Ginette) And now, induce a deadlock by waiting for a message that will never come
 >
 >
-> [  3.000000] (maestro@) Oops! Deadlock or code not perfectly clean.
+> [  3.000000] (maestro@) Oops! Deadlock detected, some activities are still around but will never complete. This usually happens when the user code is not perfectly clean.
 > [  3.000000] (maestro@) 1 actors are still running, waiting for something.
 > [  3.000000] (maestro@) Legend of the following listing: "Actor <pid> (<name>@<host>): <status>"
 > [  3.000000] (maestro@) Actor 3 (C@Ginette): waiting for communication activity 0xdeadbeef () in state WAITING to finish
index 4e1450d..2e610e7 100644 (file)
@@ -4,6 +4,7 @@ $ ${bindir:=.}/../../../bin/simgrid-mc --log=mc_dfs.thres:verbose --log=root.fmt
 > [Checker] Start a DFS exploration. Reduction is: dpor.
 > [Checker] Execute 1: BARRIER_LOCK(barrier: 0) (stack depth: 1, state: 1, 0 interleaves)
 > [Checker] Execute 1: BARRIER_WAIT(barrier: 0) (stack depth: 2, state: 2, 0 interleaves)
+> [Checker] Execution came to an end at 1;1;0 (state: 3, depth: 3)
 > [Checker] Backtracking from 1;1;0
 > [Checker] DFS exploration ended. 3 unique states visited; 1 backtracks (3 transition replays, 0 states visited overall)
 
@@ -13,6 +14,7 @@ $ ${bindir:=.}/../../../bin/simgrid-mc --log=mc_dfs.thres:verbose --log=root.fmt
 > [Checker] Execute 2: BARRIER_LOCK(barrier: 0) (stack depth: 2, state: 2, 0 interleaves)
 > [Checker] Execute 1: BARRIER_WAIT(barrier: 0) (stack depth: 3, state: 3, 0 interleaves)
 > [Checker] Execute 2: BARRIER_WAIT(barrier: 0) (stack depth: 4, state: 4, 0 interleaves)
+> [Checker] Execution came to an end at 1;2;1;2;0 (state: 5, depth: 5)
 > [Checker] Backtracking from 1;2;1;2;0
 > [Checker] INDEPENDENT Transitions:
 > [Checker]   BARRIER_WAIT(barrier: 0) (state=3)
@@ -34,6 +36,7 @@ $ ${bindir:=.}/../../../bin/simgrid-mc --log=mc_dfs.thres:verbose --log=root.fmt
 > [Checker] Execute 1: BARRIER_WAIT(barrier: 0) (stack depth: 4, state: 4, 0 interleaves)
 > [Checker] Execute 2: BARRIER_WAIT(barrier: 0) (stack depth: 5, state: 5, 0 interleaves)
 > [Checker] Execute 3: BARRIER_WAIT(barrier: 0) (stack depth: 6, state: 6, 0 interleaves)
+> [Checker] Execution came to an end at 1;2;3;1;2;3;0 (state: 7, depth: 7)
 > [Checker] Backtracking from 1;2;3;1;2;3;0
 > [Checker] INDEPENDENT Transitions:
 > [Checker]   BARRIER_WAIT(barrier: 0) (state=5)
index 9c638b0..e7dedc4 100644 (file)
@@ -5,213 +5,219 @@ p This file tests the dependencies between MUTEX transitions
 $ ${bindir:=.}/../../../bin/simgrid-mc --log=mc_dfs.thres:verbose --log=root.fmt="[Checker]%e%m%n" -- ${bindir:=.}/s4u-synchro-mutex --cfg=actors:1 --log=s4u_test.thres:critical --log=root.fmt="[App%e%e%e%e]%e%m%n"
 > [Checker] Start a DFS exploration. Reduction is: dpor.
 > [App    ] Configuration change: Set 'actors' to '1'
-> [Checker] Execute 2: MUTEX_LOCK(mutex: 0, owner:2) (stack depth: 1, state: 1, 0 interleaves)
-> [Checker] Execute 2: MUTEX_WAIT(mutex: 0, owner:2) (stack depth: 2, state: 2, 0 interleaves)
-> [Checker] Execute 2: MUTEX_UNLOCK(mutex: 0, owner:-1) (stack depth: 3, state: 3, 0 interleaves)
-> [Checker] Execute 3: MUTEX_LOCK(mutex: 0, owner:3) (stack depth: 4, state: 4, 0 interleaves)
-> [Checker] Execute 3: MUTEX_WAIT(mutex: 0, owner:3) (stack depth: 5, state: 5, 0 interleaves)
-> [Checker] Execute 3: MUTEX_UNLOCK(mutex: 0, owner:-1) (stack depth: 6, state: 6, 0 interleaves)
-> [Checker] Backtracking from 2;2;2;3;3;3;0
+> [Checker] Execute 1: MUTEX_LOCK(mutex: 0, owner:1) (stack depth: 1, state: 1, 0 interleaves)
+> [Checker] Execute 1: MUTEX_WAIT(mutex: 0, owner:1) (stack depth: 2, state: 2, 0 interleaves)
+> [Checker] Execute 1: MUTEX_UNLOCK(mutex: 0, owner:-1) (stack depth: 3, state: 3, 0 interleaves)
+> [Checker] Execute 2: MUTEX_LOCK(mutex: 0, owner:2) (stack depth: 4, state: 4, 0 interleaves)
+> [Checker] Execute 2: MUTEX_WAIT(mutex: 0, owner:2) (stack depth: 5, state: 5, 0 interleaves)
+> [Checker] Execute 2: MUTEX_UNLOCK(mutex: 0, owner:-1) (stack depth: 6, state: 6, 0 interleaves)
+> [Checker] Execution came to an end at 1;1;1;2;2;2;0 (state: 7, depth: 7)
+> [Checker] Backtracking from 1;1;1;2;2;2;0
 > [Checker] INDEPENDENT Transitions:
 > [Checker]   MUTEX_UNLOCK(mutex: 0, owner:-1) (state=3)
-> [Checker]   MUTEX_LOCK(mutex: 0, owner:3) (state=4)
+> [Checker]   MUTEX_LOCK(mutex: 0, owner:2) (state=4)
 > [Checker] INDEPENDENT Transitions:
-> [Checker]   MUTEX_WAIT(mutex: 0, owner:2) (state=2)
-> [Checker]   MUTEX_LOCK(mutex: 0, owner:3) (state=4)
+> [Checker]   MUTEX_WAIT(mutex: 0, owner:1) (state=2)
+> [Checker]   MUTEX_LOCK(mutex: 0, owner:2) (state=4)
 > [Checker] Dependent Transitions:
-> [Checker]   MUTEX_LOCK(mutex: 0, owner:2) (state=1)
-> [Checker]   MUTEX_LOCK(mutex: 0, owner:3) (state=4)
-> [Checker] Execute 3: MUTEX_LOCK(mutex: 0, owner:3) (stack depth: 1, state: 1, 0 interleaves)
-> [Checker] Execute 2: MUTEX_LOCK(mutex: 0, owner:3) (stack depth: 2, state: 8, 0 interleaves)
-> [Checker] Execute 3: MUTEX_WAIT(mutex: 0, owner:3) (stack depth: 3, state: 9, 0 interleaves)
-> [Checker] Execute 3: MUTEX_UNLOCK(mutex: 0, owner:2) (stack depth: 4, state: 10, 0 interleaves)
-> [Checker] Execute 2: MUTEX_WAIT(mutex: 0, owner:2) (stack depth: 5, state: 11, 0 interleaves)
-> [Checker] Execute 2: MUTEX_UNLOCK(mutex: 0, owner:-1) (stack depth: 6, state: 12, 0 interleaves)
-> [Checker] Backtracking from 3;2;3;3;2;2;0
+> [Checker]   MUTEX_LOCK(mutex: 0, owner:1) (state=1)
+> [Checker]   MUTEX_LOCK(mutex: 0, owner:2) (state=4)
+> [Checker] Execute 2: MUTEX_LOCK(mutex: 0, owner:2) (stack depth: 1, state: 1, 0 interleaves)
+> [Checker] Execute 1: MUTEX_LOCK(mutex: 0, owner:2) (stack depth: 2, state: 8, 0 interleaves)
+> [Checker] Execute 2: MUTEX_WAIT(mutex: 0, owner:2) (stack depth: 3, state: 9, 0 interleaves)
+> [Checker] Execute 2: MUTEX_UNLOCK(mutex: 0, owner:1) (stack depth: 4, state: 10, 0 interleaves)
+> [Checker] Execute 1: MUTEX_WAIT(mutex: 0, owner:1) (stack depth: 5, state: 11, 0 interleaves)
+> [Checker] Execute 1: MUTEX_UNLOCK(mutex: 0, owner:-1) (stack depth: 6, state: 12, 0 interleaves)
+> [Checker] Execution came to an end at 2;1;2;2;1;1;0 (state: 13, depth: 7)
+> [Checker] Backtracking from 2;1;2;2;1;1;0
 > [Checker] Dependent Transitions:
-> [Checker]   MUTEX_UNLOCK(mutex: 0, owner:2) (state=10)
-> [Checker]   MUTEX_WAIT(mutex: 0, owner:2) (state=11)
-> [Checker] Backtracking from 3;2;3;3
+> [Checker]   MUTEX_UNLOCK(mutex: 0, owner:1) (state=10)
+> [Checker]   MUTEX_WAIT(mutex: 0, owner:1) (state=11)
+> [Checker] Backtracking from 2;1;2;2
 > [Checker] INDEPENDENT Transitions:
-> [Checker]   MUTEX_LOCK(mutex: 0, owner:3) (state=8)
-> [Checker]   MUTEX_WAIT(mutex: 0, owner:3) (state=9)
+> [Checker]   MUTEX_LOCK(mutex: 0, owner:2) (state=8)
+> [Checker]   MUTEX_WAIT(mutex: 0, owner:2) (state=9)
 > [Checker] Dependent Transitions:
-> [Checker]   MUTEX_LOCK(mutex: 0, owner:3) (state=1)
-> [Checker]   MUTEX_LOCK(mutex: 0, owner:3) (state=8)
+> [Checker]   MUTEX_LOCK(mutex: 0, owner:2) (state=1)
+> [Checker]   MUTEX_LOCK(mutex: 0, owner:2) (state=8)
 > [Checker] DFS exploration ended. 13 unique states visited; 3 backtracks (18 transition replays, 3 states visited overall)
 
 $ ${bindir:=.}/../../../bin/simgrid-mc --log=mc_dfs.thres:verbose --log=root.fmt="[Checker]%e%m%n" -- ${bindir:=.}/s4u-synchro-mutex --cfg=actors:2 --log=s4u_test.thres:critical --log=root.fmt="[App%e%e%e%e]%e%m%n"
 > [Checker] Start a DFS exploration. Reduction is: dpor.
 > [App    ] Configuration change: Set 'actors' to '2'
-> [Checker] Execute 2: MUTEX_LOCK(mutex: 0, owner:2) (stack depth: 1, state: 1, 0 interleaves)
-> [Checker] Execute 2: MUTEX_WAIT(mutex: 0, owner:2) (stack depth: 2, state: 2, 0 interleaves)
-> [Checker] Execute 2: MUTEX_UNLOCK(mutex: 0, owner:-1) (stack depth: 3, state: 3, 0 interleaves)
-> [Checker] Execute 3: MUTEX_LOCK(mutex: 0, owner:3) (stack depth: 4, state: 4, 0 interleaves)
-> [Checker] Execute 3: MUTEX_WAIT(mutex: 0, owner:3) (stack depth: 5, state: 5, 0 interleaves)
-> [Checker] Execute 3: MUTEX_UNLOCK(mutex: 0, owner:-1) (stack depth: 6, state: 6, 0 interleaves)
-> [Checker] Execute 4: MUTEX_LOCK(mutex: 1, owner:4) (stack depth: 7, state: 7, 0 interleaves)
-> [Checker] Execute 4: MUTEX_WAIT(mutex: 1, owner:4) (stack depth: 8, state: 8, 0 interleaves)
-> [Checker] Execute 4: MUTEX_UNLOCK(mutex: 1, owner:-1) (stack depth: 9, state: 9, 0 interleaves)
-> [Checker] Execute 5: MUTEX_LOCK(mutex: 1, owner:5) (stack depth: 10, state: 10, 0 interleaves)
-> [Checker] Execute 5: MUTEX_WAIT(mutex: 1, owner:5) (stack depth: 11, state: 11, 0 interleaves)
-> [Checker] Execute 5: MUTEX_UNLOCK(mutex: 1, owner:-1) (stack depth: 12, state: 12, 0 interleaves)
-> [Checker] Backtracking from 2;2;2;3;3;3;4;4;4;5;5;5;0
+> [Checker] Execute 1: MUTEX_LOCK(mutex: 0, owner:1) (stack depth: 1, state: 1, 0 interleaves)
+> [Checker] Execute 1: MUTEX_WAIT(mutex: 0, owner:1) (stack depth: 2, state: 2, 0 interleaves)
+> [Checker] Execute 1: MUTEX_UNLOCK(mutex: 0, owner:-1) (stack depth: 3, state: 3, 0 interleaves)
+> [Checker] Execute 2: MUTEX_LOCK(mutex: 0, owner:2) (stack depth: 4, state: 4, 0 interleaves)
+> [Checker] Execute 2: MUTEX_WAIT(mutex: 0, owner:2) (stack depth: 5, state: 5, 0 interleaves)
+> [Checker] Execute 2: MUTEX_UNLOCK(mutex: 0, owner:-1) (stack depth: 6, state: 6, 0 interleaves)
+> [Checker] Execute 3: MUTEX_LOCK(mutex: 1, owner:3) (stack depth: 7, state: 7, 0 interleaves)
+> [Checker] Execute 3: MUTEX_WAIT(mutex: 1, owner:3) (stack depth: 8, state: 8, 0 interleaves)
+> [Checker] Execute 3: MUTEX_UNLOCK(mutex: 1, owner:-1) (stack depth: 9, state: 9, 0 interleaves)
+> [Checker] Execute 4: MUTEX_LOCK(mutex: 1, owner:4) (stack depth: 10, state: 10, 0 interleaves)
+> [Checker] Execute 4: MUTEX_WAIT(mutex: 1, owner:4) (stack depth: 11, state: 11, 0 interleaves)
+> [Checker] Execute 4: MUTEX_UNLOCK(mutex: 1, owner:-1) (stack depth: 12, state: 12, 0 interleaves)
+> [Checker] Execution came to an end at 1;1;1;2;2;2;3;3;3;4;4;4;0 (state: 13, depth: 13)
+> [Checker] Backtracking from 1;1;1;2;2;2;3;3;3;4;4;4;0
 > [Checker] INDEPENDENT Transitions:
 > [Checker]   MUTEX_UNLOCK(mutex: 1, owner:-1) (state=9)
-> [Checker]   MUTEX_LOCK(mutex: 1, owner:5) (state=10)
+> [Checker]   MUTEX_LOCK(mutex: 1, owner:4) (state=10)
 > [Checker] INDEPENDENT Transitions:
-> [Checker]   MUTEX_WAIT(mutex: 1, owner:4) (state=8)
-> [Checker]   MUTEX_LOCK(mutex: 1, owner:5) (state=10)
+> [Checker]   MUTEX_WAIT(mutex: 1, owner:3) (state=8)
+> [Checker]   MUTEX_LOCK(mutex: 1, owner:4) (state=10)
 > [Checker] Dependent Transitions:
-> [Checker]   MUTEX_LOCK(mutex: 1, owner:4) (state=7)
-> [Checker]   MUTEX_LOCK(mutex: 1, owner:5) (state=10)
+> [Checker]   MUTEX_LOCK(mutex: 1, owner:3) (state=7)
+> [Checker]   MUTEX_LOCK(mutex: 1, owner:4) (state=10)
 > [Checker] INDEPENDENT Transitions:
 > [Checker]   MUTEX_UNLOCK(mutex: 0, owner:-1) (state=6)
-> [Checker]   MUTEX_LOCK(mutex: 1, owner:4) (state=7)
+> [Checker]   MUTEX_LOCK(mutex: 1, owner:3) (state=7)
 > [Checker] INDEPENDENT Transitions:
-> [Checker]   MUTEX_WAIT(mutex: 0, owner:3) (state=5)
-> [Checker]   MUTEX_LOCK(mutex: 1, owner:4) (state=7)
+> [Checker]   MUTEX_WAIT(mutex: 0, owner:2) (state=5)
+> [Checker]   MUTEX_LOCK(mutex: 1, owner:3) (state=7)
 > [Checker] INDEPENDENT Transitions:
-> [Checker]   MUTEX_LOCK(mutex: 0, owner:3) (state=4)
-> [Checker]   MUTEX_LOCK(mutex: 1, owner:4) (state=7)
+> [Checker]   MUTEX_LOCK(mutex: 0, owner:2) (state=4)
+> [Checker]   MUTEX_LOCK(mutex: 1, owner:3) (state=7)
 > [Checker] INDEPENDENT Transitions:
 > [Checker]   MUTEX_UNLOCK(mutex: 0, owner:-1) (state=3)
-> [Checker]   MUTEX_LOCK(mutex: 1, owner:4) (state=7)
+> [Checker]   MUTEX_LOCK(mutex: 1, owner:3) (state=7)
 > [Checker] INDEPENDENT Transitions:
-> [Checker]   MUTEX_WAIT(mutex: 0, owner:2) (state=2)
-> [Checker]   MUTEX_LOCK(mutex: 1, owner:4) (state=7)
+> [Checker]   MUTEX_WAIT(mutex: 0, owner:1) (state=2)
+> [Checker]   MUTEX_LOCK(mutex: 1, owner:3) (state=7)
 > [Checker] INDEPENDENT Transitions:
-> [Checker]   MUTEX_LOCK(mutex: 0, owner:2) (state=1)
-> [Checker]   MUTEX_LOCK(mutex: 1, owner:4) (state=7)
-> [Checker] Execute 5: MUTEX_LOCK(mutex: 1, owner:5) (stack depth: 7, state: 7, 0 interleaves)
-> [Checker] Execute 4: MUTEX_LOCK(mutex: 1, owner:5) (stack depth: 8, state: 14, 0 interleaves)
-> [Checker] Execute 5: MUTEX_WAIT(mutex: 1, owner:5) (stack depth: 9, state: 15, 0 interleaves)
-> [Checker] Execute 5: MUTEX_UNLOCK(mutex: 1, owner:4) (stack depth: 10, state: 16, 0 interleaves)
-> [Checker] Execute 4: MUTEX_WAIT(mutex: 1, owner:4) (stack depth: 11, state: 17, 0 interleaves)
-> [Checker] Execute 4: MUTEX_UNLOCK(mutex: 1, owner:-1) (stack depth: 12, state: 18, 0 interleaves)
-> [Checker] Backtracking from 2;2;2;3;3;3;5;4;5;5;4;4;0
+> [Checker]   MUTEX_LOCK(mutex: 0, owner:1) (state=1)
+> [Checker]   MUTEX_LOCK(mutex: 1, owner:3) (state=7)
+> [Checker] Execute 4: MUTEX_LOCK(mutex: 1, owner:4) (stack depth: 7, state: 7, 0 interleaves)
+> [Checker] Execute 3: MUTEX_LOCK(mutex: 1, owner:4) (stack depth: 8, state: 14, 0 interleaves)
+> [Checker] Execute 4: MUTEX_WAIT(mutex: 1, owner:4) (stack depth: 9, state: 15, 0 interleaves)
+> [Checker] Execute 4: MUTEX_UNLOCK(mutex: 1, owner:3) (stack depth: 10, state: 16, 0 interleaves)
+> [Checker] Execute 3: MUTEX_WAIT(mutex: 1, owner:3) (stack depth: 11, state: 17, 0 interleaves)
+> [Checker] Execute 3: MUTEX_UNLOCK(mutex: 1, owner:-1) (stack depth: 12, state: 18, 0 interleaves)
+> [Checker] Execution came to an end at 1;1;1;2;2;2;4;3;4;4;3;3;0 (state: 19, depth: 13)
+> [Checker] Backtracking from 1;1;1;2;2;2;4;3;4;4;3;3;0
 > [Checker] Dependent Transitions:
-> [Checker]   MUTEX_UNLOCK(mutex: 1, owner:4) (state=16)
-> [Checker]   MUTEX_WAIT(mutex: 1, owner:4) (state=17)
-> [Checker] Backtracking from 2;2;2;3;3;3;5;4;5;5
+> [Checker]   MUTEX_UNLOCK(mutex: 1, owner:3) (state=16)
+> [Checker]   MUTEX_WAIT(mutex: 1, owner:3) (state=17)
+> [Checker] Backtracking from 1;1;1;2;2;2;4;3;4;4
 > [Checker] INDEPENDENT Transitions:
-> [Checker]   MUTEX_LOCK(mutex: 1, owner:5) (state=14)
-> [Checker]   MUTEX_WAIT(mutex: 1, owner:5) (state=15)
+> [Checker]   MUTEX_LOCK(mutex: 1, owner:4) (state=14)
+> [Checker]   MUTEX_WAIT(mutex: 1, owner:4) (state=15)
 > [Checker] Dependent Transitions:
-> [Checker]   MUTEX_LOCK(mutex: 1, owner:5) (state=7)
-> [Checker]   MUTEX_LOCK(mutex: 1, owner:5) (state=14)
+> [Checker]   MUTEX_LOCK(mutex: 1, owner:4) (state=7)
+> [Checker]   MUTEX_LOCK(mutex: 1, owner:4) (state=14)
 > [Checker] INDEPENDENT Transitions:
 > [Checker]   MUTEX_UNLOCK(mutex: 0, owner:-1) (state=6)
-> [Checker]   MUTEX_LOCK(mutex: 1, owner:5) (state=7)
+> [Checker]   MUTEX_LOCK(mutex: 1, owner:4) (state=7)
 > [Checker] INDEPENDENT Transitions:
-> [Checker]   MUTEX_WAIT(mutex: 0, owner:3) (state=5)
-> [Checker]   MUTEX_LOCK(mutex: 1, owner:5) (state=7)
+> [Checker]   MUTEX_WAIT(mutex: 0, owner:2) (state=5)
+> [Checker]   MUTEX_LOCK(mutex: 1, owner:4) (state=7)
 > [Checker] INDEPENDENT Transitions:
-> [Checker]   MUTEX_LOCK(mutex: 0, owner:3) (state=4)
-> [Checker]   MUTEX_LOCK(mutex: 1, owner:5) (state=7)
+> [Checker]   MUTEX_LOCK(mutex: 0, owner:2) (state=4)
+> [Checker]   MUTEX_LOCK(mutex: 1, owner:4) (state=7)
 > [Checker] INDEPENDENT Transitions:
 > [Checker]   MUTEX_UNLOCK(mutex: 0, owner:-1) (state=3)
-> [Checker]   MUTEX_LOCK(mutex: 1, owner:5) (state=7)
+> [Checker]   MUTEX_LOCK(mutex: 1, owner:4) (state=7)
 > [Checker] INDEPENDENT Transitions:
-> [Checker]   MUTEX_WAIT(mutex: 0, owner:2) (state=2)
-> [Checker]   MUTEX_LOCK(mutex: 1, owner:5) (state=7)
+> [Checker]   MUTEX_WAIT(mutex: 0, owner:1) (state=2)
+> [Checker]   MUTEX_LOCK(mutex: 1, owner:4) (state=7)
 > [Checker] INDEPENDENT Transitions:
-> [Checker]   MUTEX_LOCK(mutex: 0, owner:2) (state=1)
-> [Checker]   MUTEX_LOCK(mutex: 1, owner:5) (state=7)
+> [Checker]   MUTEX_LOCK(mutex: 0, owner:1) (state=1)
+> [Checker]   MUTEX_LOCK(mutex: 1, owner:4) (state=7)
 > [Checker] INDEPENDENT Transitions:
 > [Checker]   MUTEX_UNLOCK(mutex: 0, owner:-1) (state=3)
-> [Checker]   MUTEX_LOCK(mutex: 0, owner:3) (state=4)
+> [Checker]   MUTEX_LOCK(mutex: 0, owner:2) (state=4)
 > [Checker] INDEPENDENT Transitions:
-> [Checker]   MUTEX_WAIT(mutex: 0, owner:2) (state=2)
-> [Checker]   MUTEX_LOCK(mutex: 0, owner:3) (state=4)
+> [Checker]   MUTEX_WAIT(mutex: 0, owner:1) (state=2)
+> [Checker]   MUTEX_LOCK(mutex: 0, owner:2) (state=4)
 > [Checker] Dependent Transitions:
-> [Checker]   MUTEX_LOCK(mutex: 0, owner:2) (state=1)
-> [Checker]   MUTEX_LOCK(mutex: 0, owner:3) (state=4)
-> [Checker] Execute 3: MUTEX_LOCK(mutex: 0, owner:3) (stack depth: 1, state: 1, 0 interleaves)
-> [Checker] Execute 2: MUTEX_LOCK(mutex: 0, owner:3) (stack depth: 2, state: 20, 0 interleaves)
-> [Checker] Execute 3: MUTEX_WAIT(mutex: 0, owner:3) (stack depth: 3, state: 21, 0 interleaves)
-> [Checker] Execute 3: MUTEX_UNLOCK(mutex: 0, owner:2) (stack depth: 4, state: 22, 0 interleaves)
-> [Checker] Execute 2: MUTEX_WAIT(mutex: 0, owner:2) (stack depth: 5, state: 23, 0 interleaves)
-> [Checker] Execute 2: MUTEX_UNLOCK(mutex: 0, owner:-1) (stack depth: 6, state: 24, 0 interleaves)
-> [Checker] Execute 4: MUTEX_LOCK(mutex: 1, owner:4) (stack depth: 7, state: 25, 0 interleaves)
-> [Checker] Execute 4: MUTEX_WAIT(mutex: 1, owner:4) (stack depth: 8, state: 26, 0 interleaves)
-> [Checker] Execute 4: MUTEX_UNLOCK(mutex: 1, owner:-1) (stack depth: 9, state: 27, 0 interleaves)
-> [Checker] Execute 5: MUTEX_LOCK(mutex: 1, owner:5) (stack depth: 10, state: 28, 0 interleaves)
-> [Checker] Execute 5: MUTEX_WAIT(mutex: 1, owner:5) (stack depth: 11, state: 29, 0 interleaves)
-> [Checker] Execute 5: MUTEX_UNLOCK(mutex: 1, owner:-1) (stack depth: 12, state: 30, 0 interleaves)
-> [Checker] Backtracking from 3;2;3;3;2;2;4;4;4;5;5;5;0
+> [Checker]   MUTEX_LOCK(mutex: 0, owner:1) (state=1)
+> [Checker]   MUTEX_LOCK(mutex: 0, owner:2) (state=4)
+> [Checker] Execute 2: MUTEX_LOCK(mutex: 0, owner:2) (stack depth: 1, state: 1, 0 interleaves)
+> [Checker] Execute 1: MUTEX_LOCK(mutex: 0, owner:2) (stack depth: 2, state: 20, 0 interleaves)
+> [Checker] Execute 2: MUTEX_WAIT(mutex: 0, owner:2) (stack depth: 3, state: 21, 0 interleaves)
+> [Checker] Execute 2: MUTEX_UNLOCK(mutex: 0, owner:1) (stack depth: 4, state: 22, 0 interleaves)
+> [Checker] Execute 1: MUTEX_WAIT(mutex: 0, owner:1) (stack depth: 5, state: 23, 0 interleaves)
+> [Checker] Execute 1: MUTEX_UNLOCK(mutex: 0, owner:-1) (stack depth: 6, state: 24, 0 interleaves)
+> [Checker] Execute 3: MUTEX_LOCK(mutex: 1, owner:3) (stack depth: 7, state: 25, 0 interleaves)
+> [Checker] Execute 3: MUTEX_WAIT(mutex: 1, owner:3) (stack depth: 8, state: 26, 0 interleaves)
+> [Checker] Execute 3: MUTEX_UNLOCK(mutex: 1, owner:-1) (stack depth: 9, state: 27, 0 interleaves)
+> [Checker] Execute 4: MUTEX_LOCK(mutex: 1, owner:4) (stack depth: 10, state: 28, 0 interleaves)
+> [Checker] Execute 4: MUTEX_WAIT(mutex: 1, owner:4) (stack depth: 11, state: 29, 0 interleaves)
+> [Checker] Execute 4: MUTEX_UNLOCK(mutex: 1, owner:-1) (stack depth: 12, state: 30, 0 interleaves)
+> [Checker] Execution came to an end at 2;1;2;2;1;1;3;3;3;4;4;4;0 (state: 31, depth: 13)
+> [Checker] Backtracking from 2;1;2;2;1;1;3;3;3;4;4;4;0
 > [Checker] INDEPENDENT Transitions:
 > [Checker]   MUTEX_UNLOCK(mutex: 1, owner:-1) (state=27)
-> [Checker]   MUTEX_LOCK(mutex: 1, owner:5) (state=28)
+> [Checker]   MUTEX_LOCK(mutex: 1, owner:4) (state=28)
 > [Checker] INDEPENDENT Transitions:
-> [Checker]   MUTEX_WAIT(mutex: 1, owner:4) (state=26)
-> [Checker]   MUTEX_LOCK(mutex: 1, owner:5) (state=28)
+> [Checker]   MUTEX_WAIT(mutex: 1, owner:3) (state=26)
+> [Checker]   MUTEX_LOCK(mutex: 1, owner:4) (state=28)
 > [Checker] Dependent Transitions:
-> [Checker]   MUTEX_LOCK(mutex: 1, owner:4) (state=25)
-> [Checker]   MUTEX_LOCK(mutex: 1, owner:5) (state=28)
+> [Checker]   MUTEX_LOCK(mutex: 1, owner:3) (state=25)
+> [Checker]   MUTEX_LOCK(mutex: 1, owner:4) (state=28)
 > [Checker] INDEPENDENT Transitions:
 > [Checker]   MUTEX_UNLOCK(mutex: 0, owner:-1) (state=24)
-> [Checker]   MUTEX_LOCK(mutex: 1, owner:4) (state=25)
+> [Checker]   MUTEX_LOCK(mutex: 1, owner:3) (state=25)
 > [Checker] INDEPENDENT Transitions:
-> [Checker]   MUTEX_WAIT(mutex: 0, owner:2) (state=23)
-> [Checker]   MUTEX_LOCK(mutex: 1, owner:4) (state=25)
+> [Checker]   MUTEX_WAIT(mutex: 0, owner:1) (state=23)
+> [Checker]   MUTEX_LOCK(mutex: 1, owner:3) (state=25)
 > [Checker] INDEPENDENT Transitions:
-> [Checker]   MUTEX_UNLOCK(mutex: 0, owner:2) (state=22)
-> [Checker]   MUTEX_LOCK(mutex: 1, owner:4) (state=25)
+> [Checker]   MUTEX_UNLOCK(mutex: 0, owner:1) (state=22)
+> [Checker]   MUTEX_LOCK(mutex: 1, owner:3) (state=25)
 > [Checker] INDEPENDENT Transitions:
-> [Checker]   MUTEX_WAIT(mutex: 0, owner:3) (state=21)
-> [Checker]   MUTEX_LOCK(mutex: 1, owner:4) (state=25)
+> [Checker]   MUTEX_WAIT(mutex: 0, owner:2) (state=21)
+> [Checker]   MUTEX_LOCK(mutex: 1, owner:3) (state=25)
 > [Checker] INDEPENDENT Transitions:
-> [Checker]   MUTEX_LOCK(mutex: 0, owner:3) (state=20)
-> [Checker]   MUTEX_LOCK(mutex: 1, owner:4) (state=25)
+> [Checker]   MUTEX_LOCK(mutex: 0, owner:2) (state=20)
+> [Checker]   MUTEX_LOCK(mutex: 1, owner:3) (state=25)
 > [Checker] INDEPENDENT Transitions:
-> [Checker]   MUTEX_LOCK(mutex: 0, owner:3) (state=1)
-> [Checker]   MUTEX_LOCK(mutex: 1, owner:4) (state=25)
-> [Checker] Execute 5: MUTEX_LOCK(mutex: 1, owner:5) (stack depth: 7, state: 25, 0 interleaves)
-> [Checker] Execute 4: MUTEX_LOCK(mutex: 1, owner:5) (stack depth: 8, state: 32, 0 interleaves)
-> [Checker] Execute 5: MUTEX_WAIT(mutex: 1, owner:5) (stack depth: 9, state: 33, 0 interleaves)
-> [Checker] Execute 5: MUTEX_UNLOCK(mutex: 1, owner:4) (stack depth: 10, state: 34, 0 interleaves)
-> [Checker] Execute 4: MUTEX_WAIT(mutex: 1, owner:4) (stack depth: 11, state: 35, 0 interleaves)
-> [Checker] Execute 4: MUTEX_UNLOCK(mutex: 1, owner:-1) (stack depth: 12, state: 36, 0 interleaves)
-> [Checker] Backtracking from 3;2;3;3;2;2;5;4;5;5;4;4;0
+> [Checker]   MUTEX_LOCK(mutex: 0, owner:2) (state=1)
+> [Checker]   MUTEX_LOCK(mutex: 1, owner:3) (state=25)
+> [Checker] Execute 4: MUTEX_LOCK(mutex: 1, owner:4) (stack depth: 7, state: 25, 0 interleaves)
+> [Checker] Execute 3: MUTEX_LOCK(mutex: 1, owner:4) (stack depth: 8, state: 32, 0 interleaves)
+> [Checker] Execute 4: MUTEX_WAIT(mutex: 1, owner:4) (stack depth: 9, state: 33, 0 interleaves)
+> [Checker] Execute 4: MUTEX_UNLOCK(mutex: 1, owner:3) (stack depth: 10, state: 34, 0 interleaves)
+> [Checker] Execute 3: MUTEX_WAIT(mutex: 1, owner:3) (stack depth: 11, state: 35, 0 interleaves)
+> [Checker] Execute 3: MUTEX_UNLOCK(mutex: 1, owner:-1) (stack depth: 12, state: 36, 0 interleaves)
+> [Checker] Execution came to an end at 2;1;2;2;1;1;4;3;4;4;3;3;0 (state: 37, depth: 13)
+> [Checker] Backtracking from 2;1;2;2;1;1;4;3;4;4;3;3;0
 > [Checker] Dependent Transitions:
-> [Checker]   MUTEX_UNLOCK(mutex: 1, owner:4) (state=34)
-> [Checker]   MUTEX_WAIT(mutex: 1, owner:4) (state=35)
-> [Checker] Backtracking from 3;2;3;3;2;2;5;4;5;5
+> [Checker]   MUTEX_UNLOCK(mutex: 1, owner:3) (state=34)
+> [Checker]   MUTEX_WAIT(mutex: 1, owner:3) (state=35)
+> [Checker] Backtracking from 2;1;2;2;1;1;4;3;4;4
 > [Checker] INDEPENDENT Transitions:
-> [Checker]   MUTEX_LOCK(mutex: 1, owner:5) (state=32)
-> [Checker]   MUTEX_WAIT(mutex: 1, owner:5) (state=33)
+> [Checker]   MUTEX_LOCK(mutex: 1, owner:4) (state=32)
+> [Checker]   MUTEX_WAIT(mutex: 1, owner:4) (state=33)
 > [Checker] Dependent Transitions:
-> [Checker]   MUTEX_LOCK(mutex: 1, owner:5) (state=25)
-> [Checker]   MUTEX_LOCK(mutex: 1, owner:5) (state=32)
+> [Checker]   MUTEX_LOCK(mutex: 1, owner:4) (state=25)
+> [Checker]   MUTEX_LOCK(mutex: 1, owner:4) (state=32)
 > [Checker] INDEPENDENT Transitions:
 > [Checker]   MUTEX_UNLOCK(mutex: 0, owner:-1) (state=24)
-> [Checker]   MUTEX_LOCK(mutex: 1, owner:5) (state=25)
+> [Checker]   MUTEX_LOCK(mutex: 1, owner:4) (state=25)
 > [Checker] INDEPENDENT Transitions:
-> [Checker]   MUTEX_WAIT(mutex: 0, owner:2) (state=23)
-> [Checker]   MUTEX_LOCK(mutex: 1, owner:5) (state=25)
+> [Checker]   MUTEX_WAIT(mutex: 0, owner:1) (state=23)
+> [Checker]   MUTEX_LOCK(mutex: 1, owner:4) (state=25)
 > [Checker] INDEPENDENT Transitions:
-> [Checker]   MUTEX_UNLOCK(mutex: 0, owner:2) (state=22)
-> [Checker]   MUTEX_LOCK(mutex: 1, owner:5) (state=25)
+> [Checker]   MUTEX_UNLOCK(mutex: 0, owner:1) (state=22)
+> [Checker]   MUTEX_LOCK(mutex: 1, owner:4) (state=25)
 > [Checker] INDEPENDENT Transitions:
-> [Checker]   MUTEX_WAIT(mutex: 0, owner:3) (state=21)
-> [Checker]   MUTEX_LOCK(mutex: 1, owner:5) (state=25)
+> [Checker]   MUTEX_WAIT(mutex: 0, owner:2) (state=21)
+> [Checker]   MUTEX_LOCK(mutex: 1, owner:4) (state=25)
 > [Checker] INDEPENDENT Transitions:
-> [Checker]   MUTEX_LOCK(mutex: 0, owner:3) (state=20)
-> [Checker]   MUTEX_LOCK(mutex: 1, owner:5) (state=25)
+> [Checker]   MUTEX_LOCK(mutex: 0, owner:2) (state=20)
+> [Checker]   MUTEX_LOCK(mutex: 1, owner:4) (state=25)
 > [Checker] INDEPENDENT Transitions:
-> [Checker]   MUTEX_LOCK(mutex: 0, owner:3) (state=1)
-> [Checker]   MUTEX_LOCK(mutex: 1, owner:5) (state=25)
+> [Checker]   MUTEX_LOCK(mutex: 0, owner:2) (state=1)
+> [Checker]   MUTEX_LOCK(mutex: 1, owner:4) (state=25)
 > [Checker] Dependent Transitions:
-> [Checker]   MUTEX_UNLOCK(mutex: 0, owner:2) (state=22)
-> [Checker]   MUTEX_WAIT(mutex: 0, owner:2) (state=23)
-> [Checker] Backtracking from 3;2;3;3
+> [Checker]   MUTEX_UNLOCK(mutex: 0, owner:1) (state=22)
+> [Checker]   MUTEX_WAIT(mutex: 0, owner:1) (state=23)
+> [Checker] Backtracking from 2;1;2;2
 > [Checker] INDEPENDENT Transitions:
-> [Checker]   MUTEX_LOCK(mutex: 0, owner:3) (state=20)
-> [Checker]   MUTEX_WAIT(mutex: 0, owner:3) (state=21)
+> [Checker]   MUTEX_LOCK(mutex: 0, owner:2) (state=20)
+> [Checker]   MUTEX_WAIT(mutex: 0, owner:2) (state=21)
 > [Checker] Dependent Transitions:
-> [Checker]   MUTEX_LOCK(mutex: 0, owner:3) (state=1)
-> [Checker]   MUTEX_LOCK(mutex: 0, owner:3) (state=20)
+> [Checker]   MUTEX_LOCK(mutex: 0, owner:2) (state=1)
+> [Checker]   MUTEX_LOCK(mutex: 0, owner:2) (state=20)
 > [Checker] DFS exploration ended. 37 unique states visited; 7 backtracks (76 transition replays, 33 states visited overall)
 
 $ ${bindir:=.}/../../../bin/simgrid-mc -- ${bindir:=.}/s4u-synchro-mutex --cfg=actors:3 --log=s4u_test.thres:critical
index 2127d03..faa8d2b 100644 (file)
@@ -44,8 +44,11 @@ static void workerLockGuard(sg4::MutexPtr mutex, int& result)
   // Nothing specific here: the unlock will be automatic
 }
 
-static void master()
+int main(int argc, char** argv)
 {
+  sg4::Engine e(&argc, argv);
+  e.load_platform("../../platforms/two_hosts.xml");
+
   /* Create the requested amount of actors pairs. Each pair has a specific mutex and cell in `result`. */
   std::vector<int> result(cfg_actor_count.get());
 
@@ -55,17 +58,10 @@ static void master()
     sg4::Actor::create("worker", sg4::Host::by_name("Tremblay"), worker, mutex, std::ref(result[i]));
   }
 
-  sg4::this_actor::sleep_for(10);
+  e.run();
+
   for (int i = 0; i < cfg_actor_count; i++)
     XBT_INFO("Result[%d] -> %d", i, result[i]);
-}
-
-int main(int argc, char **argv)
-{
-  sg4::Engine e(&argc, argv);
-  e.load_platform("../../platforms/two_hosts.xml");
-  sg4::Actor::create("main", e.host_by_name("Tremblay"), master);
-  e.run();
 
   return 0;
 }
index 9e92179..fbec803 100644 (file)
@@ -1,33 +1,33 @@
 #!/usr/bin/env tesh
 
 $ ${bindir:=.}/s4u-synchro-mutex
-> [Jupiter:worker:(2) 0.000000] [s4u_test/INFO] Hello s4u, I'm ready to compute after a lock_guard
-> [Jupiter:worker:(2) 0.000000] [s4u_test/INFO] I'm done, good bye
-> [Tremblay:worker:(3) 0.000000] [s4u_test/INFO] Hello s4u, I'm ready to compute after a regular lock
-> [Tremblay:worker:(3) 0.000000] [s4u_test/INFO] I'm done, good bye
-> [Jupiter:worker:(4) 0.000000] [s4u_test/INFO] Hello s4u, I'm ready to compute after a lock_guard
-> [Jupiter:worker:(4) 0.000000] [s4u_test/INFO] I'm done, good bye
-> [Tremblay:worker:(5) 0.000000] [s4u_test/INFO] Hello s4u, I'm ready to compute after a regular lock
-> [Tremblay:worker:(5) 0.000000] [s4u_test/INFO] I'm done, good bye
-> [Jupiter:worker:(6) 0.000000] [s4u_test/INFO] Hello s4u, I'm ready to compute after a lock_guard
-> [Jupiter:worker:(6) 0.000000] [s4u_test/INFO] I'm done, good bye
-> [Tremblay:worker:(7) 0.000000] [s4u_test/INFO] Hello s4u, I'm ready to compute after a regular lock
-> [Tremblay:worker:(7) 0.000000] [s4u_test/INFO] I'm done, good bye
-> [Jupiter:worker:(8) 0.000000] [s4u_test/INFO] Hello s4u, I'm ready to compute after a lock_guard
-> [Jupiter:worker:(8) 0.000000] [s4u_test/INFO] I'm done, good bye
-> [Tremblay:worker:(9) 0.000000] [s4u_test/INFO] Hello s4u, I'm ready to compute after a regular lock
-> [Tremblay:worker:(9) 0.000000] [s4u_test/INFO] I'm done, good bye
-> [Jupiter:worker:(10) 0.000000] [s4u_test/INFO] Hello s4u, I'm ready to compute after a lock_guard
-> [Jupiter:worker:(10) 0.000000] [s4u_test/INFO] I'm done, good bye
-> [Tremblay:worker:(11) 0.000000] [s4u_test/INFO] Hello s4u, I'm ready to compute after a regular lock
-> [Tremblay:worker:(11) 0.000000] [s4u_test/INFO] I'm done, good bye
-> [Jupiter:worker:(12) 0.000000] [s4u_test/INFO] Hello s4u, I'm ready to compute after a lock_guard
-> [Jupiter:worker:(12) 0.000000] [s4u_test/INFO] I'm done, good bye
-> [Tremblay:worker:(13) 0.000000] [s4u_test/INFO] Hello s4u, I'm ready to compute after a regular lock
-> [Tremblay:worker:(13) 0.000000] [s4u_test/INFO] I'm done, good bye
-> [Tremblay:main:(1) 10.000000] [s4u_test/INFO] Result[0] -> 2
-> [Tremblay:main:(1) 10.000000] [s4u_test/INFO] Result[1] -> 2
-> [Tremblay:main:(1) 10.000000] [s4u_test/INFO] Result[2] -> 2
-> [Tremblay:main:(1) 10.000000] [s4u_test/INFO] Result[3] -> 2
-> [Tremblay:main:(1) 10.000000] [s4u_test/INFO] Result[4] -> 2
-> [Tremblay:main:(1) 10.000000] [s4u_test/INFO] Result[5] -> 2
+> [Jupiter:worker:(1) 0.000000] [s4u_test/INFO] Hello s4u, I'm ready to compute after a lock_guard
+> [Jupiter:worker:(1) 0.000000] [s4u_test/INFO] I'm done, good bye
+> [Jupiter:worker:(3) 0.000000] [s4u_test/INFO] Hello s4u, I'm ready to compute after a lock_guard
+> [Jupiter:worker:(3) 0.000000] [s4u_test/INFO] I'm done, good bye
+> [Jupiter:worker:(5) 0.000000] [s4u_test/INFO] Hello s4u, I'm ready to compute after a lock_guard
+> [Jupiter:worker:(5) 0.000000] [s4u_test/INFO] I'm done, good bye
+> [Jupiter:worker:(7) 0.000000] [s4u_test/INFO] Hello s4u, I'm ready to compute after a lock_guard
+> [Jupiter:worker:(7) 0.000000] [s4u_test/INFO] I'm done, good bye
+> [Jupiter:worker:(9) 0.000000] [s4u_test/INFO] Hello s4u, I'm ready to compute after a lock_guard
+> [Jupiter:worker:(9) 0.000000] [s4u_test/INFO] I'm done, good bye
+> [Jupiter:worker:(11) 0.000000] [s4u_test/INFO] Hello s4u, I'm ready to compute after a lock_guard
+> [Jupiter:worker:(11) 0.000000] [s4u_test/INFO] I'm done, good bye
+> [Tremblay:worker:(2) 0.000000] [s4u_test/INFO] Hello s4u, I'm ready to compute after a regular lock
+> [Tremblay:worker:(2) 0.000000] [s4u_test/INFO] I'm done, good bye
+> [Tremblay:worker:(4) 0.000000] [s4u_test/INFO] Hello s4u, I'm ready to compute after a regular lock
+> [Tremblay:worker:(4) 0.000000] [s4u_test/INFO] I'm done, good bye
+> [Tremblay:worker:(6) 0.000000] [s4u_test/INFO] Hello s4u, I'm ready to compute after a regular lock
+> [Tremblay:worker:(6) 0.000000] [s4u_test/INFO] I'm done, good bye
+> [Tremblay:worker:(8) 0.000000] [s4u_test/INFO] Hello s4u, I'm ready to compute after a regular lock
+> [Tremblay:worker:(8) 0.000000] [s4u_test/INFO] I'm done, good bye
+> [Tremblay:worker:(10) 0.000000] [s4u_test/INFO] Hello s4u, I'm ready to compute after a regular lock
+> [Tremblay:worker:(10) 0.000000] [s4u_test/INFO] I'm done, good bye
+> [Tremblay:worker:(12) 0.000000] [s4u_test/INFO] Hello s4u, I'm ready to compute after a regular lock
+> [Tremblay:worker:(12) 0.000000] [s4u_test/INFO] I'm done, good bye
+> [0.000000] [s4u_test/INFO] Result[0] -> 2
+> [0.000000] [s4u_test/INFO] Result[1] -> 2
+> [0.000000] [s4u_test/INFO] Result[2] -> 2
+> [0.000000] [s4u_test/INFO] Result[3] -> 2
+> [0.000000] [s4u_test/INFO] Result[4] -> 2
+> [0.000000] [s4u_test/INFO] Result[5] -> 2
index eb2a5e1..d63b175 100644 (file)
@@ -26,6 +26,7 @@ $ ${bindir:=.}/../../../bin/simgrid-mc --log=mc_dfs.thres:verbose --log=root.fmt
 > [Checker] Execute 2: SEM_LOCK(semaphore: 1) (stack depth: 22, state: 22, 0 interleaves)
 > [Checker] Execute 2: SEM_WAIT(semaphore: 1, granted: yes) (stack depth: 23, state: 23, 0 interleaves)
 > [Checker] Execute 2: SEM_UNLOCK(semaphore: 0) (stack depth: 24, state: 24, 0 interleaves)
+> [Checker] Execution came to an end at 1;1;1;1;2;2;2;1;1;1;2;2;2;1;1;1;2;2;2;1;1;2;2;2;0 (state: 25, depth: 25)
 > [Checker] Backtracking from 1;1;1;1;2;2;2;1;1;1;2;2;2;1;1;1;2;2;2;1;1;2;2;2;0
 > [Checker] INDEPENDENT Transitions:
 > [Checker]   SEM_UNLOCK(semaphore: 1) (state=21)
index 823f226..8fe6841 100644 (file)
@@ -1,5 +1,5 @@
 <?xml version='1.0'?>
-<!DOCTYPE platform SYSTEM "http://simgrid.gforge.inria.fr/simgrid/simgrid.dtd">
+<!DOCTYPE platform SYSTEM "https://simgrid.org/simgrid.dtd">
 <platform version="4.1">
   <zone id="AS0" routing="Floyd">
 
index ab46961..fe84e47 100644 (file)
@@ -33,6 +33,7 @@ class ResultHolder:
 
 
 def worker_context_manager(mutex: Mutex, result: ResultHolder):
+    # When using a context manager, the lock and the unlock are automatic. This is the easiest approach
     with mutex:
         this_actor.info(f"Hello simgrid, I'm ready to compute after acquiring the mutex from a context manager")
         result.value += 1
@@ -40,6 +41,8 @@ def worker_context_manager(mutex: Mutex, result: ResultHolder):
 
 
 def worker(mutex: Mutex, result: ResultHolder):
+    # If you lock your mutex manually, you also have to unlock it.
+    # Beware of exceptions preventing your unlock() from being executed!
     mutex.lock()
     this_actor.info("Hello simgrid, I'm ready to compute after a regular lock")
     result.value += 1
@@ -47,25 +50,24 @@ def worker(mutex: Mutex, result: ResultHolder):
     this_actor.info("I'm done, good bye")
 
 
-def master(settings):
+
+def main():
+    settings = create_parser().parse_known_args()[0]
+    e = Engine(sys.argv)
+    e.load_platform(settings.platform)
+
+    # Create the requested amount of actors pairs. Each pair has a specific mutex and cell in `result`
     results = [ResultHolder(value=0) for _ in range(settings.actors)]
     for i in range(settings.actors):
         mutex = Mutex()
         Actor.create(f"worker-{i}(mgr)", Host.by_name("Jupiter"), worker_context_manager, mutex, results[i])
         Actor.create(f"worker-{i}", Host.by_name("Tremblay"), worker, mutex, results[i])
-    this_actor.sleep_for(10)
-    for i in range(settings.actors):
-        this_actor.info(f"Result[{i}] -> {results[i].value}")
-    this_actor.info("I'm done, good bye")
 
-
-def main():
-    settings = create_parser().parse_known_args()[0]
-    e = Engine(sys.argv)
-    e.load_platform(settings.platform)
-    Actor.create("master", Host.by_name("Tremblay"), master, settings)
     e.run()
 
+    for i in range(settings.actors):
+        this_actor.info(f"Result[{i}] -> {results[i].value}")
+
 
 if __name__ == "__main__":
     main()
index 2271c0a..372a2ca 100644 (file)
@@ -2,41 +2,36 @@
 
 p Testing Mutex
 
-$ ${pythoncmd:=python3} ${PYTHON_TOOL_OPTIONS:=} ${bindir:=.}/synchro-mutex.py --platform ${platfdir}/two_hosts.xml --actors 0 "--log=root.fmt:[%10.6r]%e(%i:%a@%h)%e%m%n"
->[ 10.000000] (1:master@Tremblay) I'm done, good bye
-
 $ ${pythoncmd:=python3} ${PYTHON_TOOL_OPTIONS:=} ${bindir:=.}/synchro-mutex.py --platform ${platfdir}/two_hosts.xml --actors 1 "--log=root.fmt:[%10.6r]%e(%i:%a@%h)%e%m%n"
->[  0.000000] (2:worker-0(mgr)@Jupiter) Hello simgrid, I'm ready to compute after acquiring the mutex from a context manager
->[  0.000000] (2:worker-0(mgr)@Jupiter) I'm done, good bye
->[  0.000000] (3:worker-0@Tremblay) Hello simgrid, I'm ready to compute after a regular lock
->[  0.000000] (3:worker-0@Tremblay) I'm done, good bye
->[ 10.000000] (1:master@Tremblay) Result[0] -> 2
->[ 10.000000] (1:master@Tremblay) I'm done, good bye
+>[  0.000000] (1:worker-0(mgr)@Jupiter) Hello simgrid, I'm ready to compute after acquiring the mutex from a context manager
+>[  0.000000] (2:worker-0@Tremblay) Hello simgrid, I'm ready to compute after a regular lock
+>[  0.000000] (1:worker-0(mgr)@Jupiter) I'm done, good bye
+>[  0.000000] (2:worker-0@Tremblay) I'm done, good bye
+>[  0.000000] (0:maestro@) Result[0] -> 2
 
 $ ${pythoncmd:=python3} ${PYTHON_TOOL_OPTIONS:=} ${bindir:=.}/synchro-mutex.py --platform ${platfdir}/two_hosts.xml --actors 5 "--log=root.fmt:[%10.6r]%e(%i:%a@%h)%e%m%n"
->[  0.000000] (2:worker-0(mgr)@Jupiter) Hello simgrid, I'm ready to compute after acquiring the mutex from a context manager
->[  0.000000] (2:worker-0(mgr)@Jupiter) I'm done, good bye
->[  0.000000] (3:worker-0@Tremblay) Hello simgrid, I'm ready to compute after a regular lock
->[  0.000000] (3:worker-0@Tremblay) I'm done, good bye
->[  0.000000] (4:worker-1(mgr)@Jupiter) Hello simgrid, I'm ready to compute after acquiring the mutex from a context manager
->[  0.000000] (4:worker-1(mgr)@Jupiter) I'm done, good bye
->[  0.000000] (5:worker-1@Tremblay) Hello simgrid, I'm ready to compute after a regular lock
->[  0.000000] (5:worker-1@Tremblay) I'm done, good bye
->[  0.000000] (6:worker-2(mgr)@Jupiter) Hello simgrid, I'm ready to compute after acquiring the mutex from a context manager
->[  0.000000] (6:worker-2(mgr)@Jupiter) I'm done, good bye
->[  0.000000] (7:worker-2@Tremblay) Hello simgrid, I'm ready to compute after a regular lock
->[  0.000000] (7:worker-2@Tremblay) I'm done, good bye
->[  0.000000] (8:worker-3(mgr)@Jupiter) Hello simgrid, I'm ready to compute after acquiring the mutex from a context manager
->[  0.000000] (8:worker-3(mgr)@Jupiter) I'm done, good bye
->[  0.000000] (9:worker-3@Tremblay) Hello simgrid, I'm ready to compute after a regular lock
->[  0.000000] (9:worker-3@Tremblay) I'm done, good bye
->[  0.000000] (10:worker-4(mgr)@Jupiter) Hello simgrid, I'm ready to compute after acquiring the mutex from a context manager
->[  0.000000] (10:worker-4(mgr)@Jupiter) I'm done, good bye
->[  0.000000] (11:worker-4@Tremblay) Hello simgrid, I'm ready to compute after a regular lock
->[  0.000000] (11:worker-4@Tremblay) I'm done, good bye
->[ 10.000000] (1:master@Tremblay) Result[0] -> 2
->[ 10.000000] (1:master@Tremblay) Result[1] -> 2
->[ 10.000000] (1:master@Tremblay) Result[2] -> 2
->[ 10.000000] (1:master@Tremblay) Result[3] -> 2
->[ 10.000000] (1:master@Tremblay) Result[4] -> 2
->[ 10.000000] (1:master@Tremblay) I'm done, good bye
+>[  0.000000] (1:worker-0(mgr)@Jupiter) Hello simgrid, I'm ready to compute after acquiring the mutex from a context manager
+>[  0.000000] (3:worker-1(mgr)@Jupiter) Hello simgrid, I'm ready to compute after acquiring the mutex from a context manager
+>[  0.000000] (5:worker-2(mgr)@Jupiter) Hello simgrid, I'm ready to compute after acquiring the mutex from a context manager
+>[  0.000000] (7:worker-3(mgr)@Jupiter) Hello simgrid, I'm ready to compute after acquiring the mutex from a context manager
+>[  0.000000] (9:worker-4(mgr)@Jupiter) Hello simgrid, I'm ready to compute after acquiring the mutex from a context manager
+>[  0.000000] (2:worker-0@Tremblay) Hello simgrid, I'm ready to compute after a regular lock
+>[  0.000000] (1:worker-0(mgr)@Jupiter) I'm done, good bye
+>[  0.000000] (4:worker-1@Tremblay) Hello simgrid, I'm ready to compute after a regular lock
+>[  0.000000] (3:worker-1(mgr)@Jupiter) I'm done, good bye
+>[  0.000000] (6:worker-2@Tremblay) Hello simgrid, I'm ready to compute after a regular lock
+>[  0.000000] (5:worker-2(mgr)@Jupiter) I'm done, good bye
+>[  0.000000] (8:worker-3@Tremblay) Hello simgrid, I'm ready to compute after a regular lock
+>[  0.000000] (7:worker-3(mgr)@Jupiter) I'm done, good bye
+>[  0.000000] (10:worker-4@Tremblay) Hello simgrid, I'm ready to compute after a regular lock
+>[  0.000000] (9:worker-4(mgr)@Jupiter) I'm done, good bye
+>[  0.000000] (2:worker-0@Tremblay) I'm done, good bye
+>[  0.000000] (4:worker-1@Tremblay) I'm done, good bye
+>[  0.000000] (6:worker-2@Tremblay) I'm done, good bye
+>[  0.000000] (8:worker-3@Tremblay) I'm done, good bye
+>[  0.000000] (10:worker-4@Tremblay) I'm done, good bye
+>[  0.000000] (0:maestro@) Result[0] -> 2
+>[  0.000000] (0:maestro@) Result[1] -> 2
+>[  0.000000] (0:maestro@) Result[2] -> 2
+>[  0.000000] (0:maestro@) Result[3] -> 2
+>[  0.000000] (0:maestro@) Result[4] -> 2
index d1d8ab4..353fcdb 100644 (file)
@@ -32,10 +32,11 @@ namespace s4u {
  * That is, activities are all the things that do take time to the actor in the simulated world.
  */
 class XBT_PUBLIC Activity : public xbt::Extendable<Activity> {
+#ifndef DOXYGEN
   friend Comm;
   friend Exec;
   friend Io;
-#ifndef DOXYGEN
+  friend kernel::activity::ActivityImpl;
   friend std::vector<ActivityPtr> create_DAG_from_dot(const std::string& filename);
   friend std::vector<ActivityPtr> create_DAG_from_DAX(const std::string& filename);
 #endif
@@ -97,7 +98,9 @@ protected:
 
 private:
   static xbt::signal<void(Activity&)> on_veto;
-  static xbt::signal<void(Activity&)> on_completion;
+  static xbt::signal<void(Activity const&)> on_completion;
+  static xbt::signal<void(Activity const&)> on_suspended;
+  static xbt::signal<void(Activity const&)> on_resumed;
 
 public:
   /*! Add a callback fired each time that the activity fails to start because of a veto (e.g., unsolved dependency or no
@@ -105,6 +108,10 @@ public:
   static void on_veto_cb(const std::function<void(Activity&)>& cb) { on_veto.connect(cb); }
   /*! Add a callback fired when the activity completes (either normally, cancelled or failed) */
   static void on_completion_cb(const std::function<void(Activity const&)>& cb) { on_completion.connect(cb); }
+  /*! Add a callback fired when the activity is suspended */
+  static void on_suspended_cb(const std::function<void(Activity const&)>& cb) { on_suspended.connect(cb); }
+  /*! Add a callback fired when the activity is resumed after being suspended */
+  static void on_resumed_cb(const std::function<void(Activity const&)>& cb) { on_resumed.connect(cb); }
 
   void vetoable_start()
   {
index 1e5e589..e066d41 100644 (file)
@@ -34,6 +34,8 @@ public:
   static BarrierPtr create(unsigned int expected_actors);
   /** Blocks into the barrier. Every waiting actors will be unlocked once the expected amount of actors reaches the barrier */
   int wait();
+  /** Returns some debug information about the barrier */
+  std::string to_string() const;
 
 #ifndef DOXYGEN
   /* refcounting */
index 6070543..84b0cbb 100644 (file)
@@ -45,13 +45,11 @@ public:
   static xbt::signal<void(Comm const&)> on_send;
   static xbt::signal<void(Comm const&)> on_recv;
   static xbt::signal<void(Comm const&)> on_start;
-  static xbt::signal<void(Comm const&)> on_completion;
 #endif
 
   static void on_send_cb(const std::function<void(Comm const&)>& cb) { on_send.connect(cb); }
   static void on_recv_cb(const std::function<void(Comm const&)>& cb) { on_recv.connect(cb); }
   static void on_start_cb(const std::function<void(Comm const&)>& cb) { on_start.connect(cb); }
-  static void on_completion_cb(const std::function<void(Activity const&)>& cb) { on_completion.connect(cb); }
   /* More callbacks */
   CommPtr set_copy_data_callback(const std::function<void(kernel::activity::CommImpl*, void*, size_t)>& callback);
   static void copy_buffer_callback(kernel::activity::CommImpl*, void*, size_t);
@@ -176,29 +174,6 @@ public:
   /*! Same as wait_all, but with a timeout. Return the number of terminated comm (less than comms.size() if the timeout
    * occurs). */
   static size_t wait_all_for(const std::vector<CommPtr>& comms, double timeout);
-
-#ifndef DOXYGEN
-  XBT_ATTRIB_DEPRECATED_v332("Please use a plain vector for parameter") static int wait_any(
-      const std::vector<CommPtr>* comms)
-  {
-    return static_cast<int>(wait_any_for(*comms, -1));
-  }
-  XBT_ATTRIB_DEPRECATED_v332("Please use a plain vector for first parameter") static int wait_any_for(
-      const std::vector<CommPtr>* comms, double timeout)
-  {
-    return static_cast<int>(wait_any_for(*comms, timeout));
-  }
-  XBT_ATTRIB_DEPRECATED_v332("Please use a plain vector for parameter") static void wait_all(
-      const std::vector<CommPtr>* comms)
-  {
-    wait_all(*comms);
-  }
-  XBT_ATTRIB_DEPRECATED_v332("Please use a plain vector for parameter") static int test_any(
-      const std::vector<CommPtr>* comms)
-  {
-    return static_cast<int>(test_any(*comms));
-  }
-#endif
 };
 } // namespace s4u
 } // namespace simgrid
index 3458593..b0cdbf2 100644 (file)
@@ -61,13 +61,6 @@ public:
   /*! Same as wait_any, but with a timeout. If the timeout occurs, parameter last is returned.*/
   static ssize_t wait_any_for(const std::vector<ExecPtr>& execs, double timeout);
 
-#ifndef DOXYGEN
-  XBT_ATTRIB_DEPRECATED_v332("Please use a plain vector for parameter")
-  static int wait_any(std::vector<ExecPtr>* execs) { return static_cast<int>(wait_any_for(*execs, -1)); }
-  XBT_ATTRIB_DEPRECATED_v332("Please use a plain vector for first parameter")
-  static int wait_any_for(std::vector<ExecPtr>* execs, double timeout) { return static_cast<int>(wait_any_for(*execs, timeout)); }
-#endif
-
   /** @brief On sequential executions, returns the amount of flops that remain to be done; This cannot be used on
    * parallel executions. */
   double get_remaining() const override;
index 1eadf70..bb6fb7f 100644 (file)
@@ -59,11 +59,6 @@ public:
   /** @brief Get the netpoint associated to this netzone */
   kernel::routing::NetPoint* get_netpoint();
 
-#ifndef DOXYGEN
-  XBT_ATTRIB_DEPRECATED_v332("Please use set_parent() to manage NetZone's relationship") NetZone* add_child(
-      NetZone* new_zone);
-#endif
-
   void extract_xbt_graph(const s_xbt_graph_t* graph, std::map<std::string, xbt_node_t, std::less<>>* nodes,
                          std::map<std::string, xbt_edge_t, std::less<>>* edges);
 
@@ -87,34 +82,12 @@ public:
   void add_route(kernel::routing::NetPoint* src, kernel::routing::NetPoint* dst, kernel::routing::NetPoint* gw_src,
                  kernel::routing::NetPoint* gw_dst, const std::vector<LinkInRoute>& link_list, bool symmetrical = true);
 
-#ifndef DOXYGEN
-  XBT_ATTRIB_DEPRECATED_v332(
-      "Please use add_route() method which uses s4u::LinkInRoute instead of "
-      "LinkImpl") void add_route(kernel::routing::NetPoint* src, kernel::routing::NetPoint* dst,
-                                 kernel::routing::NetPoint* gw_src, kernel::routing::NetPoint* gw_dst,
-                                 const std::vector<kernel::resource::StandardLinkImpl*>& link_list, bool symmetrical);
-
-  XBT_ATTRIB_DEPRECATED_v332(
-      "Please use add_bypass_route() method which uses s4u::LinkInRoute instead of "
-      "LinkImpl") void add_bypass_route(kernel::routing::NetPoint* src, kernel::routing::NetPoint* dst,
-                                        kernel::routing::NetPoint* gw_src, kernel::routing::NetPoint* gw_dst,
-                                        const std::vector<kernel::resource::StandardLinkImpl*>& link_list,
-                                        bool /*symmetrical*/);
-#endif
-
   void add_bypass_route(kernel::routing::NetPoint* src, kernel::routing::NetPoint* dst,
                         kernel::routing::NetPoint* gw_src, kernel::routing::NetPoint* gw_dst,
                         const std::vector<LinkInRoute>& link_list);
 
-#ifndef DOXYGEN
-  /*** Called on each newly created regular route (not on bypass routes) */
-  static xbt::signal<void(bool symmetrical, kernel::routing::NetPoint* src, kernel::routing::NetPoint* dst,
-                          kernel::routing::NetPoint* gw_src, kernel::routing::NetPoint* gw_dst,
-                          std::vector<kernel::resource::StandardLinkImpl*> const& link_list)>
-      on_route_creation; // XBT_ATTRIB_DEPRECATED_v332 : should not be used by users, used by ns3.. if necessary,
-                         // signal shouldn't use LinkImpl*
-
 private:
+#ifndef DOXYGEN
   static xbt::signal<void(NetZone const&)> on_creation;
   static xbt::signal<void(NetZone const&)> on_seal;
 #endif
@@ -180,13 +153,6 @@ public:
 
   /** @brief Seal this netzone configuration */
   NetZone* seal();
-
-private:
-#ifndef DOXYGEN
-  /** @brief XBT_ATTRIB_DEPRECATED_v332 Auxiliary function to convert types */
-  static std::vector<LinkInRoute>
-  convert_to_linkInRoute(const std::vector<kernel::resource::StandardLinkImpl*>& link_list);
-#endif
 };
 
 // External constructors so that the types (and the types of their content) remain hidden
index 974a1e2..c4e0691 100644 (file)
@@ -30,13 +30,13 @@ namespace s4u {
 class XBT_PUBLIC Semaphore {
 #ifndef DOXYGEN
   friend kernel::activity::SemaphoreImpl;
-  friend void kernel::activity::intrusive_ptr_release(kernel::activity::SemaphoreImpl* sem);
+  friend XBT_PUBLIC void kernel::activity::intrusive_ptr_release(kernel::activity::SemaphoreImpl* sem);
 #endif
 
   kernel::activity::SemaphoreImpl* const pimpl_;
 
-  friend void intrusive_ptr_add_ref(const Semaphore* sem);
-  friend void intrusive_ptr_release(const Semaphore* sem);
+  friend XBT_PUBLIC void intrusive_ptr_add_ref(const Semaphore* sem);
+  friend XBT_PUBLIC void intrusive_ptr_release(const Semaphore* sem);
 
   explicit Semaphore(kernel::activity::SemaphoreImpl* sem) : pimpl_(sem) {}
   ~Semaphore() = default;
index 8a7a33c..f902d64 100644 (file)
@@ -61,9 +61,6 @@ public:
     SUSPENDED, /**< Suspend/resume does not involve disk I/O, so we assume there is no transition states. */
     DESTROYED
   );
-#ifndef DOXYGEN
-  using state XBT_ATTRIB_DEPRECATED_v332("Please use VirtualMachine::State") = State;
-#endif
 
   kernel::resource::VirtualMachineImpl* get_vm_impl() const { return pimpl_vm_; }
   void start();
index 4d77ec2..a7b6705 100644 (file)
@@ -35,10 +35,6 @@ XBT_ATTRIB_DEPRECATED_v333("Please use Actor::is_maestro()") XBT_PUBLIC int SIMI
 XBT_ATTRIB_DEPRECATED_v333("Please use simgrid_set_maestro()") XBT_PUBLIC
     void SIMIX_set_maestro(void (*code)(void*), void* data);
 
-/* Simulation execution */
-XBT_ATTRIB_DEPRECATED_v332("Please use EngineImpl:run()") XBT_PUBLIC void SIMIX_run();
-XBT_ATTRIB_DEPRECATED_v332("Please use simgrid_get_clock() or Engine::get_clock()") XBT_PUBLIC double SIMIX_get_clock();
-
 SG_END_DECL
 
 /********************************* Process ************************************/
index 8698afe..c6b9787 100644 (file)
 #define XBT_ATTRIB_DEPRECATED(mesg) __attribute__((deprecated(mesg)))
 #endif
 
-#define XBT_ATTRIB_DEPRECATED_v332(mesg)                                                                               \
-  XBT_ATTRIB_DEPRECATED(mesg " (this compatibility wrapper will be dropped after v3.31)")
 #define XBT_ATTRIB_DEPRECATED_v333(mesg)                                                                               \
   XBT_ATTRIB_DEPRECATED(mesg " (this compatibility wrapper will be dropped after v3.32)")
 #define XBT_ATTRIB_DEPRECATED_v334(mesg)                                                                               \
   XBT_ATTRIB_DEPRECATED(mesg " (this compatibility wrapper will be dropped after v3.33)")
 #define XBT_ATTRIB_DEPRECATED_v335(mesg)                                                                               \
   XBT_ATTRIB_DEPRECATED(mesg " (this compatibility wrapper will be dropped after v3.34)")
+#define XBT_ATTRIB_DEPRECATED_v336(mesg)                                                                               \
+  XBT_ATTRIB_DEPRECATED(mesg " (this compatibility wrapper will be dropped after v3.35)")
 
 /* Work around https://github.com/microsoft/vscode-cpptools/issues/4503 */
 #ifdef __INTELLISENSE__
index 6a12eb7..21877a1 100755 (executable)
--- a/setup.py
+++ b/setup.py
@@ -88,7 +88,7 @@ class CMakeBuild(build_ext):
 
 setup(
     name='simgrid',
-    version='3.30.1',
+    version='3.31.1',
     author='Da SimGrid Team',
     author_email='simgrid-community@inria.fr',
     description='Toolkit for scalable simulation of distributed applications',
index 1742c3f..56d5fa2 100644 (file)
@@ -4,7 +4,7 @@
 sonar.organization=simgrid
 sonar.projectKey=simgrid_simgrid
 sonar.projectName=SimGrid
-sonar.projectVersion=3.30.1
+sonar.projectVersion=3.31.1
 
 sonar.links.homepage=https://simgrid.org
 sonar.links.issue=https://framagit.org/simgrid/simgrid/issues
index d08e791..c7762da 100644 (file)
@@ -719,9 +719,8 @@ PYBIND11_MODULE(simgrid, m)
            py::return_value_policy::reference_internal,
            py::call_guard<py::gil_scoped_release>(),
            "Start the comm, and ignore its result. It can be completely forgotten after that.")
-      // use py::overload_cast for wait_all/wait_any, until the overload marked XBT_ATTRIB_DEPRECATED_v332 is removed
       .def_static(
-          "wait_all", py::overload_cast<const std::vector<simgrid::s4u::CommPtr>&>(&simgrid::s4u::Comm::wait_all),
+          "wait_all", &simgrid::s4u::Comm::wait_all,
           py::arg("comms"),
           py::call_guard<py::gil_scoped_release>(),
           "Block until the completion of all communications in the list.")
@@ -731,13 +730,13 @@ PYBIND11_MODULE(simgrid, m)
                   "Block until the completion of all communications in the list, or raises TimeoutException after "
                   "the specified timeout.")
       .def_static(
-          "wait_any", py::overload_cast<const std::vector<simgrid::s4u::CommPtr>&>(&simgrid::s4u::Comm::wait_any),
+          "wait_any", &simgrid::s4u::Comm::wait_any,
           py::arg("comms"),
           py::call_guard<py::gil_scoped_release>(),
           "Block until the completion of any communication in the list and return the index of the terminated one.")
       .def_static(
           "wait_any_for",
-          py::overload_cast<const std::vector<simgrid::s4u::CommPtr>&, double>(&simgrid::s4u::Comm::wait_any_for),
+          &simgrid::s4u::Comm::wait_any_for,
           py::arg("comms"), py::arg("timeout"),
           py::call_guard<py::gil_scoped_release>(),
           "Block until the completion of any communication in the list and return the index of the terminated "
index f06eb01..dba451c 100644 (file)
@@ -10,9 +10,6 @@
 #include <simgrid/s4u/Host.hpp>
 #include <simgrid/sg_config.hpp>
 
-#define SIMIX_H_NO_DEPRECATED_WARNING // avoid deprecation warning on include (remove with XBT_ATTRIB_DEPRECATED_v332)
-#include <simgrid/simix.h>
-
 #include "mc/mc.h"
 #include "src/kernel/EngineImpl.hpp"
 #include "src/kernel/resource/StandardLinkImpl.hpp"
 #include "src/mc/remote/AppSide.hpp"
 #endif
 
-double NOW = 0;
-
 XBT_LOG_NEW_DEFAULT_CATEGORY(ker_engine, "Logging specific to Engine (kernel)");
 
 namespace simgrid {
 namespace kernel {
+double EngineImpl::now_           = 0.0;
 EngineImpl* EngineImpl::instance_ = nullptr; /* That singleton is awful too. */
 
 config::Flag<double> cfg_breakpoint{"debug/breakpoint",
@@ -345,7 +341,7 @@ void EngineImpl::seal_platform() const
 void EngineImpl::load_platform(const std::string& platf)
 {
   double start = xbt_os_time();
-  if (boost::algorithm::ends_with(platf, ".so") or boost::algorithm::ends_with(platf, ".dylib")) {
+  if (boost::algorithm::ends_with(platf, ".so") || boost::algorithm::ends_with(platf, ".dylib")) {
 #ifdef _WIN32
     xbt_die("loading platform through shared library isn't supported on windows");
 #else
@@ -536,7 +532,7 @@ void EngineImpl::presolve() const
   XBT_DEBUG("Consume all trace events occurring before the starting time.");
   double next_event_date;
   while ((next_event_date = profile::future_evt_set.next_date()) != -1.0) {
-    if (next_event_date > NOW)
+    if (next_event_date > now_)
       break;
 
     double value                 = -1.0;
@@ -549,7 +545,7 @@ void EngineImpl::presolve() const
 
   XBT_DEBUG("Set every models in the right state by updating them to 0.");
   for (auto const& model : models_)
-    model->update_actions_state(NOW, 0.0);
+    model->update_actions_state(now_, 0.0);
 }
 
 double EngineImpl::solve(double max_date) const
@@ -559,9 +555,9 @@ double EngineImpl::solve(double max_date) const
   resource::Resource* resource = nullptr;
 
   if (max_date != -1.0) {
-    xbt_assert(max_date >= NOW, "You asked to simulate up to %f, but that's in the past already", max_date);
+    xbt_assert(max_date >= now_, "You asked to simulate up to %f, but that's in the past already", max_date);
 
-    time_delta = max_date - NOW;
+    time_delta = max_date - now_;
   }
 
   XBT_DEBUG("Looking for next event in all models");
@@ -569,7 +565,7 @@ double EngineImpl::solve(double max_date) const
     if (not model->next_occurring_event_is_idempotent()) {
       continue;
     }
-    double next_event = model->next_occurring_event(NOW);
+    double next_event = model->next_occurring_event(now_);
     if ((time_delta < 0.0 || next_event < time_delta) && next_event >= 0.0) {
       time_delta = next_event;
     }
@@ -590,9 +586,9 @@ double EngineImpl::solve(double max_date) const
         continue;
 
       if (next_event_date != -1.0) {
-        time_delta = std::min(next_event_date - NOW, time_delta);
+        time_delta = std::min(next_event_date - now_, time_delta);
       } else {
-        time_delta = std::max(next_event_date - NOW, time_delta); // Get the positive component
+        time_delta = std::max(next_event_date - now_, time_delta); // Get the positive component
       }
 
       XBT_DEBUG("Run the NS3 network at most %fs", time_delta);
@@ -604,29 +600,29 @@ double EngineImpl::solve(double max_date) const
         time_delta = model_next_action_end;
     }
 
-    if (next_event_date < 0.0 || (next_event_date > NOW + time_delta)) {
+    if (next_event_date < 0.0 || (next_event_date > now_ + time_delta)) {
       // next event may have already occurred or will after the next resource change, then bail out
       XBT_DEBUG("no next usable TRACE event. Stop searching for it");
       break;
     }
 
-    XBT_DEBUG("Updating models (min = %g, NOW = %g, next_event_date = %g)", time_delta, NOW, next_event_date);
+    XBT_DEBUG("Updating models (min = %g, NOW = %g, next_event_date = %g)", time_delta, now_, next_event_date);
 
     while (auto* event = profile::future_evt_set.pop_leq(next_event_date, &value, &resource)) {
       if (resource->is_used() || (watched_hosts().find(resource->get_cname()) != watched_hosts().end())) {
-        time_delta = next_event_date - NOW;
+        time_delta = next_event_date - now_;
         XBT_DEBUG("This event invalidates the next_occurring_event() computation of models. Next event set to %f",
                   time_delta);
       }
-      // FIXME: I'm too lame to update NOW live, so I change it and restore it so that the real update with surf_min
+      // FIXME: I'm too lame to update now_ live, so I change it and restore it so that the real update with surf_min
       // will work
-      double round_start = NOW;
-      NOW                = next_event_date;
+      double round_start = now_;
+      now_               = next_event_date;
       /* update state of the corresponding resource to the new value. Does not touch lmm.
          It will be modified if needed when updating actions */
       XBT_DEBUG("Calling update_resource_state for resource %s", resource->get_cname());
       resource->apply_event(event, value);
-      NOW = round_start;
+      now_ = round_start;
     }
   }
 
@@ -643,11 +639,11 @@ double EngineImpl::solve(double max_date) const
   XBT_DEBUG("Duration set to %f", time_delta);
 
   // Bump the time: jump into the future
-  NOW = NOW + time_delta;
+  now_ += time_delta;
 
   // Inform the models of the date change
   for (auto const& model : models_)
-    model->update_actions_state(NOW, time_delta);
+    model->update_actions_state(now_, time_delta);
 
   s4u::Engine::on_time_advance(time_delta);
 
@@ -723,9 +719,9 @@ void EngineImpl::run(double max_date)
       next_time = std::min(next_time, max_date);
     }
 
-    XBT_DEBUG("Calling solve(%g) %g", next_time, NOW);
+    XBT_DEBUG("Calling solve(%g) %g", next_time, now_);
     elapsed_time = solve(next_time);
-    XBT_DEBUG("Moving time ahead. NOW=%g; elapsed: %g", NOW, elapsed_time);
+    XBT_DEBUG("Moving time ahead. NOW=%g; elapsed: %g", now_, elapsed_time);
 
     // Execute timers until there isn't anything to be done:
     bool again = false;
@@ -745,7 +741,8 @@ void EngineImpl::run(double max_date)
         XBT_CRITICAL("Oops! Daemon actors cannot do any blocking activity (communications, synchronization, etc) "
                      "once the simulation is over. Please fix your on_exit() functions.");
       } else {
-        XBT_CRITICAL("Oops! Deadlock or code not perfectly clean.");
+        XBT_CRITICAL("Oops! Deadlock detected, some activities are still around but will never complete. "
+                     "This usually happens when the user code is not perfectly clean.");
       }
       display_all_actor_status();
       simgrid::s4u::Engine::on_deadlock();
@@ -755,7 +752,7 @@ void EngineImpl::run(double max_date)
       }
     }
   } while ((vetoed_activities == nullptr || vetoed_activities->empty()) &&
-           ((elapsed_time > -1.0 && not double_equals(max_date, NOW, 0.00001)) || has_actors_to_run()));
+           ((elapsed_time > -1.0 && not double_equals(max_date, now_, 0.00001)) || has_actors_to_run()));
 
   if (not actor_list_.empty() && max_date < 0 && not(vetoed_activities == nullptr || vetoed_activities->empty()))
     THROW_IMPOSSIBLE;
@@ -765,12 +762,7 @@ void EngineImpl::run(double max_date)
 
 double EngineImpl::get_clock()
 {
-  return NOW;
+  return now_;
 }
 } // namespace kernel
 } // namespace simgrid
-
-void SIMIX_run() // XBT_ATTRIB_DEPRECATED_v332
-{
-  simgrid::kernel::EngineImpl::get_instance()->run(-1);
-}
index 0ddfc52..28d6c57 100644 (file)
@@ -65,6 +65,7 @@ class EngineImpl {
   xbt_dynar_t actors_vector_      = xbt_dynar_new(sizeof(actor::ActorImpl*), nullptr);
 #endif
 
+  static double now_;
   static EngineImpl* instance_;
   actor::ActorImpl* maestro_ = nullptr;
   context::ContextFactory* context_factory_ = nullptr;
index dbf06bc..3c47e41 100644 (file)
@@ -4,6 +4,7 @@
  * under the terms of the license (GNU LGPL) which comes with this package. */
 
 #include <simgrid/modelchecker.h>
+#include <simgrid/s4u/Activity.hpp>
 #include <simgrid/s4u/Engine.hpp>
 
 #include "src/kernel/activity/ActivityImpl.hpp"
@@ -180,7 +181,7 @@ void ActivityImpl::suspend()
     return;
   XBT_VERB("This activity is suspended (remain: %f)", surf_action_->get_remains());
   surf_action_->suspend();
-  on_suspended(*this);
+  s4u::Activity::on_suspended(*get_iface());
 }
 
 void ActivityImpl::resume()
@@ -189,7 +190,7 @@ void ActivityImpl::resume()
     return;
   XBT_VERB("This activity is resumed (remain: %f)", surf_action_->get_remains());
   surf_action_->resume();
-  on_resumed(*this);
+  s4u::Activity::on_resumed(*get_iface());
 }
 
 void ActivityImpl::cancel()
@@ -236,8 +237,6 @@ void intrusive_ptr_release(ActivityImpl* activity)
     delete activity;
   }
 }
-xbt::signal<void(ActivityImpl const&)> ActivityImpl::on_resumed;
-xbt::signal<void(ActivityImpl const&)> ActivityImpl::on_suspended;
 }
 }
 } // namespace simgrid::kernel::activity::
index 68126bc..5a5404e 100644 (file)
@@ -91,9 +91,6 @@ public:
   friend XBT_PUBLIC void intrusive_ptr_add_ref(ActivityImpl* activity);
   friend XBT_PUBLIC void intrusive_ptr_release(ActivityImpl* activity);
   int get_refcount() const { return static_cast<int>(refcount_); } // For debugging purpose
-
-  static xbt::signal<void(ActivityImpl const&)> on_suspended;
-  static xbt::signal<void(ActivityImpl const&)> on_resumed;
 };
 
 /* This class exists to allow chained setters as in exec->set_name()->set_priority()->set_blah()
index e34ba73..083b874 100644 (file)
@@ -74,6 +74,11 @@ public:
   }
 
   s4u::Barrier& get_iface() { return piface_; }
+
+  std::string to_string() const
+  {
+    return xbt::string_printf("Barrier %u: %zu of %u", id_, ongoing_acquisitions_.size(), expected_actors_);
+  }
 };
 } // namespace activity
 } // namespace kernel
index ef37508..a9e747f 100644 (file)
@@ -39,16 +39,9 @@ namespace kernel {
 namespace actor {
 
 /*------------------------- [ ActorIDTrait ] -------------------------*/
-static unsigned long maxpid = 0;
-unsigned long get_maxpid()
-{
-  return maxpid;
-}
-unsigned long* get_maxpid_addr()
-{
-  return &maxpid;
-}
-ActorIDTrait::ActorIDTrait(const std::string& name, aid_t ppid) : name_(name), pid_(maxpid++), ppid_(ppid) {}
+unsigned long ActorIDTrait::maxpid_ = 0;
+
+ActorIDTrait::ActorIDTrait(const std::string& name, aid_t ppid) : name_(name), pid_(maxpid_++), ppid_(ppid) {}
 
 ActorImpl* ActorImpl::self()
 {
index d822f6d..f27b624 100644 (file)
@@ -27,15 +27,19 @@ class XBT_PUBLIC ActorIDTrait {
   aid_t pid_         = 0;
   aid_t ppid_        = -1;
 
+  static unsigned long maxpid_;
+
 public:
   explicit ActorIDTrait(const std::string& name, aid_t ppid);
   const xbt::string& get_name() const { return name_; }
   const char* get_cname() const { return name_.c_str(); }
   aid_t get_pid() const { return pid_; }
   aid_t get_ppid() const { return ppid_; }
+
+  static unsigned long get_maxpid() { return maxpid_; }
+  // In MC mode, the application sends this pointer to the MC
+  static unsigned long* get_maxpid_addr() { return &maxpid_; }
 };
-XBT_PUBLIC unsigned long get_maxpid();
-XBT_PUBLIC unsigned long* get_maxpid_addr(); // In MC mode, the application sends this pointers to the MC
 
 /*------------------------- [ ActorRestartingTrait ] -------------------------*/
 class XBT_PUBLIC ActorRestartingTrait {
index c9f732e..af027a7 100644 (file)
@@ -58,16 +58,16 @@ class DiskImpl : public Resource_T<DiskImpl>, public xbt::PropertyHolder {
   std::unordered_map<s4u::Disk::Operation, s4u::NonLinearResourceCb> sharing_policy_cb_ = {};
   std::function<s4u::Disk::IoFactorCb> factor_cb_                                       = {};
 
+  Metric read_bw_      = {0.0, 0, nullptr};
+  Metric write_bw_     = {0.0, 0, nullptr};
+  double readwrite_bw_ = -1; /* readwrite constraint bound, usually max(read, write) */
+
   void apply_sharing_policy_cfg();
 
 protected:
   ~DiskImpl() override = default; // Disallow direct deletion. Call destroy() instead.
 
 public:
-  Metric read_bw_  = {0.0, 0, nullptr};
-  Metric write_bw_ = {0.0, 0, nullptr};
-  double readwrite_bw_ = -1; /* readwrite constraint bound, usually max(read, write) */
-
   explicit DiskImpl(const std::string& name, double read_bandwidth, double write_bandwidth);
   DiskImpl(const DiskImpl&) = delete;
   DiskImpl& operator=(const DiskImpl&) = delete;
@@ -78,13 +78,14 @@ public:
   DiskImpl* set_host(s4u::Host* host);
   s4u::Host* get_host() const { return host_; }
 
-  virtual void set_read_bandwidth(double read_bw) = 0;
+  virtual void set_read_bandwidth(double value) { read_bw_.peak = value; }
   double get_read_bandwidth() const { return read_bw_.peak * read_bw_.scale; }
 
-  virtual void set_write_bandwidth(double write_bw) = 0;
+  virtual void set_write_bandwidth(double value) { write_bw_.peak = value; }
   double get_write_bandwidth() const { return write_bw_.peak * write_bw_.scale; }
 
-  virtual void set_readwrite_bandwidth(double bw) = 0;
+  virtual void set_readwrite_bandwidth(double value) { readwrite_bw_ = value; }
+  double get_readwrite_bandwidth() const { return readwrite_bw_; }
 
   DiskImpl* set_read_constraint(lmm::Constraint* constraint_read);
   lmm::Constraint* get_read_constraint() const { return constraint_read_; }
@@ -92,6 +93,12 @@ public:
   DiskImpl* set_write_constraint(lmm::Constraint* constraint_write);
   lmm::Constraint* get_write_constraint() const { return constraint_write_; }
 
+  profile::Event* get_read_event() const { return read_bw_.event; }
+  void unref_read_event() { tmgr_trace_event_unref(&read_bw_.event); }
+
+  profile::Event* get_write_event() const { return write_bw_.event; }
+  void unref_write_event() { tmgr_trace_event_unref(&write_bw_.event); }
+
   DiskImpl* set_read_bandwidth_profile(profile::Profile* profile);
   DiskImpl* set_write_bandwidth_profile(profile::Profile* profile);
 
index e741ba1..2c36cac 100644 (file)
@@ -92,13 +92,13 @@ static void remove_active_exec(s4u::Activity const& task)
   }
 }
 
-static s4u::VirtualMachine* get_vm_from_activity(kernel::activity::ActivityImpl const& act)
+static s4u::VirtualMachine* get_vm_from_activity(s4u::Activity const& act)
 {
-  auto* exec = dynamic_cast<kernel::activity::ExecImpl const*>(&act);
+  auto* exec = dynamic_cast<kernel::activity::ExecImpl const*>(act.get_impl());
   return exec != nullptr ? dynamic_cast<s4u::VirtualMachine*>(exec->get_host()) : nullptr;
 }
 
-static void add_active_activity(kernel::activity::ActivityImpl const& act)
+static void add_active_activity(s4u::Activity const& act)
 {
   const s4u::VirtualMachine* vm = get_vm_from_activity(act);
   if (vm != nullptr) {
@@ -108,7 +108,7 @@ static void add_active_activity(kernel::activity::ActivityImpl const& act)
   }
 }
 
-static void remove_active_activity(kernel::activity::ActivityImpl const& act)
+static void remove_active_activity(s4u::Activity const& act)
 {
   const s4u::VirtualMachine* vm = get_vm_from_activity(act);
   if (vm != nullptr) {
@@ -123,8 +123,8 @@ VMModel::VMModel(const std::string& name) : HostModel(name)
   s4u::Host::on_state_change_cb(host_state_change);
   s4u::Exec::on_start_cb(add_active_exec);
   s4u::Activity::on_completion_cb(remove_active_exec);
-  activity::ActivityImpl::on_resumed.connect(add_active_activity);
-  activity::ActivityImpl::on_suspended.connect(remove_active_activity);
+  s4u::Activity::on_resumed_cb(add_active_activity);
+  s4u::Activity::on_suspended_cb(remove_active_activity);
 }
 
 double VMModel::next_occurring_event(double now)
index 0f17aa7..a00d6bc 100644 (file)
@@ -38,14 +38,11 @@ Event* Profile::schedule(FutureEvtSet* fes, resource::Resource* resource)
 
   fes_ = fes;
 
-  if(event_list.empty())
-    cb(event_list);
-
-  if(event_list.empty()) {
+  if (get_enough_events(0)) {
+    fes_->add_event(event_list[0].date_, event);
+  } else {
     event->free_me  = true;
     tmgr_trace_event_unref(&event);
-  } else {
-    fes_->add_event(event_list[0].date_, event);
   }
   return event;
 }
@@ -59,15 +56,13 @@ DatedValue Profile::next(Event* event)
 
   event->idx++;
 
-  if (event->idx == event_list.size())
-    cb(event_list);
-  if(event->idx>=event_list.size())
-    event->free_me = true;
-  else {
-    const DatedValue& nextDateVal = event_list.at(event->idx);
+  if (get_enough_events(event->idx)) {
+    const DatedValue& nextDateVal = event_list[event->idx];
     xbt_assert(nextDateVal.date_>=0);
     xbt_assert(nextDateVal.value_>=0);
     fes_->add_event(event_date +nextDateVal.date_, event);
+  } else {
+    event->free_me = true;
   }
   return dateVal;
 }
@@ -77,7 +72,7 @@ Profile::Profile(const std::string& name, const std::function<ProfileBuilder::Up
 {
   xbt_assert(trace_list.find(name) == trace_list.end(), "Refusing to define trace %s twice", name.c_str());
   trace_list.insert({name,this});
-  cb(event_list);
+  get_enough_events(0);
 }
 
 } // namespace profile
index 9b9402a..5c51540 100644 (file)
@@ -54,6 +54,13 @@ private:
   std::vector<DatedValue> event_list;
   FutureEvtSet* fes_  = nullptr;
   double repeat_delay;
+
+  bool get_enough_events(size_t index)
+  {
+    if (index >= event_list.size() && cb)
+      cb(event_list);
+    return index < event_list.size();
+  }
 };
 
 } // namespace profile
index 3db3726..d7ba428 100644 (file)
@@ -144,7 +144,7 @@ public:
       }
 
       xbt_assert(splittedval.size() > i, "Invalid profile line");
-      if (i == 1 or i == 2) {
+      if (i == 1 || i == 2) {
         stochevent.date_params = {std::stod(splittedval[i - 1])};
       } else if (i == 3) {
         stochevent.date_params = {std::stod(splittedval[1]), std::stod(splittedval[2])};
@@ -169,7 +169,7 @@ public:
       }
 
       xbt_assert(splittedval.size() > i + j, "Invalid profile line");
-      if (j == 0 or j == 1) {
+      if (j == 0 || j == 1) {
         stochevent.value_params = {std::stod(splittedval[i + j])};
       } else if (j == 2) {
         stochevent.value_params = {std::stod(splittedval[i + 1]), std::stod(splittedval[i + 2])};
@@ -188,9 +188,9 @@ public:
       pattern.emplace_back(stochevent);
     }
 
-    xbt_assert(not stochastic or periodicity <= 0, "If you want periodicity with stochastic profiles, use LOOP_AFTER");
+    xbt_assert(not stochastic || periodicity <= 0, "If you want periodicity with stochastic profiles, use LOOP_AFTER");
     if (periodicity > 0) {
-      xbt_assert(loop and loop_delay == 0);
+      xbt_assert(loop && loop_delay == 0);
       loop_delay = periodicity - last_date;
     }
 
@@ -199,7 +199,7 @@ public:
 
   double get_repeat_delay() const
   {
-    if (not stochastic and loop)
+    if (not stochastic && loop)
       return loop_delay;
     return -1.0;
   }
@@ -207,7 +207,7 @@ public:
   void operator()(std::vector<DatedValue>& event_list) const
   {
     size_t initial_size = event_list.size();
-    if (loop or not initial_size) {
+    if (loop || not initial_size) {
       for (auto const& dv : pattern)
         event_list.emplace_back(dv.get_datedvalue());
       if (initial_size)
@@ -237,7 +237,7 @@ Profile* ProfileBuilder::from_file(const std::string& path)
 
 
 Profile* ProfileBuilder::from_void() {
-  static Profile void_profile("__void__",[](std::vector<DatedValue>&){},-1.0);
+  static Profile void_profile("__void__", nullptr, -1.0);
   return &void_profile;
 }
 
index 021c7b8..ebdeeee 100644 (file)
@@ -165,7 +165,6 @@ void RoutedZone::add_route_check_params(NetPoint* src, NetPoint* dst, NetPoint*
     xbt_assert(not dst->is_netzone(),
                "When defining a route, dst cannot be a netzone such as '%s'. Did you meant to have a NetzoneRoute?",
                dstName);
-    s4u::NetZone::on_route_creation(symmetrical, src, dst, gw_src, gw_dst, get_link_list_impl(link_list, false));
     NetZoneImpl::on_route_creation(symmetrical, src, dst, gw_src, gw_dst, get_link_list_impl(link_list, false));
   } else {
     XBT_DEBUG("Load NetzoneRoute from %s@%s to %s@%s", srcName, gw_src->get_cname(), dstName, gw_dst->get_cname());
@@ -196,7 +195,6 @@ void RoutedZone::add_route_check_params(NetPoint* src, NetPoint* dst, NetPoint*
                "Invalid NetzoneRoute from %s@%s to %s@%s: gw_dst %s belongs to %s, not to %s.", srcName,
                gw_src->get_cname(), dstName, gw_dst->get_cname(), gw_dst->get_cname(),
                gw_dst->get_englobing_zone()->get_cname(), dst->get_cname());
-    s4u::NetZone::on_route_creation(symmetrical, gw_src, gw_dst, gw_src, gw_dst, get_link_list_impl(link_list, false));
     NetZoneImpl::on_route_creation(symmetrical, gw_src, gw_dst, gw_src, gw_dst, get_link_list_impl(link_list, false));
   }
 }
index 8bf67d3..ecb376e 100644 (file)
@@ -29,6 +29,8 @@ class ModelChecker {
   std::unique_ptr<RemoteProcess> remote_process_;
   Exploration* exploration_ = nullptr;
 
+  unsigned long visited_states_ = 0;
+
   // Expect MessageType::SIMCALL_TO_STRING or MessageType::SIMCALL_DOT_LABEL
   std::string simcall_to_string(MessageType type, aid_t aid, int times_considered);
 
@@ -62,13 +64,13 @@ public:
   Exploration* get_exploration() const { return exploration_; }
   void set_exploration(Exploration* exploration) { exploration_ = exploration; }
 
+  unsigned long get_visited_states() const { return visited_states_; }
+  void inc_visited_states() { visited_states_++; }
+
 private:
   void setup_ignore();
   bool handle_message(const char* buffer, ssize_t size);
   void handle_waitpid();
-
-public:
-  unsigned long visited_states = 0;
 };
 
 }
index ad9a135..873154c 100644 (file)
@@ -44,9 +44,9 @@ std::unique_ptr<simgrid::mc::VisitedState>
 VisitedStates::addVisitedState(unsigned long state_number, simgrid::mc::State* graph_state, bool compare_snapshots)
 {
   auto new_state             = std::make_unique<simgrid::mc::VisitedState>(state_number);
-  graph_state->system_state_ = new_state->system_state;
+  graph_state->set_system_state(new_state->system_state);
   XBT_DEBUG("Snapshot %p of visited state %ld (exploration stack state %ld)", new_state->system_state.get(),
-            new_state->num, graph_state->num_);
+            new_state->num, graph_state->get_num());
 
   auto range = boost::range::equal_range(states_, new_state.get(), Api::get().compare_pair());
 
index a953919..a9aaba9 100644 (file)
@@ -88,12 +88,12 @@ std::size_t Api::get_remote_heap_bytes() const
 
 void Api::mc_inc_visited_states() const
 {
-  mc_model_checker->visited_states++;
+  mc_model_checker->inc_visited_states();
 }
 
 unsigned long Api::mc_get_visited_states() const
 {
-  return mc_model_checker->visited_states;
+  return mc_model_checker->get_visited_states();
 }
 
 void Api::mc_exit(int status) const
@@ -101,7 +101,7 @@ void Api::mc_exit(int status) const
   mc_model_checker->exit(status);
 }
 
-void Api::restore_state(std::shared_ptr<simgrid::mc::Snapshot> system_state) const
+void Api::restore_state(simgrid::mc::Snapshot* system_state) const
 {
   system_state->restore(&mc_model_checker->get_remote_process());
 }
index 39d658e..19daf85 100644 (file)
@@ -69,7 +69,7 @@ public:
   XBT_ATTRIB_NORETURN void mc_exit(int status) const;
 
   // STATE APIs
-  void restore_state(std::shared_ptr<simgrid::mc::Snapshot> system_state) const;
+  void restore_state(Snapshot* system_state) const;
 
   // SNAPSHOT APIs
   bool snapshot_equal(const Snapshot* s1, const Snapshot* s2) const;
index bc5f7a0..dd243f8 100644 (file)
@@ -20,9 +20,6 @@ class XBT_PRIVATE State : public xbt::Extendable<State> {
   /* Outgoing transition: what was the last transition that we took to leave this state? */
   std::unique_ptr<Transition> transition_;
 
-public:
-  explicit State();
-
   /** Sequential state number (used for debugging) */
   long num_ = 0;
 
@@ -30,7 +27,10 @@ public:
   std::vector<ActorState> actor_states_;
 
   /** Snapshot of system state (if needed) */
-  std::shared_ptr<simgrid::mc::Snapshot> system_state_;
+  std::shared_ptr<Snapshot> system_state_;
+
+public:
+  explicit State();
 
   /* Returns a positive number if there is another transition to pick, or -1 if not */
   int next_transition() const;
@@ -38,11 +38,16 @@ public:
   /* Explore a new path; the parameter must be the result of a previous call to next_transition() */
   void execute_next(int next);
 
+  long get_num() const { return num_; }
   std::size_t count_todo() const;
   void mark_todo(aid_t actor) { this->actor_states_[actor].mark_todo(); }
+  bool is_done(aid_t actor) const { return this->actor_states_[actor].is_done(); }
   Transition* get_transition() const;
   void set_transition(Transition* t) { transition_.reset(t); }
 
+  Snapshot* get_system_state() const { return system_state_.get(); }
+  void set_system_state(std::shared_ptr<Snapshot> state) { system_state_ = std::move(state); }
+
   /* Returns the total amount of states created so far (for statistics) */
   static long get_expanded_states() { return expended_states_; }
 };
index fc5d3c4..6e1bcba 100644 (file)
@@ -90,24 +90,22 @@ simgrid::xbt::Extension<simgrid::mc::Exploration, CommDetExtension> CommDetExten
 /********** State Extension ***********/
 
 class StateCommDet {
-  CommDetExtension* checker_;
-
 public:
   std::vector<std::vector<simgrid::mc::PatternCommunication>> incomplete_comm_pattern_;
   std::vector<unsigned> communication_indices_;
 
   static simgrid::xbt::Extension<simgrid::mc::State, StateCommDet> EXTENSION_ID;
-  explicit StateCommDet(CommDetExtension* checker) : checker_(checker)
+  explicit StateCommDet(CommDetExtension* checker)
   {
     const unsigned long maxpid = Api::get().get_maxpid();
     for (unsigned long i = 0; i < maxpid; i++) {
       std::vector<simgrid::mc::PatternCommunication> res;
-      for (auto const& comm : checker_->incomplete_communications_pattern[i])
+      for (auto const& comm : checker->incomplete_communications_pattern[i])
         res.push_back(comm->dup());
       incomplete_comm_pattern_.push_back(std::move(res));
     }
 
-    for (auto const& list_process_comm : checker_->initial_communications_pattern)
+    for (auto const& list_process_comm : checker->initial_communications_pattern)
       this->communication_indices_.push_back(list_process_comm.index_comm);
   }
 };
index aede648..5e41cfa 100644 (file)
@@ -42,8 +42,8 @@ xbt::signal<void()> DFSExplorer::on_log_state_signal;
 void DFSExplorer::check_non_termination(const State* current_state)
 {
   for (auto state = stack_.rbegin(); state != stack_.rend(); ++state)
-    if (Api::get().snapshot_equal((*state)->system_state_.get(), current_state->system_state_.get())) {
-      XBT_INFO("Non-progressive cycle: state %ld -> state %ld", (*state)->num_, current_state->num_);
+    if (Api::get().snapshot_equal((*state)->get_system_state(), current_state->get_system_state())) {
+      XBT_INFO("Non-progressive cycle: state %ld -> state %ld", (*state)->get_num(), current_state->get_num());
       XBT_INFO("******************************************");
       XBT_INFO("*** NON-PROGRESSIVE CYCLE DETECTED ***");
       XBT_INFO("******************************************");
@@ -68,8 +68,10 @@ RecordTrace DFSExplorer::get_record_trace() // override
 std::vector<std::string> DFSExplorer::get_textual_trace() // override
 {
   std::vector<std::string> trace;
-  for (auto const& state : stack_)
-    trace.push_back(state->get_transition()->to_string());
+  for (auto const& state : stack_) {
+    const auto* t = state->get_transition();
+    trace.push_back(xbt::string_printf("%ld: %s", t->aid_, t->to_string().c_str()));
+  }
   return trace;
 }
 
@@ -94,7 +96,8 @@ void DFSExplorer::run()
     State* state = stack_.back().get();
 
     XBT_DEBUG("**************************************************");
-    XBT_DEBUG("Exploration depth=%zu (state:%ld; %zu interleaves)", stack_.size(), state->num_, state->count_todo());
+    XBT_DEBUG("Exploration depth=%zu (state:%ld; %zu interleaves)", stack_.size(), state->get_num(),
+              state->count_todo());
 
     Api::get().mc_inc_visited_states();
 
@@ -127,8 +130,11 @@ void DFSExplorer::run()
       XBT_DEBUG("There remains %zu actors, but none to interleave (depth %zu).",
                 mc_model_checker->get_remote_process().actors().size(), stack_.size() + 1);
 
-      if (mc_model_checker->get_remote_process().actors().empty())
+      if (mc_model_checker->get_remote_process().actors().empty()) {
         mc_model_checker->finalize_app();
+        XBT_VERB("Execution came to an end at %s (state: %ld, depth: %zu)", get_record_trace().to_string().c_str(),
+                 state->get_num(), stack_.size());
+      }
       this->backtrack();
       continue;
     }
@@ -140,7 +146,7 @@ void DFSExplorer::run()
     // If there are processes to interleave and the maximum depth has not been
     // reached then perform one step of the exploration algorithm.
     XBT_VERB("Execute %ld: %.60s (stack depth: %zu, state: %ld, %zu interleaves)", state->get_transition()->aid_,
-             state->get_transition()->to_string().c_str(), stack_.size(), state->num_, state->count_todo());
+             state->get_transition()->to_string().c_str(), stack_.size(), state->get_num(), state->count_todo());
 
     std::string req_str;
     if (dot_output != nullptr)
@@ -155,7 +161,7 @@ void DFSExplorer::run()
 
     /* Check whether we already explored next_state in the past (but only if interested in state-equality reduction) */
     if (_sg_mc_max_visited_states > 0)
-      visited_state_ = visited_states_.addVisitedState(next_state->num_, next_state.get(), true);
+      visited_state_ = visited_states_.addVisitedState(next_state->get_num(), next_state.get(), true);
 
     /* If this is a new state (or if we don't care about state-equality reduction) */
     if (visited_state_ == nullptr) {
@@ -171,10 +177,11 @@ void DFSExplorer::run()
       }
 
       if (dot_output != nullptr)
-        std::fprintf(dot_output, "\"%ld\" -> \"%ld\" [%s];\n", state->num_, next_state->num_, req_str.c_str());
+        std::fprintf(dot_output, "\"%ld\" -> \"%ld\" [%s];\n", state->get_num(), next_state->get_num(),
+                     req_str.c_str());
 
     } else if (dot_output != nullptr)
-      std::fprintf(dot_output, "\"%ld\" -> \"%ld\" [%s];\n", state->num_,
+      std::fprintf(dot_output, "\"%ld\" -> \"%ld\" [%s];\n", state->get_num(),
                    visited_state_->original_num == -1 ? visited_state_->num : visited_state_->original_num,
                    req_str.c_str());
 
@@ -211,32 +218,32 @@ void DFSExplorer::backtrack()
           break;
         } else if (prev_state->get_transition()->depends(state->get_transition())) {
           XBT_VERB("Dependent Transitions:");
-          XBT_VERB("  %s (state=%ld)", prev_state->get_transition()->to_string().c_str(), prev_state->num_);
-          XBT_VERB("  %s (state=%ld)", state->get_transition()->to_string().c_str(), state->num_);
+          XBT_VERB("  %s (state=%ld)", prev_state->get_transition()->to_string().c_str(), prev_state->get_num());
+          XBT_VERB("  %s (state=%ld)", state->get_transition()->to_string().c_str(), state->get_num());
 
-          if (not prev_state->actor_states_[issuer_id].is_done())
+          if (not prev_state->is_done(issuer_id))
             prev_state->mark_todo(issuer_id);
           else
             XBT_DEBUG("Actor %ld is in done set", issuer_id);
           break;
         } else {
           XBT_VERB("INDEPENDENT Transitions:");
-          XBT_VERB("  %s (state=%ld)", prev_state->get_transition()->to_string().c_str(), prev_state->num_);
-          XBT_VERB("  %s (state=%ld)", state->get_transition()->to_string().c_str(), state->num_);
+          XBT_VERB("  %s (state=%ld)", prev_state->get_transition()->to_string().c_str(), prev_state->get_num());
+          XBT_VERB("  %s (state=%ld)", state->get_transition()->to_string().c_str(), state->get_num());
         }
       }
     }
 
     if (state->count_todo() && stack_.size() < (std::size_t)_sg_mc_max_depth) {
       /* We found a back-tracking point, let's loop */
-      XBT_DEBUG("Back-tracking to state %ld at depth %zu", state->num_, stack_.size() + 1);
+      XBT_DEBUG("Back-tracking to state %ld at depth %zu", state->get_num(), stack_.size() + 1);
       stack_.push_back(
           std::move(state)); // Put it back on the stack from which it was removed earlier in this while loop
       this->restore_state();
-      XBT_DEBUG("Back-tracking to state %ld at depth %zu done", stack_.back()->num_, stack_.size());
+      XBT_DEBUG("Back-tracking to state %ld at depth %zu done", stack_.back()->get_num(), stack_.size());
       break;
     } else {
-      XBT_DEBUG("Delete state %ld at depth %zu", state->num_, stack_.size() + 1);
+      XBT_DEBUG("Delete state %ld at depth %zu", state->get_num(), stack_.size() + 1);
     }
   }
 }
@@ -245,8 +252,8 @@ void DFSExplorer::restore_state()
 {
   /* If asked to rollback on a state that has a snapshot, restore it */
   State* last_state = stack_.back().get();
-  if (last_state->system_state_) {
-    Api::get().restore_state(last_state->system_state_);
+  if (auto* system_state = last_state->get_system_state()) {
+    Api::get().restore_state(system_state);
     on_restore_system_state_signal(last_state);
     return;
   }
index b8de82a..edb3cf5 100644 (file)
@@ -25,8 +25,8 @@ VisitedPair::VisitedPair(int pair_num, xbt_automaton_state_t automaton_state,
     : num(pair_num), automaton_state(automaton_state)
 {
   this->graph_state = std::move(graph_state);
-  if (this->graph_state->system_state_ == nullptr)
-    this->graph_state->system_state_ = std::make_shared<Snapshot>(pair_num);
+  if (not this->graph_state->get_system_state())
+    this->graph_state->set_system_state(std::make_shared<Snapshot>(pair_num));
   this->heap_bytes_used     = Api::get().get_remote_heap_bytes();
   this->actors_count        = Api::get().get_actors().size();
   this->other_num           = -1;
@@ -71,8 +71,8 @@ std::shared_ptr<VisitedPair> LivenessChecker::insert_acceptance_pair(simgrid::mc
       std::shared_ptr<simgrid::mc::VisitedPair> const& pair_test = *i;
       if (xbt_automaton_state_compare(pair_test->automaton_state, new_pair->automaton_state) != 0 ||
           *(pair_test->atomic_propositions) != *(new_pair->atomic_propositions) ||
-          not Api::get().snapshot_equal(pair_test->graph_state->system_state_.get(),
-                                        new_pair->graph_state->system_state_.get()))
+          not Api::get().snapshot_equal(pair_test->graph_state->get_system_state(),
+                                        new_pair->graph_state->get_system_state()))
         continue;
       XBT_INFO("Pair %d already reached (equal to pair %d) !", new_pair->num, pair_test->num);
       exploration_stack_.pop_back();
@@ -102,8 +102,8 @@ void LivenessChecker::replay()
   /* Intermediate backtracking */
   if (_sg_mc_checkpoint > 0) {
     const Pair* pair = exploration_stack_.back().get();
-    if (pair->graph_state->system_state_) {
-      Api::get().restore_state(pair->graph_state->system_state_);
+    if (auto* system_state = pair->graph_state->get_system_state()) {
+      Api::get().restore_state(system_state);
       return;
     }
   }
@@ -148,8 +148,8 @@ int LivenessChecker::insert_visited_pair(std::shared_ptr<VisitedPair> visited_pa
     const VisitedPair* pair_test = i->get();
     if (xbt_automaton_state_compare(pair_test->automaton_state, visited_pair->automaton_state) != 0 ||
         *(pair_test->atomic_propositions) != *(visited_pair->atomic_propositions) ||
-        not Api::get().snapshot_equal(pair_test->graph_state->system_state_.get(),
-                                      visited_pair->graph_state->system_state_.get()))
+        not Api::get().snapshot_equal(pair_test->graph_state->get_system_state(),
+                                      visited_pair->graph_state->get_system_state()))
       continue;
     if (pair_test->other_num == -1)
       visited_pair->other_num = pair_test->num;
index e733950..24631fe 100644 (file)
@@ -96,12 +96,12 @@ double MC_process_clock_get(const simgrid::kernel::actor::ActorImpl* process)
 {
   if (simgrid::mc::processes_time.empty())
     return 0;
-  if (process != nullptr)
-    return simgrid::mc::processes_time[process->get_pid()];
-  return -1;
+  if (process == nullptr)
+    return -1;
+  return simgrid::mc::processes_time.at(process->get_pid());
 }
 
 void MC_process_clock_add(const simgrid::kernel::actor::ActorImpl* process, double amount)
 {
-  simgrid::mc::processes_time[process->get_pid()] += amount;
+  simgrid::mc::processes_time.at(process->get_pid()) += amount;
 }
index 895f158..8330582 100644 (file)
@@ -43,7 +43,7 @@ void RecordTrace::replay() const
 
 void simgrid::mc::RecordTrace::replay(const std::string& path_string)
 {
-  simgrid::mc::processes_time.resize(simgrid::kernel::actor::get_maxpid());
+  simgrid::mc::processes_time.resize(kernel::actor::ActorImpl::get_maxpid());
   simgrid::mc::RecordTrace trace(path_string.c_str());
   trace.replay();
   for (auto* item : trace.transitions_)
index 5aad994..e222ab7 100644 (file)
@@ -75,7 +75,7 @@ AppSide* AppSide::initialize(xbt_dynar_t actors_addr)
              strerror(errno));
 
   s_mc_message_initial_addresses_t message{MessageType::INITIAL_ADDRESSES, mmalloc_preinit(),
-                                           kernel::actor::get_maxpid_addr(), actors_addr};
+                                           kernel::actor::ActorImpl::get_maxpid_addr(), actors_addr};
   xbt_assert(instance_->channel_.send(message) == 0, "Could not send the initial message with addresses.");
 
   instance_->handle_messages();
@@ -200,7 +200,7 @@ void AppSide::handle_messages() const
 
 void AppSide::main_loop() const
 {
-  simgrid::mc::processes_time.resize(simgrid::kernel::actor::get_maxpid());
+  simgrid::mc::processes_time.resize(simgrid::kernel::actor::ActorImpl::get_maxpid());
   MC_ignore_heap(simgrid::mc::processes_time.data(),
                  simgrid::mc::processes_time.size() * sizeof(simgrid::mc::processes_time[0]));
 
index 1335153..74c84e0 100644 (file)
@@ -32,10 +32,10 @@ TestAnyTransition::TestAnyTransition(aid_t issuer, int times_considered, std::st
 }
 std::string TestAnyTransition::to_string(bool verbose) const
 {
-  auto res = xbt::string_printf("%ld: TestAny{ ", aid_);
+  auto res = xbt::string_printf("TestAny{ ");
   for (auto const* t : transitions_)
     res += t->to_string(verbose);
-  res += "}";
+  res += " }";
   return res;
 }
 bool TestAnyTransition::depends(const Transition* other) const
@@ -54,10 +54,10 @@ WaitAnyTransition::WaitAnyTransition(aid_t issuer, int times_considered, std::st
 }
 std::string WaitAnyTransition::to_string(bool verbose) const
 {
-  auto res = xbt::string_printf("%ld: WaitAny{ ", aid_);
+  auto res = xbt::string_printf("WaitAny{ ");
   for (auto const* t : transitions_)
     res += t->to_string(verbose);
-  res += "}";
+  res += " }";
   return res;
 }
 bool WaitAnyTransition::depends(const Transition* other) const
index 8aaf811..1ddabd1 100644 (file)
@@ -30,7 +30,7 @@ CommWaitTransition::CommWaitTransition(aid_t issuer, int times_considered, std::
 }
 std::string CommWaitTransition::to_string(bool verbose) const
 {
-  auto res = xbt::string_printf("%ld: WaitComm(from %ld to %ld, mbox=%u, %s", aid_, sender_, receiver_, mbox_,
+  auto res = xbt::string_printf("WaitComm(from %ld to %ld, mbox=%u, %s", sender_, receiver_, mbox_,
                                 (timeout_ ? "timeout" : "no timeout"));
   if (verbose) {
     res += ", sbuff=" + xbt::string_printf("%" PRIxPTR, sbuff_) + ", size=" + std::to_string(size_);
@@ -56,9 +56,11 @@ bool CommWaitTransition::depends(const Transition* other) const
     if (sbuff_ != 0 && rbuff_ != 0 && wait->sbuff_ != 0 && wait->rbuff_ != 0 && rbuff_ != wait->sbuff_ &&
         rbuff_ != wait->rbuff_ && rbuff_ != sbuff_)
       return false;
+
+    return true;
   }
 
-  return true;
+  return false; // Comm transitions are INDEP with non-comm transitions
 }
 CommTestTransition::CommTestTransition(aid_t issuer, int times_considered, std::stringstream& stream)
     : Transition(Type::COMM_TEST, issuer, times_considered)
@@ -70,7 +72,7 @@ CommTestTransition::CommTestTransition(aid_t issuer, int times_considered, std::
 }
 std::string CommTestTransition::to_string(bool verbose) const
 {
-  auto res = xbt::string_printf("%ld: TestComm(from %ld to %ld, mbox=%u", aid_, sender_, receiver_, mbox_);
+  auto res = xbt::string_printf("TestComm(from %ld to %ld, mbox=%u", sender_, receiver_, mbox_);
   if (verbose) {
     res += ", sbuff=" + xbt::string_printf("%" PRIxPTR, sbuff_) + ", size=" + std::to_string(size_);
     res += ", rbuff=" + xbt::string_printf("%" PRIxPTR, rbuff_);
@@ -97,7 +99,7 @@ bool CommTestTransition::depends(const Transition* other) const
     return false;
   }
 
-  return true;
+  return false; // Comm transitions are INDEP with non-comm transitions
 }
 
 CommRecvTransition::CommRecvTransition(aid_t issuer, int times_considered, std::stringstream& stream)
@@ -107,7 +109,7 @@ CommRecvTransition::CommRecvTransition(aid_t issuer, int times_considered, std::
 }
 std::string CommRecvTransition::to_string(bool verbose) const
 {
-  auto res = xbt::string_printf("%ld: iRecv(mbox=%u", aid_, mbox_);
+  auto res = xbt::string_printf("iRecv(mbox=%u", mbox_);
   if (verbose)
     res += ", rbuff=" + xbt::string_printf("%" PRIxPTR, rbuff_);
   res += ")";
@@ -133,6 +135,8 @@ bool CommRecvTransition::depends(const Transition* other) const
 
     if ((aid_ != test->sender_) && (aid_ != test->receiver_) && (test->rbuff_ != rbuff_))
       return false;
+
+    return true; // DEP with other send transitions
   }
 
   if (auto* wait = dynamic_cast<const CommWaitTransition*>(other)) {
@@ -144,9 +148,11 @@ bool CommRecvTransition::depends(const Transition* other) const
 
     if ((aid_ != wait->sender_) && (aid_ != wait->receiver_) && (wait->rbuff_ != rbuff_))
       return false;
+
+    return true; // DEP with other wait transitions
   }
 
-  return true;
+  return false; // Comm transitions are INDEP with non-comm transitions
 }
 
 CommSendTransition::CommSendTransition(aid_t issuer, int times_considered, std::stringstream& stream)
@@ -157,7 +163,7 @@ CommSendTransition::CommSendTransition(aid_t issuer, int times_considered, std::
 }
 std::string CommSendTransition::to_string(bool verbose = false) const
 {
-  auto res = xbt::string_printf("%ld: iSend(mbox=%u", aid_, mbox_);
+  auto res = xbt::string_printf("iSend(mbox=%u", mbox_);
   if (verbose)
     res += ", sbuff=" + xbt::string_printf("%" PRIxPTR, sbuff_) + ", size=" + std::to_string(size_);
   res += ")";
@@ -184,6 +190,8 @@ bool CommSendTransition::depends(const Transition* other) const
 
     if ((aid_ != test->sender_) && (aid_ != test->receiver_) && (test->sbuff_ != sbuff_))
       return false;
+
+    return true; // DEP with other test transitions
   }
 
   if (const auto* wait = dynamic_cast<const CommWaitTransition*>(other)) {
@@ -195,9 +203,11 @@ bool CommSendTransition::depends(const Transition* other) const
 
     if ((aid_ != wait->sender_) && (aid_ != wait->receiver_) && (wait->sbuff_ != sbuff_))
       return false;
+
+    return true; // DEP with other wait transitions
   }
 
-  return true;
+  return false; // Comm transitions are INDEP with non-comm transitions
 }
 
 } // namespace mc
index dcc650d..6032b0d 100644 (file)
@@ -25,7 +25,9 @@ template class xbt::Extendable<s4u::Activity>;
 namespace s4u {
 
 xbt::signal<void(Activity&)> Activity::on_veto;
-xbt::signal<void(Activity&)> Activity::on_completion;
+xbt::signal<void(Activity const&)> Activity::on_completion;
+xbt::signal<void(Activity const&)> Activity::on_suspended;
+xbt::signal<void(Activity const&)> Activity::on_resumed;
 
 std::set<Activity*>* Activity::vetoed_activities_ = nullptr;
 
index 194af96..372470b 100644 (file)
@@ -108,6 +108,9 @@ void Actor::join() const
 
 void Actor::join(double timeout) const
 {
+  xbt_assert(not(MC_is_active() || MC_record_replay_is_active()),
+             "Actor::join() is not usable in MC yet. Please report this bug.");
+
   kernel::actor::ActorImpl* issuer = kernel::actor::ActorImpl::self();
   const kernel::actor::ActorImpl* target = pimpl_;
   kernel::actor::simcall_blocking([issuer, target, timeout] {
index 8aa46d2..f22b711 100644 (file)
@@ -42,7 +42,7 @@ int Barrier::wait()
         kernel::actor::simcall_answered([issuer, this] { return pimpl_->acquire_async(issuer); }, &lock_observer);
 
     kernel::actor::BarrierObserver wait_observer{issuer, mc::Transition::Type::BARRIER_WAIT, acquisition.get()};
-    return kernel::actor::simcall_blocking([issuer, acquisition] { return acquisition->wait_for(issuer, -1); },
+    return kernel::actor::simcall_blocking([issuer, acquisition] { acquisition->wait_for(issuer, -1); },
                                            &wait_observer);
 
   } else { // Do it in one simcall only
@@ -53,6 +53,11 @@ int Barrier::wait()
   }
 }
 
+std::string Barrier::to_string() const
+{
+  return pimpl_->to_string();
+}
+
 void intrusive_ptr_add_ref(Barrier* barrier)
 {
   intrusive_ptr_add_ref(barrier->pimpl_);
index eec97a7..1020047 100644 (file)
@@ -22,7 +22,6 @@ namespace simgrid {
 namespace s4u {
 xbt::signal<void(Comm const&)> Comm::on_send;
 xbt::signal<void(Comm const&)> Comm::on_recv;
-xbt::signal<void(Comm const&)> Comm::on_completion;
 
 CommPtr Comm::set_copy_data_callback(const std::function<void(kernel::activity::CommImpl*, void*, size_t)>& callback)
 {
index ea62433..9f4dd40 100644 (file)
@@ -462,11 +462,6 @@ Engine* Engine::set_default_comm_data_copy_callback(
 } // namespace s4u
 } // namespace simgrid
 
-double SIMIX_get_clock() // XBT_ATTRIB_DEPRECATED_v332
-{
-  return simgrid::s4u::Engine::get_clock();
-}
-
 /* **************************** Public C interface *************************** */
 void simgrid_init(int* argc, char** argv)
 {
index f6eba91..6542263 100644 (file)
@@ -25,8 +25,7 @@ void Mutex::lock()
         kernel::actor::simcall_answered([issuer, this] { return pimpl_->lock_async(issuer); }, &lock_observer);
 
     kernel::actor::MutexObserver wait_observer{issuer, mc::Transition::Type::MUTEX_WAIT, pimpl_};
-    kernel::actor::simcall_blocking([issuer, acquisition] { return acquisition->wait_for(issuer, -1); },
-                                    &wait_observer);
+    kernel::actor::simcall_blocking([issuer, &acquisition] { acquisition->wait_for(issuer, -1); }, &wait_observer);
 
   } else { // Do it in one simcall only
     kernel::actor::simcall_blocking([issuer, this] { pimpl_->lock_async(issuer)->wait_for(issuer, -1); });
index 06950ef..699116c 100644 (file)
 namespace simgrid {
 namespace s4u {
 
-xbt::signal<void(bool symmetrical, kernel::routing::NetPoint* src, kernel::routing::NetPoint* dst,
-                 kernel::routing::NetPoint* gw_src, kernel::routing::NetPoint* gw_dst,
-                 std::vector<kernel::resource::StandardLinkImpl*> const& link_list)>
-    NetZone::on_route_creation;
 xbt::signal<void(NetZone const&)> NetZone::on_creation;
 xbt::signal<void(NetZone const&)> NetZone::on_seal;
 
@@ -50,12 +46,6 @@ std::vector<NetZone*> NetZone::get_children() const
   return res;
 }
 
-NetZone* NetZone::add_child(NetZone* new_zone) // XBT_ATTRIB_DEPRECATED_v332
-{
-  new_zone->set_parent(this);
-  return this;
-}
-
 const std::string& NetZone::get_name() const
 {
   return pimpl_->get_name();
@@ -97,17 +87,6 @@ unsigned long NetZone::add_component(kernel::routing::NetPoint* elm)
   return pimpl_->add_component(elm);
 }
 
-// XBT_ATTRIB_DEPRECATED_v332
-std::vector<LinkInRoute>
-NetZone::convert_to_linkInRoute(const std::vector<kernel::resource::StandardLinkImpl*>& link_list)
-{
-  std::vector<LinkInRoute> links;
-  for (const auto* link : link_list) {
-    links.emplace_back(LinkInRoute(link->get_iface()));
-  }
-  return links;
-}
-
 void NetZone::add_route(kernel::routing::NetPoint* src, kernel::routing::NetPoint* dst,
                         kernel::routing::NetPoint* gw_src, kernel::routing::NetPoint* gw_dst,
                         const std::vector<LinkInRoute>& link_list, bool symmetrical)
@@ -115,22 +94,6 @@ void NetZone::add_route(kernel::routing::NetPoint* src, kernel::routing::NetPoin
   pimpl_->add_route(src, dst, gw_src, gw_dst, link_list, symmetrical);
 }
 
-// XBT_ATTRIB_DEPRECATED_v332
-void NetZone::add_route(kernel::routing::NetPoint* src, kernel::routing::NetPoint* dst,
-                        kernel::routing::NetPoint* gw_src, kernel::routing::NetPoint* gw_dst,
-                        const std::vector<kernel::resource::StandardLinkImpl*>& link_list, bool symmetrical)
-{
-  pimpl_->add_route(src, dst, gw_src, gw_dst, convert_to_linkInRoute(link_list), symmetrical);
-}
-
-// XBT_ATTRIB_DEPRECATED_v332
-void NetZone::add_bypass_route(kernel::routing::NetPoint* src, kernel::routing::NetPoint* dst,
-                               kernel::routing::NetPoint* gw_src, kernel::routing::NetPoint* gw_dst,
-                               const std::vector<kernel::resource::StandardLinkImpl*>& link_list, bool /*symmetrical*/)
-{
-  pimpl_->add_bypass_route(src, dst, gw_src, gw_dst, convert_to_linkInRoute(link_list));
-}
-
 void NetZone::add_bypass_route(kernel::routing::NetPoint* src, kernel::routing::NetPoint* dst,
                                kernel::routing::NetPoint* gw_src, kernel::routing::NetPoint* gw_dst,
                                const std::vector<LinkInRoute>& link_list)
index 2aabc79..2b9bbdc 100644 (file)
@@ -36,13 +36,13 @@ bool Semaphore::acquire_timeout(double timeout)
 
     kernel::actor::SemaphoreAcquisitionObserver wait_observer{issuer, mc::Transition::Type::SEM_WAIT, acquisition.get(),
                                                               timeout};
-    return kernel::actor::simcall_blocking(
-        [issuer, acquisition, timeout] { return acquisition->wait_for(issuer, timeout); }, &wait_observer);
+    return kernel::actor::simcall_blocking([issuer, acquisition, timeout] { acquisition->wait_for(issuer, timeout); },
+                                           &wait_observer);
 
   } else { // Do it in one simcall only and without observer
     kernel::actor::SemaphoreAcquisitionObserver observer{issuer, mc::Transition::Type::SEM_WAIT, nullptr, timeout};
     return kernel::actor::simcall_blocking(
-        [this, issuer, timeout] { return pimpl_->acquire_async(issuer)->wait_for(issuer, timeout); }, &observer);
+        [this, issuer, timeout] { pimpl_->acquire_async(issuer)->wait_for(issuer, timeout); }, &observer);
   }
 }
 
index 8764f14..6f205a2 100644 (file)
@@ -57,6 +57,7 @@ int PMPI_Init(int*, char***)
   smpi_process()->mark_as_initialized();
 
   smpi_mpi_init();
+  CHECK_COLLECTIVE(smpi_process()->comm_world(), "MPI_Init")
 
   return MPI_SUCCESS;
 }
@@ -64,7 +65,9 @@ int PMPI_Init(int*, char***)
 int PMPI_Finalize()
 {
   smpi_bench_end();
+  CHECK_COLLECTIVE(smpi_process()->comm_world(), "MPI_Finalize")
   aid_t rank_traced = simgrid::s4u::this_actor::get_pid();
+  smpi_process()->mark_as_finalizing();
   TRACE_smpi_comm_in(rank_traced, __func__, new simgrid::instr::NoOpTIData("finalize"));
 
   if(simgrid::config::get_value<bool>("smpi/finalization-barrier"))
index 3fd9db7..5915270 100644 (file)
@@ -37,7 +37,7 @@ int PMPI_Ibarrier(MPI_Comm comm, MPI_Request *request)
 {
   CHECK_COMM(1)
   CHECK_REQUEST(2)
-
+  CHECK_COLLECTIVE(comm, request == MPI_REQUEST_IGNORED ? "PMPI_Barrier" : "PMPI_Ibarrier")
   const SmpiBenchGuard suspend_bench;
   aid_t pid = simgrid::s4u::this_actor::get_pid();
   TRACE_smpi_comm_in(pid, request == MPI_REQUEST_IGNORED ? "PMPI_Barrier" : "PMPI_Ibarrier",
@@ -67,6 +67,8 @@ int PMPI_Ibcast(void* buf, int count, MPI_Datatype datatype, int root, MPI_Comm
   CHECK_BUFFER(1, buf, count, datatype)
   CHECK_ROOT(4)
   CHECK_REQUEST(6)
+  CHECK_COLLECTIVE(comm, std::string(request == MPI_REQUEST_IGNORED ? "PMPI_Bcast" : "PMPI_Ibcast") + " with root " +
+                             std::to_string(root))
 
   const SmpiBenchGuard suspend_bench;
   aid_t pid = simgrid::s4u::this_actor::get_pid();
@@ -115,6 +117,8 @@ int PMPI_Igather(const void* sendbuf, int sendcount, MPI_Datatype sendtype, void
   }
   CHECK_ROOT(7)
   CHECK_REQUEST(9)
+  CHECK_COLLECTIVE(comm, std::string(request == MPI_REQUEST_IGNORED ? "PMPI_Gather" : "PMPI_Igather") + +" with root " +
+                             std::to_string(root))
 
   const void* real_sendbuf   = sendbuf;
   int real_sendcount         = sendcount;
@@ -175,6 +179,8 @@ int PMPI_Igatherv(const void* sendbuf, int sendcount, MPI_Datatype sendtype, voi
   }
   CHECK_ROOT(8)
   CHECK_REQUEST(10)
+  CHECK_COLLECTIVE(comm, std::string(request == MPI_REQUEST_IGNORED ? "PMPI_Gatherv" : "PMPI_Igatherv") +
+                             " with root " + std::to_string(root))
 
   if (rank == root){
     for (int i = 0; i < comm->size(); i++) {
@@ -239,6 +245,7 @@ int PMPI_Iallgather(const void* sendbuf, int sendcount, MPI_Datatype sendtype, v
   CHECK_BUFFER(1, sendbuf, sendcount, sendtype)
   CHECK_BUFFER(4, recvbuf, recvcount, recvtype)
   CHECK_REQUEST(8)
+  CHECK_COLLECTIVE(comm, request == MPI_REQUEST_IGNORED ? "PMPI_Allgather" : "PMPI_Iallggather")
 
   if (sendbuf == MPI_IN_PLACE) {
     sendbuf   = static_cast<char*>(recvbuf) + recvtype->get_extent() * recvcount * comm->rank();
@@ -296,6 +303,7 @@ int PMPI_Iallgatherv(const void* sendbuf, int sendcount, MPI_Datatype sendtype,
     CHECK_COUNT(5, recvcounts[i])
     CHECK_BUFFER(4, recvbuf, recvcounts[i], recvtype)
   }
+  CHECK_COLLECTIVE(comm, MPI_REQUEST_IGNORED ? "PMPI_Allgatherv" : "PMPI_Iallgatherv")
 
   const SmpiBenchGuard suspend_bench;
   if (sendbuf == MPI_IN_PLACE) {
@@ -351,6 +359,8 @@ int PMPI_Iscatter(const void* sendbuf, int sendcount, MPI_Datatype sendtype, voi
   }
   CHECK_ROOT(8)
   CHECK_REQUEST(9)
+  CHECK_COLLECTIVE(comm, std::string(request == MPI_REQUEST_IGNORED ? "PMPI_Scatter" : "PMPI_Iscatter") +
+                             " with root " + std::to_string(root))
 
   if (recvbuf == MPI_IN_PLACE) {
     recvtype  = sendtype;
@@ -415,6 +425,8 @@ int PMPI_Iscatterv(const void* sendbuf, const int* sendcounts, const int* displs
   } else {
     CHECK_NOT_IN_PLACE_ROOT(4, recvbuf)
   }
+  CHECK_COLLECTIVE(comm, std::string(request == MPI_REQUEST_IGNORED ? "PMPI_Scatterv" : "PMPI_Iscatterv") +
+                             " with root " + std::to_string(root))
 
   const SmpiBenchGuard suspend_bench;
 
@@ -464,6 +476,8 @@ int PMPI_Ireduce(const void *sendbuf, void *recvbuf, int count, MPI_Datatype dat
   CHECK_OP(5, op, datatype)
   CHECK_ROOT(7)
   CHECK_REQUEST(8)
+  CHECK_COLLECTIVE(comm, std::string(request == MPI_REQUEST_IGNORED ? "PMPI_Reduce" : "PMPI_Ireduce") + " with op " +
+                             op->name() + " and root " + std::to_string(root))
 
   const SmpiBenchGuard suspend_bench;
   aid_t pid = simgrid::s4u::this_actor::get_pid();
@@ -514,6 +528,8 @@ int PMPI_Iallreduce(const void *sendbuf, void *recvbuf, int count, MPI_Datatype
   CHECK_BUFFER(1, sendbuf, count, datatype)
   CHECK_BUFFER(2, recvbuf, count, datatype)
   CHECK_REQUEST(7)
+  CHECK_COLLECTIVE(comm, std::string(request == MPI_REQUEST_IGNORED ? "PMPI_Alleduce" : "PMPI_Iallreduce") +
+                             " with op " + op->name())
 
   const SmpiBenchGuard suspend_bench;
   std::vector<unsigned char> tmp_sendbuf;
@@ -551,6 +567,8 @@ int PMPI_Iscan(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datat
   CHECK_BUFFER(2,recvbuf,count, datatype)
   CHECK_REQUEST(7)
   CHECK_OP(5, op, datatype)
+  CHECK_COLLECTIVE(comm,
+                   std::string(request == MPI_REQUEST_IGNORED ? "PMPI_Scan" : "PMPI_Iscan") + " with op " + op->name())
 
   const SmpiBenchGuard suspend_bench;
   aid_t pid = simgrid::s4u::this_actor::get_pid();
@@ -586,6 +604,8 @@ int PMPI_Iexscan(const void *sendbuf, void *recvbuf, int count, MPI_Datatype dat
   CHECK_BUFFER(2, recvbuf, count, datatype)
   CHECK_REQUEST(7)
   CHECK_OP(5, op, datatype)
+  CHECK_COLLECTIVE(comm, std::string(request == MPI_REQUEST_IGNORED ? "PMPI_Exscan" : "PMPI_Iexscan") + " with op " +
+                             op->name())
 
   const SmpiBenchGuard suspend_bench;
   aid_t pid = simgrid::s4u::this_actor::get_pid();
@@ -627,6 +647,8 @@ int PMPI_Ireduce_scatter(const void *sendbuf, void *recvbuf, const int *recvcoun
     CHECK_BUFFER(1, sendbuf, recvcounts[i], datatype)
     CHECK_BUFFER(2, recvbuf, recvcounts[i], datatype)
   }
+  CHECK_COLLECTIVE(comm, std::string(request == MPI_REQUEST_IGNORED ? "PMPI_Reduce_scatter" : "PMPI_Ireduce_scatter") +
+                             " with op " + op->name())
 
   const SmpiBenchGuard suspend_bench;
   aid_t pid                          = simgrid::s4u::this_actor::get_pid();
@@ -673,6 +695,9 @@ int PMPI_Ireduce_scatter_block(const void* sendbuf, void* recvbuf, int recvcount
   CHECK_BUFFER(2, recvbuf, recvcount, datatype)
   CHECK_REQUEST(7)
   CHECK_OP(5, op, datatype)
+  CHECK_COLLECTIVE(
+      comm, std::string(request == MPI_REQUEST_IGNORED ? "PMPI_Reduce_scatter_block" : "PMPI_Ireduce_scatter_block") +
+                " with op " + op->name())
 
   const SmpiBenchGuard suspend_bench;
   int count = comm->size();
@@ -721,6 +746,7 @@ int PMPI_Ialltoall(const void* sendbuf, int sendcount, MPI_Datatype sendtype, vo
   CHECK_COUNT(5, recvcount)
   CHECK_BUFFER(4, recvbuf, recvcount, recvtype)
   CHECK_REQUEST(8)
+  CHECK_COLLECTIVE(comm, request == MPI_REQUEST_IGNORED ? "PMPI_Alltoall" : "PMPI_Ialltoall")
 
   aid_t pid                  = simgrid::s4u::this_actor::get_pid();
   int real_sendcount         = sendcount;
@@ -779,6 +805,7 @@ int PMPI_Ialltoallv(const void* sendbuf, const int* sendcounts, const int* sendd
   CHECK_NULL(6, MPI_ERR_COUNT, recvcounts)
   CHECK_NULL(7, MPI_ERR_ARG, recvdispls)
   CHECK_REQUEST(10)
+  CHECK_COLLECTIVE(comm, request == MPI_REQUEST_IGNORED ? "PMPI_Alltoallv" : "PMPI_Ialltoallv")
 
   aid_t pid = simgrid::s4u::this_actor::get_pid();
   int size = comm->size();
@@ -883,6 +910,7 @@ int PMPI_Ialltoallw(const void* sendbuf, const int* sendcounts, const int* sendd
     CHECK_TYPE(8, recvtypes[i])
     CHECK_BUFFER(5, recvbuf, recvcounts[i], recvtypes[i])
   }
+  CHECK_COLLECTIVE(comm, request == MPI_REQUEST_IGNORED ? "PMPI_Alltoallw" : "PMPI_Ialltoallw")
 
   const SmpiBenchGuard suspend_bench;
 
index ac85cf3..4416bfe 100644 (file)
@@ -128,6 +128,7 @@ int PMPI_Comm_split(MPI_Comm comm, int color, int key, MPI_Comm* comm_out)
 {
   CHECK_NULL(4, MPI_ERR_ARG, comm_out)
   CHECK_COMM2(1, comm)
+  CHECK_COLLECTIVE(comm, __func__)
   if( color != MPI_UNDEFINED)//we use a negative value for MPI_UNDEFINED
     CHECK_NEGATIVE(3, MPI_ERR_ARG, color)
   const SmpiBenchGuard suspend_bench;
@@ -139,6 +140,7 @@ int PMPI_Comm_split_type(MPI_Comm comm, int split_type, int key, MPI_Info info,
 {
   CHECK_COMM(1)
   CHECK_NULL(5, MPI_ERR_ARG, newcomm)
+  CHECK_COLLECTIVE(comm, __func__)
   const SmpiBenchGuard suspend_bench;
   *newcomm = comm->split_type(split_type, key, info);
   return MPI_SUCCESS;
index 70df57f..e87680f 100644 (file)
@@ -38,6 +38,7 @@ extern MPI_Errhandler SMPI_default_File_Errhandler;
 
 int PMPI_File_open(MPI_Comm comm, const char *filename, int amode, MPI_Info info, MPI_File *fh){
   CHECK_COMM(1)
+  CHECK_COLLECTIVE(comm, "MPI_File_open")
   CHECK_NULL(2, MPI_ERR_FILE, filename)
   if (amode < 0)
     return MPI_ERR_AMODE;
@@ -54,6 +55,7 @@ int PMPI_File_open(MPI_Comm comm, const char *filename, int amode, MPI_Info info
 
 int PMPI_File_close(MPI_File *fh){
   CHECK_NULL(2, MPI_ERR_ARG, fh)
+  CHECK_COLLECTIVE((*fh)->comm(), __func__)
   const SmpiBenchGuard suspend_bench;
   int ret = simgrid::smpi::File::close(fh);
   *fh = MPI_FILE_NULL;
@@ -69,6 +71,7 @@ int PMPI_File_seek(MPI_File fh, MPI_Offset offset, int whence){
 
 int PMPI_File_seek_shared(MPI_File fh, MPI_Offset offset, int whence){
   CHECK_FILE(1, fh)
+  CHECK_COLLECTIVE(fh->comm(), __func__)
   const SmpiBenchGuard suspend_bench;
   int ret = fh->seek_shared(offset,whence);
   return ret;
@@ -143,6 +146,7 @@ int PMPI_File_write_shared(MPI_File fh, const void *buf, int count,MPI_Datatype
 int PMPI_File_read_all(MPI_File fh, void *buf, int count,MPI_Datatype datatype, MPI_Status *status){
   CHECK_FILE_INPUTS
   CHECK_WRONLY(fh)
+  CHECK_COLLECTIVE(fh->comm(), __func__)
   const SmpiBenchGuard suspend_bench;
   aid_t rank_traced = simgrid::s4u::this_actor::get_pid();
   TRACE_smpi_comm_in(rank_traced, __func__, new simgrid::instr::CpuTIData("IO - read_all", count * datatype->size()));
@@ -154,6 +158,7 @@ int PMPI_File_read_all(MPI_File fh, void *buf, int count,MPI_Datatype datatype,
 int PMPI_File_read_ordered(MPI_File fh, void *buf, int count,MPI_Datatype datatype, MPI_Status *status){
   CHECK_FILE_INPUTS
   CHECK_WRONLY(fh)
+  CHECK_COLLECTIVE(fh->comm(), __func__)
   const SmpiBenchGuard suspend_bench;
   aid_t rank_traced = simgrid::s4u::this_actor::get_pid();
   TRACE_smpi_comm_in(rank_traced, __func__,
@@ -166,6 +171,7 @@ int PMPI_File_read_ordered(MPI_File fh, void *buf, int count,MPI_Datatype dataty
 int PMPI_File_write_all(MPI_File fh, const void *buf, int count,MPI_Datatype datatype, MPI_Status *status){
   CHECK_FILE_INPUTS
   CHECK_RDONLY(fh)
+  CHECK_COLLECTIVE(fh->comm(), __func__)
   const SmpiBenchGuard suspend_bench;
   aid_t rank_traced = simgrid::s4u::this_actor::get_pid();
   TRACE_smpi_comm_in(rank_traced, __func__, new simgrid::instr::CpuTIData("IO - write_all", count * datatype->size()));
@@ -177,6 +183,7 @@ int PMPI_File_write_all(MPI_File fh, const void *buf, int count,MPI_Datatype dat
 int PMPI_File_write_ordered(MPI_File fh, const void *buf, int count,MPI_Datatype datatype, MPI_Status *status){
   CHECK_FILE_INPUTS
   CHECK_RDONLY(fh)
+  CHECK_COLLECTIVE(fh->comm(), __func__)
   const SmpiBenchGuard suspend_bench;
   aid_t rank_traced = simgrid::s4u::this_actor::get_pid();
   TRACE_smpi_comm_in(rank_traced, __func__,
@@ -203,6 +210,7 @@ int PMPI_File_read_at(MPI_File fh, MPI_Offset offset, void *buf, int count,MPI_D
 int PMPI_File_read_at_all(MPI_File fh, MPI_Offset offset, void *buf, int count,MPI_Datatype datatype, MPI_Status *status){
   CHECK_FILE_INPUT_OFFSET
   CHECK_WRONLY(fh)
+  CHECK_COLLECTIVE(fh->comm(), __func__)
   const SmpiBenchGuard suspend_bench;
   aid_t rank_traced = simgrid::s4u::this_actor::get_pid();
   TRACE_smpi_comm_in(rank_traced, __func__,
@@ -231,6 +239,7 @@ int PMPI_File_write_at(MPI_File fh, MPI_Offset offset, const void *buf, int coun
 int PMPI_File_write_at_all(MPI_File fh, MPI_Offset offset, const void *buf, int count,MPI_Datatype datatype, MPI_Status *status){
   CHECK_FILE_INPUT_OFFSET
   CHECK_RDONLY(fh)
+  CHECK_COLLECTIVE(fh->comm(), __func__)
   const SmpiBenchGuard suspend_bench;
   aid_t rank_traced = simgrid::s4u::this_actor::get_pid();
   TRACE_smpi_comm_in(rank_traced, __func__,
@@ -252,6 +261,7 @@ int PMPI_File_delete(const char *filename, MPI_Info info){
 
 int PMPI_File_set_view(MPI_File fh, MPI_Offset disp, MPI_Datatype etype, MPI_Datatype filetype, const char *datarep, MPI_Info info){
   CHECK_FILE(1, fh)
+  CHECK_COLLECTIVE(fh->comm(), __func__)
   if(not ((fh->flags() & MPI_MODE_SEQUENTIAL) && (disp == MPI_DISPLACEMENT_CURRENT)))
     CHECK_OFFSET(2, disp)
   CHECK_TYPE(3, etype)
@@ -295,6 +305,7 @@ int PMPI_File_get_size(MPI_File  fh, MPI_Offset* size)
 int PMPI_File_set_size(MPI_File  fh, MPI_Offset size)
 {
   CHECK_FILE(1, fh)
+  CHECK_COLLECTIVE(fh->comm(), __func__)
   fh->set_size(size);
   return MPI_SUCCESS;
 }
index 3603577..9198240 100644 (file)
@@ -24,6 +24,7 @@ int PMPI_Cart_create(MPI_Comm comm, int ndims, const int* dims, const int* perio
   CHECK_NEGATIVE(2, MPI_ERR_ARG, ndims)
   for (int i = 0; i < ndims; i++)
     CHECK_NEGATIVE(2, MPI_ERR_ARG, dims[i])
+  CHECK_COLLECTIVE(comm, __func__)
   const auto* topo = new simgrid::smpi::Topo_Cart(comm, ndims, dims, periodic, reorder, comm_cart);
   if (*comm_cart == MPI_COMM_NULL) {
     delete topo;
@@ -109,6 +110,7 @@ int PMPI_Cart_sub(MPI_Comm comm, const int* remain_dims, MPI_Comm* comm_new) {
   CHECK_COMM(1)
   CHECK_NULL(1, MPI_ERR_TOPOLOGY, comm->topo())
   CHECK_NULL(3, MPI_ERR_ARG, comm_new)
+  CHECK_COLLECTIVE(comm, __func__)
   auto* topo = static_cast<MPIR_Cart_Topology>(comm->topo().get());
   if (topo==nullptr) {
     return MPI_ERR_ARG;
index c65498e..cd03d88 100644 (file)
@@ -30,8 +30,10 @@ XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(smpi_pmpi);
 int PMPI_Win_create( void *base, MPI_Aint size, int disp_unit, MPI_Info info, MPI_Comm comm, MPI_Win *win){
   int retval = 0;
   CHECK_COMM(5)
+  CHECK_BUFFER(1, base, size, MPI_BYTE)
   CHECK_NEGATIVE(2, MPI_ERR_OTHER, size)
   CHECK_NEGATIVE(3, MPI_ERR_OTHER, disp_unit)
+  CHECK_COLLECTIVE(comm, __func__)
   const SmpiBenchGuard suspend_bench;
   if (base == nullptr && size != 0){
     retval= MPI_ERR_OTHER;
@@ -99,13 +101,13 @@ int PMPI_Win_detach(MPI_Win win, const void* base)
 int PMPI_Win_free( MPI_Win* win){
   CHECK_NULL(1, MPI_ERR_WIN, win)
   CHECK_WIN(1, (*win))
+  CHECK_COLLECTIVE((*win)->comm(), __func__)
   if (_smpi_cfg_pedantic && (*win)->opened() == 1){//only check in pedantic mode, as it's not clear this is illegal
     XBT_WARN("Attempt to destroy a MPI_Win too early -missing MPI_Win_fence ?");
     return MPI_ERR_WIN;
   }
   const SmpiBenchGuard suspend_bench;
-  delete *win;
-  return MPI_SUCCESS;
+  return simgrid::smpi::Win::del(*win);
 }
 
 int PMPI_Win_set_name(MPI_Win  win, const char * name)
index 57501a5..e991df0 100644 (file)
@@ -58,7 +58,7 @@ int alltoall__pair_rma(const void *send_buff, int send_count, MPI_Datatype send_
             rank /* send_chunk*/, send_count, send_type);
   }
   win->fence(assert);
-  delete win;
+  simgrid::smpi::Win::del(win);
   return 0;
 }
 
index 57b87e2..8def355 100644 (file)
@@ -41,6 +41,7 @@
 
 #include "../coll_tuned_topo.hpp"
 #include "../colls_private.hpp"
+#include "smpi_actor.hpp"
 namespace simgrid{
 namespace smpi{
 int barrier__mvapich2_pair(MPI_Comm comm)
@@ -49,6 +50,7 @@ int barrier__mvapich2_pair(MPI_Comm comm)
     int size, rank;
     int d, dst, src;
     int mpi_errno = MPI_SUCCESS;
+    int tag = smpi_process()->finalizing() ? COLL_TAG_BARRIER-1: COLL_TAG_BARRIER;
 
     size = comm->size();
     /* Trivial barriers return immediately */
@@ -68,25 +70,25 @@ int barrier__mvapich2_pair(MPI_Comm comm)
         if (rank < surfeit) {
             /* get the fanin letter from the upper "half" process: */
             dst = N2_prev + rank;
-            Request::recv(nullptr, 0, MPI_BYTE, dst, COLL_TAG_BARRIER, comm, MPI_STATUS_IGNORE);
+            Request::recv(nullptr, 0, MPI_BYTE, dst, tag, comm, MPI_STATUS_IGNORE);
         }
 
         /* combine on embedded N2_prev power-of-two processes */
         for (d = 1; d < N2_prev; d <<= 1) {
             dst = (rank ^ d);
-            Request::sendrecv(nullptr, 0, MPI_BYTE, dst, COLL_TAG_BARRIER, nullptr, 0, MPI_BYTE, dst, COLL_TAG_BARRIER,
+            Request::sendrecv(nullptr, 0, MPI_BYTE, dst, tag, nullptr, 0, MPI_BYTE, dst, tag,
                               comm, MPI_STATUS_IGNORE);
         }
 
         /* fanout data to nodes above N2_prev... */
         if (rank < surfeit) {
             dst = N2_prev + rank;
-            Request::send(nullptr, 0, MPI_BYTE, dst, COLL_TAG_BARRIER, comm);
+            Request::send(nullptr, 0, MPI_BYTE, dst, tag, comm);
         }
     } else {
         /* fanin data to power of 2 subset */
         src = rank - N2_prev;
-        Request::sendrecv(nullptr, 0, MPI_BYTE, src, COLL_TAG_BARRIER, nullptr, 0, MPI_BYTE, src, COLL_TAG_BARRIER,
+        Request::sendrecv(nullptr, 0, MPI_BYTE, src, tag, nullptr, 0, MPI_BYTE, src, tag,
                           comm, MPI_STATUS_IGNORE);
     }
 
index 3d540de..5c921c8 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "../coll_tuned_topo.hpp"
 #include "../colls_private.hpp"
+#include "smpi_actor.hpp"
 
 /*
  * Barrier is meant to be a synchronous operation, as some BTLs can mark
@@ -52,35 +53,35 @@ int barrier__ompi_doublering(MPI_Comm comm)
 
     rank = comm->rank();
     size = comm->size();
-
+    int tag = smpi_process()->finalizing() ? COLL_TAG_BARRIER-1: COLL_TAG_BARRIER;
     XBT_DEBUG("ompi_coll_tuned_barrier_ompi_doublering rank %d", rank);
 
     left = ((rank-1+size)%size);
     right = ((rank+1)%size);
 
     if (rank > 0) { /* receive message from the left */
-      Request::recv(nullptr, 0, MPI_BYTE, left, COLL_TAG_BARRIER, comm, MPI_STATUS_IGNORE);
+      Request::recv(nullptr, 0, MPI_BYTE, left, tag, comm, MPI_STATUS_IGNORE);
     }
 
     /* Send message to the right */
-    Request::send(nullptr, 0, MPI_BYTE, right, COLL_TAG_BARRIER, comm);
+    Request::send(nullptr, 0, MPI_BYTE, right, tag, comm);
 
     /* root needs to receive from the last node */
     if (rank == 0) {
-      Request::recv(nullptr, 0, MPI_BYTE, left, COLL_TAG_BARRIER, comm, MPI_STATUS_IGNORE);
+      Request::recv(nullptr, 0, MPI_BYTE, left, tag, comm, MPI_STATUS_IGNORE);
     }
 
     /* Allow nodes to exit */
     if (rank > 0) { /* post Receive from left */
-      Request::recv(nullptr, 0, MPI_BYTE, left, COLL_TAG_BARRIER, comm, MPI_STATUS_IGNORE);
+      Request::recv(nullptr, 0, MPI_BYTE, left, tag, comm, MPI_STATUS_IGNORE);
     }
 
     /* send message to the right one */
-    Request::send(nullptr, 0, MPI_BYTE, right, COLL_TAG_BARRIER, comm);
+    Request::send(nullptr, 0, MPI_BYTE, right, tag, comm);
 
     /* rank 0 post receive from the last node */
     if (rank == 0) {
-      Request::recv(nullptr, 0, MPI_BYTE, left, COLL_TAG_BARRIER, comm, MPI_STATUS_IGNORE);
+      Request::recv(nullptr, 0, MPI_BYTE, left, tag, comm, MPI_STATUS_IGNORE);
     }
 
     return MPI_SUCCESS;
@@ -99,6 +100,7 @@ int barrier__ompi_recursivedoubling(MPI_Comm comm)
 
     rank = comm->rank();
     size = comm->size();
+    int tag = smpi_process()->finalizing() ? COLL_TAG_BARRIER-1: COLL_TAG_BARRIER;
     XBT_DEBUG(
                  "ompi_coll_tuned_barrier_ompi_recursivedoubling rank %d",
                  rank);
@@ -112,13 +114,13 @@ int barrier__ompi_recursivedoubling(MPI_Comm comm)
         if (rank >= adjsize) {
             /* send message to lower ranked node */
             remote = rank - adjsize;
-            Request::sendrecv(nullptr, 0, MPI_BYTE, remote, COLL_TAG_BARRIER, nullptr, 0, MPI_BYTE, remote,
-                              COLL_TAG_BARRIER, comm, MPI_STATUS_IGNORE);
+            Request::sendrecv(nullptr, 0, MPI_BYTE, remote, tag, nullptr, 0, MPI_BYTE, remote,
+                              tag, comm, MPI_STATUS_IGNORE);
 
         } else if (rank < (size - adjsize)) {
 
             /* receive message from high level rank */
-            Request::recv(nullptr, 0, MPI_BYTE, rank + adjsize, COLL_TAG_BARRIER, comm, MPI_STATUS_IGNORE);
+            Request::recv(nullptr, 0, MPI_BYTE, rank + adjsize, tag, comm, MPI_STATUS_IGNORE);
         }
     }
 
@@ -131,8 +133,8 @@ int barrier__ompi_recursivedoubling(MPI_Comm comm)
             if (remote >= adjsize) continue;
 
             /* post receive from the remote node */
-            Request::sendrecv(nullptr, 0, MPI_BYTE, remote, COLL_TAG_BARRIER, nullptr, 0, MPI_BYTE, remote,
-                              COLL_TAG_BARRIER, comm, MPI_STATUS_IGNORE);
+            Request::sendrecv(nullptr, 0, MPI_BYTE, remote, tag, nullptr, 0, MPI_BYTE, remote,
+                              tag, comm, MPI_STATUS_IGNORE);
         }
     }
 
@@ -141,7 +143,7 @@ int barrier__ompi_recursivedoubling(MPI_Comm comm)
         if (rank < (size - adjsize)) {
             /* send enter message to higher ranked node */
             remote = rank + adjsize;
-            Request::send(nullptr, 0, MPI_BYTE, remote, COLL_TAG_BARRIER, comm);
+            Request::send(nullptr, 0, MPI_BYTE, remote, tag, comm);
         }
     }
 
@@ -161,6 +163,7 @@ int barrier__ompi_bruck(MPI_Comm comm)
 
     rank = comm->rank();
     size = comm->size();
+    int tag = smpi_process()->finalizing() ? COLL_TAG_BARRIER-1: COLL_TAG_BARRIER;
     XBT_DEBUG(
                  "ompi_coll_tuned_barrier_ompi_bruck rank %d", rank);
 
@@ -170,7 +173,7 @@ int barrier__ompi_bruck(MPI_Comm comm)
         to   = (rank + distance) % size;
 
         /* send message to lower ranked node */
-        Request::sendrecv(nullptr, 0, MPI_BYTE, to, COLL_TAG_BARRIER, nullptr, 0, MPI_BYTE, from, COLL_TAG_BARRIER,
+        Request::sendrecv(nullptr, 0, MPI_BYTE, to, tag, nullptr, 0, MPI_BYTE, from, tag,
                           comm, MPI_STATUS_IGNORE);
     }
 
@@ -188,11 +191,12 @@ int barrier__ompi_two_procs(MPI_Comm comm)
     int remote;
 
     remote = comm->rank();
+    int tag = smpi_process()->finalizing() ? COLL_TAG_BARRIER-1: COLL_TAG_BARRIER;
     XBT_DEBUG(
                  "ompi_coll_tuned_barrier_ompi_two_procs rank %d", remote);
     remote = (remote + 1) & 0x1;
 
-    Request::sendrecv(nullptr, 0, MPI_BYTE, remote, COLL_TAG_BARRIER, nullptr, 0, MPI_BYTE, remote, COLL_TAG_BARRIER,
+    Request::sendrecv(nullptr, 0, MPI_BYTE, remote, tag, nullptr, 0, MPI_BYTE, remote, tag,
                       comm, MPI_STATUS_IGNORE);
     return (MPI_SUCCESS);
 }
@@ -218,12 +222,13 @@ int barrier__ompi_basic_linear(MPI_Comm comm)
     int size = comm->size();
     int rank = comm->rank();
 
+    int tag = smpi_process()->finalizing() ? COLL_TAG_BARRIER-1: COLL_TAG_BARRIER;
     /* All non-root send & receive zero-length message. */
 
     if (rank > 0) {
-      Request::send(nullptr, 0, MPI_BYTE, 0, COLL_TAG_BARRIER, comm);
+      Request::send(nullptr, 0, MPI_BYTE, 0, tag, comm);
 
-      Request::recv(nullptr, 0, MPI_BYTE, 0, COLL_TAG_BARRIER, comm, MPI_STATUS_IGNORE);
+      Request::recv(nullptr, 0, MPI_BYTE, 0, tag, comm, MPI_STATUS_IGNORE);
     }
 
     /* The root collects and broadcasts the messages. */
@@ -233,12 +238,12 @@ int barrier__ompi_basic_linear(MPI_Comm comm)
 
         requests = new MPI_Request[size];
         for (i = 1; i < size; ++i) {
-          requests[i] = Request::irecv(nullptr, 0, MPI_BYTE, i, COLL_TAG_BARRIER, comm);
+          requests[i] = Request::irecv(nullptr, 0, MPI_BYTE, i, tag, comm);
         }
         Request::waitall( size-1, requests+1, MPI_STATUSES_IGNORE );
 
         for (i = 1; i < size; ++i) {
-          requests[i] = Request::isend(nullptr, 0, MPI_BYTE, i, COLL_TAG_BARRIER, comm);
+          requests[i] = Request::isend(nullptr, 0, MPI_BYTE, i, tag, comm);
         }
         Request::waitall( size-1, requests+1, MPI_STATUSES_IGNORE );
         delete[] requests;
@@ -262,6 +267,7 @@ int barrier__ompi_tree(MPI_Comm comm)
 
     rank = comm->rank();
     size = comm->size();
+    int tag = smpi_process()->finalizing() ? COLL_TAG_BARRIER-1: COLL_TAG_BARRIER;
     XBT_DEBUG(
                  "ompi_coll_tuned_barrier_ompi_tree %d",
                  rank);
@@ -273,9 +279,9 @@ int barrier__ompi_tree(MPI_Comm comm)
         partner = rank ^ jump;
         if (!(partner & (jump-1)) && partner < size) {
             if (partner > rank) {
-              Request::recv(nullptr, 0, MPI_BYTE, partner, COLL_TAG_BARRIER, comm, MPI_STATUS_IGNORE);
+              Request::recv(nullptr, 0, MPI_BYTE, partner, tag, comm, MPI_STATUS_IGNORE);
             } else if (partner < rank) {
-              Request::send(nullptr, 0, MPI_BYTE, partner, COLL_TAG_BARRIER, comm);
+              Request::send(nullptr, 0, MPI_BYTE, partner, tag, comm);
             }
         }
     }
@@ -285,9 +291,9 @@ int barrier__ompi_tree(MPI_Comm comm)
         partner = rank ^ jump;
         if (!(partner & (jump-1)) && partner < size) {
             if (partner > rank) {
-              Request::send(nullptr, 0, MPI_BYTE, partner, COLL_TAG_BARRIER, comm);
+              Request::send(nullptr, 0, MPI_BYTE, partner, tag, comm);
             } else if (partner < rank) {
-              Request::recv(nullptr, 0, MPI_BYTE, partner, COLL_TAG_BARRIER, comm, MPI_STATUS_IGNORE);
+              Request::recv(nullptr, 0, MPI_BYTE, partner, tag, comm, MPI_STATUS_IGNORE);
             }
         }
     }
index 3351208..87cfe01 100644 (file)
@@ -31,7 +31,7 @@ constexpr unsigned MPI_REQ_MATCHED        = 0x4000;
 constexpr unsigned MPI_REQ_CANCELLED      = 0x8000;
 constexpr unsigned MPI_REQ_NBC            = 0x10000;
 
-enum class SmpiProcessState { UNINITIALIZED, INITIALIZING, INITIALIZED /*(=MPI_Init called)*/, FINALIZED };
+enum class SmpiProcessState { UNINITIALIZED, INITIALIZING, INITIALIZED /*(=MPI_Init called)*/, FINALIZING, FINALIZED };
 
 constexpr int COLL_TAG_REDUCE         = -112;
 constexpr int COLL_TAG_SCATTER        = -223;
@@ -582,6 +582,15 @@ XBT_PRIVATE void private_execute_flops(double flops);
 #define CHECK_COMM2(num, comm)\
   CHECK_MPI_NULL((num), MPI_COMM_NULL, MPI_ERR_COMM, (comm))
 
+#define CHECK_COLLECTIVE(comm, call)                                                                                   \
+  {                                                                                                                    \
+    if (_smpi_cfg_pedantic) {                                                                                          \
+      std::string call_string = (call);                                                                                \
+      CHECK_ARGS((simgrid::smpi::utils::check_collectives_ordering((comm), call_string) != MPI_SUCCESS),               \
+                 MPI_ERR_OTHER, "%s: collective mismatch", call_string.c_str())                                        \
+    }                                                                                                                  \
+  }
+
 #define CHECK_DELETED(num, err, obj)\
   CHECK_ARGS((obj)->deleted(), (err), "%s: param %d %s has already been freed", __func__, (num),\
   _XBT_STRINGIFY(obj))
index 3b1e6f8..a44f60f 100644 (file)
@@ -56,7 +56,9 @@ public:
   int finalized() const;
   int initializing() const;
   int initialized() const;
+  int finalizing() const;
   void mark_as_initialized();
+  void mark_as_finalizing();
   void set_replaying(bool value);
   bool replaying() const;
   std::string get_instance_id() const { return instance_id_;}
index 87ff9b2..dee8666 100644 (file)
@@ -42,6 +42,8 @@ class Comm : public F2C, public Keyval{
 
   std::unordered_map<std::string, unsigned int> sent_messages_;
   std::unordered_map<std::string, unsigned int> recv_messages_;
+  unsigned int collectives_count_ = 0;
+  std::vector<unsigned int> collectives_counts_; // for MPI_COMM_WORLD only
 
 public:
   static std::unordered_map<int, smpi_key_elem> keyvals_;
@@ -97,6 +99,8 @@ public:
   void increment_sent_messages_count(int src, int dst, int tag);
   unsigned int get_received_messages_count(int src, int dst, int tag);
   void increment_received_messages_count(int src, int dst, int tag);
+  unsigned int get_collectives_count();
+  void increment_collectives_count();
 };
 
 } // namespace smpi
index ff1c128..66a561d 100644 (file)
@@ -19,14 +19,20 @@ class Op : public F2C{
   int refcount_ = 1;
   bool is_predefined_;
   int types_; //bitmask of the allowed datatypes flags
+  std::string name_;
 
 public:
-  Op(MPI_User_function* function, bool commutative, bool predefined=false, int types=0) : func_(function), is_commutative_(commutative), is_predefined_(predefined), types_(types) {if(not predefined) this->add_f();}
+  Op(MPI_User_function* function, bool commutative, bool predefined = false, int types = 0, std::string name = "MPI_Op")
+      : func_(function), is_commutative_(commutative), is_predefined_(predefined), types_(types), name_(std::move(name))
+  {
+    if (not predefined)
+      this->add_f();
+  }
   bool is_commutative() const { return is_commutative_; }
   bool is_predefined() const { return is_predefined_; }
   bool is_fortran_op() const { return is_fortran_op_; }
   int allowed_types() const { return types_; }
-  std::string name() const override {return std::string("MPI_Op");}
+  std::string name() const override {return name_;}
   // tell that we were created from fortran, so we need to translate the type to fortran when called
   void set_fortran_op() { is_fortran_op_ = true; }
   void apply(const void* invec, void* inoutvec, const int* len, MPI_Datatype datatype) const;
index a531494..6ad6982 100644 (file)
@@ -8,6 +8,7 @@
 #include <xbt/base.h>
 
 #include "smpi_f2c.hpp"
+#include "smpi_comm.hpp"
 
 #include <cstddef>
 #include <string>
@@ -35,6 +36,7 @@ XBT_PUBLIC void set_current_handle(F2C* handle);
 XBT_PUBLIC void set_current_buffer(int i, const char* name, const void* handle);
 XBT_PUBLIC size_t get_buffer_size(const void* ptr);
 XBT_PUBLIC void account_free(const void* ptr);
+XBT_PUBLIC int check_collectives_ordering(MPI_Comm comm, const std::string& call);
 
 } // namespace utils
 } // namespace smpi
index 0789da5..339b3c2 100644 (file)
@@ -53,7 +53,7 @@ public:
   Win(MPI_Info info, MPI_Comm comm) : Win(MPI_BOTTOM, 0, 1, info, comm, false, true){};
   Win(const Win&) = delete;
   Win& operator=(const Win&) = delete;
-  ~Win() override;
+  static int del(Win* win);
   int attach (void *base, MPI_Aint size);
   int detach (const void *base);
   void get_name(char* name, int* length) const;
index 4e2fa04..ad8af7d 100644 (file)
@@ -99,6 +99,19 @@ void ActorExt::mark_as_initialized()
     state_ = SmpiProcessState::INITIALIZED;
 }
 
+/** @brief Mark a process as finalizing (=MPI_Finalize called) */
+void ActorExt::mark_as_finalizing()
+{
+  if (state_ != SmpiProcessState::FINALIZED)
+    state_ = SmpiProcessState::FINALIZING;
+}
+
+/** @brief Check if a process is finalizing */
+int ActorExt::finalizing() const
+{
+  return (state_ == SmpiProcessState::FINALIZING);
+}
+
 void ActorExt::set_replaying(bool value)
 {
   if (state_ != SmpiProcessState::FINALIZED)
index 0467704..55b6c77 100644 (file)
@@ -112,7 +112,7 @@ simgrid::config::Flag<std::string> _smpi_cfg_comp_adjustment_file{
 simgrid::config::Flag<bool> _smpi_cfg_default_errhandler_is_error{
   "smpi/errors-are-fatal", "Whether MPI errors are fatal or just return. Default is true", true };
 simgrid::config::Flag<bool> _smpi_cfg_pedantic{
-  "smpi/pedantic", "Activate extra checks that may crash slightly incorrect codes which would not crash on actual implementations", true };
+  "smpi/pedantic", "Activate extra checks that may crash slightly incorrect codes which would not crash on actual implementations", false };
 simgrid::config::Flag<double> _smpi_init_sleep(
   "smpi/init", "Time to inject inside a call to MPI_Init", 0.0);
 #if HAVE_PAPI
index 837cedf..77436cc 100644 (file)
@@ -11,6 +11,7 @@
 #include "src/surf/xml/platf.hpp"
 #include "xbt/file.hpp"
 #include "xbt/log.h"
+#include "xbt/ex.h"
 #include "xbt/parse_units.hpp"
 #include "xbt/sysdep.h"
 #include <algorithm>
@@ -48,6 +49,8 @@ current_buffer_metadata_t current_buffer2;
 
 std::unordered_map<const void*, alloc_metadata_t> allocs;
 
+std::unordered_map<int, std::vector<std::string>> collective_calls;
+
 std::vector<s_smpi_factor_t> parse_factor(const std::string& smpi_coef_string)
 {
   std::vector<s_smpi_factor_t> smpi_factor;
@@ -345,6 +348,29 @@ void account_free(const void* ptr){
   }
 }
 
+int check_collectives_ordering(MPI_Comm comm, const std::string& call)
+{
+  unsigned int count = comm->get_collectives_count();
+  comm->increment_collectives_count();
+  auto vec = collective_calls.find(comm->id());
+  if (vec == collective_calls.end()) {
+    collective_calls.emplace(comm->id(), std::vector<std::string>{call});
+  } else {
+    // are we the first ? add the call
+    if (vec->second.size() == count) {
+      vec->second.emplace_back(call);
+    } else if (vec->second.size() > count) {
+      if (vec->second[count] != call) {
+        XBT_WARN("Collective operation mismatch. For process %ld, expected %s, got %s",
+                 simgrid::s4u::this_actor::get_pid(), vec->second[count].c_str(), call.c_str());
+        return MPI_ERR_OTHER;
+      }
+    } else {
+      THROW_IMPOSSIBLE;
+    }
+  }
+  return MPI_SUCCESS;
+}
 }
 }
 } // namespace simgrid
index b482e21..7a19277 100644 (file)
@@ -55,7 +55,6 @@ Comm::Comm(MPI_Group group, MPI_Topology topo, bool smp, int in_id)
     colls::bcast(&id, 1, MPI_INT, 0, this);
     XBT_DEBUG("Communicator %p has id %d", this, id);
     id_=id;//only set here, as we don't want to change it in the middle of the bcast
-    colls::barrier(this);
   }
 }
 
@@ -650,5 +649,31 @@ void Comm::increment_received_messages_count(int src, int dst, int tag)
   recv_messages_[hash_message(src, dst, tag)]++;
 }
 
+unsigned int Comm::get_collectives_count()
+{
+  if (this==MPI_COMM_UNINITIALIZED){
+    return smpi_process()->comm_world()->get_collectives_count();
+  }else if(this == MPI_COMM_WORLD || this == smpi_process()->comm_world()){
+    if (collectives_counts_.empty())
+      collectives_counts_.resize(this->size());
+    return collectives_counts_[this->rank()];
+  }else{
+    return collectives_count_;
+  }
+}
+
+void Comm::increment_collectives_count()
+{
+   if (this==MPI_COMM_UNINITIALIZED){
+    smpi_process()->comm_world()->increment_collectives_count();
+  }else if (this == MPI_COMM_WORLD || this == smpi_process()->comm_world()){
+    if (collectives_counts_.empty())
+      collectives_counts_.resize(this->size());
+    collectives_counts_[this->rank()]++;
+  }else{
+    collectives_count_++;
+  }
+}
+
 } // namespace smpi
 } // namespace simgrid
index db78594..5318322 100644 (file)
@@ -81,7 +81,7 @@ File::~File()
     delete shared_file_pointer_;
     delete[] list_;
   }
-  delete win_;
+  simgrid::smpi::Win::del(win_);
   file_->close();
   F2C::free_f(this->f2c_id());
   if (info_ != MPI_INFO_NULL)
index 3e4e348..d2e9c50 100644 (file)
@@ -238,9 +238,8 @@ static void no_func(void*, void*, int*, MPI_Datatype*)
   /* obviously a no-op */
 }
 
-
-#define CREATE_MPI_OP(name, func, types)                                                                                      \
-  SMPI_Op _XBT_CONCAT(smpi_MPI_, name)(&(func) /* func */, true, true, types);
+#define CREATE_MPI_OP(name, func, types)                                                                               \
+  SMPI_Op _XBT_CONCAT(smpi_MPI_, name)(&(func), true, true, types, _XBT_STRINGIFY(MPI_##name));
 
 #define MAX_TYPES DT_FLAG_C_INTEGER|DT_FLAG_F_INTEGER|DT_FLAG_FP|DT_FLAG_MULTILANG
 #define LAND_TYPES DT_FLAG_C_INTEGER|DT_FLAG_FP|DT_FLAG_LOGICAL|DT_FLAG_MULTILANG
index 0b5dde5..57c1aca 100644 (file)
@@ -1093,9 +1093,8 @@ int Request::wait(MPI_Request * request, MPI_Status * status)
         // this is not a detached send
         kernel::actor::ActorImpl* issuer = kernel::actor::ActorImpl::self();
         kernel::actor::ActivityWaitSimcall observer{issuer, (*request)->action_.get(), -1};
-        kernel::actor::simcall_blocking(
-            [&observer] { observer.get_activity()->wait_for(observer.get_issuer(), observer.get_timeout()); },
-            &observer);
+        kernel::actor::simcall_blocking([issuer, &observer] { observer.get_activity()->wait_for(issuer, -1); },
+                                        &observer);
       } catch (const CancelException&) {
         XBT_VERB("Request cancelled");
       }
index 65b034a..8eb022d 100644 (file)
@@ -62,38 +62,47 @@ Win::Win(void* base, MPI_Aint size, int disp_unit, MPI_Info info, MPI_Comm comm,
   colls::allgather(&connected_wins_[rank_], sizeof(MPI_Win), MPI_BYTE, connected_wins_.data(), sizeof(MPI_Win),
                    MPI_BYTE, comm);
   if  (MC_is_active() || MC_record_replay_is_active()){
-    if (bar_.get() == nullptr) // First to arrive on the barrier
+    s4u::Barrier* bar_ptr;
+    if (rank_ == 0) {
       bar_ = s4u::Barrier::create(comm->size());
-    bar_->wait();
-  }else{
-    colls::barrier(comm);
+      bar_ptr = bar_.get();
+    }
+    colls::bcast(&bar_ptr, sizeof(s4u::Barrier*), MPI_BYTE, 0, comm);
+    if (rank_ != 0)
+      bar_ = s4u::BarrierPtr(bar_ptr);
   }
   this->add_f();
 }
 
-Win::~Win(){
+int Win::del(Win* win){
   //As per the standard, perform a barrier to ensure every async comm is finished
   if  (MC_is_active() || MC_record_replay_is_active())
-    bar_->wait();
+    win->bar_->wait();
   else
-    colls::barrier(comm_);
-  flush_local_all();
+    colls::barrier(win->comm_);
+  win->flush_local_all();
 
-  if (info_ != MPI_INFO_NULL)
-    simgrid::smpi::Info::unref(info_);
-  if (errhandler_ != MPI_ERRHANDLER_NULL)
-    simgrid::smpi::Errhandler::unref(errhandler_);
+  if (win->info_ != MPI_INFO_NULL)
+    simgrid::smpi::Info::unref(win->info_);
+  if (win->errhandler_ != MPI_ERRHANDLER_NULL)
+    simgrid::smpi::Errhandler::unref(win->errhandler_);
 
-  comm_->remove_rma_win(this);
+  win->comm_->remove_rma_win(win);
 
-  colls::barrier(comm_);
-  Comm::unref(comm_);
+  colls::barrier(win->comm_);
+  Comm::unref(win->comm_);
+  if (!win->lockers_.empty() || win->opened_ < 0){
+    XBT_WARN("Freeing a locked or opened window");
+    return MPI_ERR_WIN;
+  }
+  if (win->allocated_)
+    xbt_free(win->base_);
 
-  if (allocated_)
-    xbt_free(base_);
+  F2C::free_f(win->f2c_id());
+  win->cleanup_attr<Win>();
 
-  F2C::free_f(this->f2c_id());
-  cleanup_attr<Win>();
+  delete win;
+  return MPI_SUCCESS;
 }
 
 int Win::attach(void* /*base*/, MPI_Aint size)
@@ -428,7 +437,7 @@ int Win::start(MPI_Group group, int /*assert*/)
 
   group->ref();
   dst_group_ = group;
-  opened_++; // we're open for business !
+  opened_--; // we're open for business !
   XBT_DEBUG("Leaving MPI_Win_Start");
   return MPI_SUCCESS;
 }
@@ -453,7 +462,7 @@ int Win::post(MPI_Group group, int /*assert*/)
 
   group->ref();
   src_group_ = group;
-  opened_++; // we're open for business !
+  opened_--; // we're open for business !
   XBT_DEBUG("Leaving MPI_Win_Post");
   return MPI_SUCCESS;
 }
@@ -479,7 +488,7 @@ int Win::complete(){
 
   flush_local_all();
 
-  opened_--; //we're closed for business !
+  opened_++; //we're closed for business !
   Group::unref(dst_group_);
   dst_group_ = MPI_GROUP_NULL;
   return MPI_SUCCESS;
@@ -505,7 +514,7 @@ int Win::wait(){
 
   flush_local_all();
 
-  opened_--; //we're closed for business !
+  opened_++; //we're closed for business !
   Group::unref(src_group_);
   src_group_ = MPI_GROUP_NULL;
   return MPI_SUCCESS;
index ef1eb1d..953a18e 100755 (executable)
@@ -233,7 +233,7 @@ while true; do
             shift 1
             ;;
         "-analyze")
-            SIMOPTS="$SIMOPTS --cfg=smpi/display-timing:yes --cfg=smpi/display-allocs:yes --cfg=smpi/list-leaks:50"
+            SIMOPTS="$SIMOPTS --cfg=smpi/display-timing:yes --cfg=smpi/display-allocs:yes --cfg=smpi/list-leaks:50 --cfg=smpi/pedantic:true"
             shift 1
             ;;
         "-help" | "--help" | "-h")
index a84c094..e638f1f 100644 (file)
@@ -77,41 +77,37 @@ DiskAction* DiskS19Model::io_start(const DiskImpl* disk, sg_size_t size, s4u::Io
  ************/
 void DiskS19::set_read_bandwidth(double value)
 {
-  read_bw_.peak = value;
-
+  DiskImpl::set_read_bandwidth(value);
   if (get_read_constraint()) {
-    get_model()->get_maxmin_system()->update_constraint_bound(get_read_constraint(), read_bw_.peak * read_bw_.scale);
+    get_model()->get_maxmin_system()->update_constraint_bound(get_read_constraint(), get_read_bandwidth());
   }
 }
 
 void DiskS19::set_write_bandwidth(double value)
 {
-  write_bw_.peak = value;
-
+  DiskImpl::set_write_bandwidth(value);
   if (get_write_constraint()) {
-    get_model()->get_maxmin_system()->update_constraint_bound(get_write_constraint(), write_bw_.peak * write_bw_.scale);
+    get_model()->get_maxmin_system()->update_constraint_bound(get_write_constraint(), get_write_bandwidth());
   }
 }
 
 void DiskS19::set_readwrite_bandwidth(double value)
 {
-  readwrite_bw_ = value;
+  DiskImpl::set_readwrite_bandwidth(value);
   if (get_constraint()) {
-    get_model()->get_maxmin_system()->update_constraint_bound(get_constraint(), readwrite_bw_);
+    get_model()->get_maxmin_system()->update_constraint_bound(get_constraint(), get_readwrite_bandwidth());
   }
 }
 
 void DiskS19::apply_event(kernel::profile::Event* triggered, double value)
 {
   /* Find out which of my iterators was triggered, and react accordingly */
-  if (triggered == read_bw_.event) {
+  if (triggered == get_read_event()) {
     set_read_bandwidth(value);
-    tmgr_trace_event_unref(&read_bw_.event);
-
-  } else if (triggered == write_bw_.event) {
+    unref_read_event();
+  } else if (triggered == get_write_event()) {
     set_write_bandwidth(value);
-    tmgr_trace_event_unref(&write_bw_.event);
-
+    unref_write_event();
   } else if (triggered == get_state_event()) {
     if (value > 0)
       turn_on();
index c2a007f..623f4c5 100644 (file)
@@ -7,8 +7,8 @@ $ ${bindir:=.}/../../../bin/simgrid-mc ${bindir:=.}/random-bug assert ${platfdir
 > [  0.000000] (0:maestro@) *** PROPERTY NOT VALID ***
 > [  0.000000] (0:maestro@) **************************
 > [  0.000000] (0:maestro@) Counter-example execution trace:
-> [  0.000000] (0:maestro@)   Random([0;5] ~> 3)
-> [  0.000000] (0:maestro@)   Random([0;5] ~> 4)
+> [  0.000000] (0:maestro@)   1: Random([0;5] ~> 3)
+> [  0.000000] (0:maestro@)   1: Random([0;5] ~> 4)
 > [  0.000000] (0:maestro@) Path = 1/3;1/4
 > [  0.000000] (0:maestro@) DFS exploration ended. 27 unique states visited; 22 backtracks (68 transition replays, 19 states visited overall)
 
index 1aeb067..f73d665 100644 (file)
@@ -7,8 +7,8 @@ $ ${bindir:=.}/../../../bin/simgrid-mc ${bindir:=.}/random-bug assert ${platfdir
 > [  0.000000] (0:maestro@) *** PROPERTY NOT VALID ***
 > [  0.000000] (0:maestro@) **************************
 > [  0.000000] (0:maestro@) Counter-example execution trace:
-> [  0.000000] (0:maestro@)   Random([0;5] ~> 3)
-> [  0.000000] (0:maestro@)   Random([0;5] ~> 4)
+> [  0.000000] (0:maestro@)   1: Random([0;5] ~> 3)
+> [  0.000000] (0:maestro@)   1: Random([0;5] ~> 4)
 > [  0.000000] (0:maestro@) Path = 1/3;1/4
 > [  0.000000] (0:maestro@) DFS exploration ended. 27 unique states visited; 22 backtracks (68 transition replays, 19 states visited overall)
 
@@ -22,8 +22,8 @@ $ ${bindir:=.}/../../../bin/simgrid-mc ${bindir:=.}/random-bug abort ${platfdir}
 > [  0.000000] (0:maestro@) **************************
 > [  0.000000] (0:maestro@) From signal: Aborted
 > [  0.000000] (0:maestro@) Counter-example execution trace:
-> [  0.000000] (0:maestro@)   Random([0;5] ~> 3)
-> [  0.000000] (0:maestro@)   Random([0;5] ~> 4)
+> [  0.000000] (0:maestro@)   1: Random([0;5] ~> 3)
+> [  0.000000] (0:maestro@)   1: Random([0;5] ~> 4)
 > [  0.000000] (0:maestro@) Path = 1/3;1/4
 > [  0.000000] (0:maestro@) DFS exploration ended. 27 unique states visited; 22 backtracks (68 transition replays, 19 states visited overall)
 > [  0.000000] (0:maestro@) Stack trace not displayed because you passed --log=no_loc
@@ -45,8 +45,8 @@ $ ${bindir:=.}/../../../bin/simgrid-mc ${bindir:=.}/random-bug segv ${platfdir}/
 > [  0.000000] (0:maestro@) **************************
 > [  0.000000] (0:maestro@) From signal: Segmentation fault
 > [  0.000000] (0:maestro@) Counter-example execution trace:
-> [  0.000000] (0:maestro@)   Random([0;5] ~> 3)
-> [  0.000000] (0:maestro@)   Random([0;5] ~> 4)
+> [  0.000000] (0:maestro@)   1: Random([0;5] ~> 3)
+> [  0.000000] (0:maestro@)   1: Random([0;5] ~> 4)
 > [  0.000000] (0:maestro@) Path = 1/3;1/4
 > [  0.000000] (0:maestro@) DFS exploration ended. 27 unique states visited; 22 backtracks (68 transition replays, 19 states visited overall)
 > [  0.000000] (0:maestro@) Stack trace not displayed because you passed --log=no_loc
index e8605f9..c9e92c7 100644 (file)
@@ -54,10 +54,10 @@ def master():
 
   assert False, "The impossible just happened (yet again): daemons shall not finish."
 
-def worker(id):
+def worker(my_id):
   global todo
-  this_actor.info(f"Worker {id} booting")
-  this_actor.on_exit(lambda killed: this_actor.info(f"Worker {id} dying {'forcefully' if killed else 'peacefully'}."))
+  this_actor.info(f"Worker {my_id} booting")
+  this_actor.on_exit(lambda killed: this_actor.info(f"Worker {my_id} dying {'forcefully' if killed else 'peacefully'}."))
 
   while todo > 0:
     assert Engine.clock < deadline, f"Failed to run all tasks in less than {deadline} seconds. Is this an infinite loop?"
@@ -78,7 +78,6 @@ def worker(id):
       this_actor.info("Timeouted while getting a task.")
 
 if __name__ == '__main__':
-  global mailbox
   e = Engine(sys.argv)
 
   assert host_count > 2, "You need at least 2 workers (i.e., 3 hosts) or the master will be auto-killed when the only worker gets killed."
index fd2aa91..529aad5 100644 (file)
@@ -5,7 +5,31 @@
 # Only the python scripts are embeeded in the archive, and the C test files are generated at config time using these scripts.
 # These python scripts are copied over from the MBI repository with as little changes as possible.
 
-set(generator_scripts CollMatchingGenerator.py ResleakGenerator.py) # More generators to come
+set(generator_scripts 
+    CollArgGenerator.py
+    CollComGenerator.py
+    CollLocalConcurrencyGenerator.py
+    CollMatchingGenerator.py
+    CollP2PMatchingGenerator.py
+    CollP2PMessageRaceGenerator.py
+    CollTopoGenerator.py
+    MissingWaitandStartGenerator.py
+    P2PArgGenerator.py
+    P2PComGenerator.py
+    P2PInvalidComGenerator.py
+    P2PLocalConcurrencyGenerator.py
+    P2PMatchingANYSRCGenerator.py
+    P2PMatchingGenerator.py
+    P2PProbeGenerator.py
+    ResleakGenerator.py
+    RMAArgGenerator.py
+    RMAInvalidArgGenerator.py
+    RMALocalLocalConcurrencyGenerator.py
+    RMAP2PGlobalConcurrencyGenerator.py
+    RMARemoteLocalConcurrencyGenerator.py
+    RMARemoteRemoteConcurrencyGenerator.py
+    RMAReqLifecycleGenerator.py
+    RMAWinBufferGenerator.py)
 
 if (enable_smpi_MBI_testsuite)
   if (NOT enable_smpi)
@@ -63,6 +87,28 @@ if (enable_smpi_MBI_testsuite)
   else()
     file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/MBIutils.py DESTINATION ${CMAKE_BINARY_DIR}/MBI)
   endif()
+
+  # The following tests are known to fail because simgrid does not intercept local modifications yet
+  # An idea could be to use ASan on the verified application, along with https://github.com/google/sanitizers/wiki/AddressSanitizerManualPoisoning
+  # But currently, ASan is not usable at all, since the Checker dislikes this trick when it tries to read the memory of the app. 
+  # We should change the checker to not read the app when verifying safty properties
+  foreach(localmodif 
+          LocalConcurrency_Iallgather_nok      LocalConcurrency_Iallgatherv_nok     LocalConcurrency_Iallreduce_nok      LocalConcurrency_Ialltoall_nok
+          LocalConcurrency_Ialltoallv_nok      LocalConcurrency_Ibcast_nok          LocalConcurrency_Iexscan_nok         LocalConcurrency_Igather_nok
+          LocalConcurrency_Irecv_Isend_nok     LocalConcurrency_Irecv_Send_init_nok LocalConcurrency_Irecv_Send_nok      LocalConcurrency_Ireduce_nok
+          LocalConcurrency_Iscan_nok           LocalConcurrency_Iscatter_nok        LocalConcurrency_Recv_Isend_nok      LocalConcurrency_Recv_Send_init_nok
+          LocalConcurrency_Recv_init_Isend_nok LocalConcurrency_Recv_init_Send_nok  LocalConcurrency_Recv_init_Send_init_nok
+
+          GlobalConcurrency_Get_Isend_Irecv_nok GlobalConcurrency_Get_Isend_Recv_nok GlobalConcurrency_Get_Send_Irecv_nok GlobalConcurrency_Get_Send_Recv_nok 
+          GlobalConcurrency_Put_Isend_Irecv_nok GlobalConcurrency_Put_Isend_Recv_nok GlobalConcurrency_Put_Send_Irecv_nok GlobalConcurrency_Put_Send_Recv_nok 
+
+          GlobalConcurrency_rl_Win_fence_Get_rload_nok     GlobalConcurrency_rl_Win_fence_Get_rstore_nok 
+          GlobalConcurrency_rl_Win_fence_Put_rload_nok     GlobalConcurrency_rl_Win_fence_Put_rstore_nok
+          GlobalConcurrency_rl_Win_lock_all_Get_rload_nok  GlobalConcurrency_rl_Win_lock_all_Get_rstore_nok
+          GlobalConcurrency_rl_Win_lock_all_Put_rload_nok  GlobalConcurrency_rl_Win_lock_all_Put_rstore_nok
+       )
+    set_tests_properties(mbi-${localmodif} PROPERTIES WILL_FAIL true)
+  endforeach(localmodif )
 endif()
 
 # Add the needed files to the distribution
diff --git a/teshsuite/smpi/MBI/CollArgGenerator.py b/teshsuite/smpi/MBI/CollArgGenerator.py
new file mode 100755 (executable)
index 0000000..8e2e68a
--- /dev/null
@@ -0,0 +1,224 @@
+#! /usr/bin/python3
+import os
+import sys
+from generator_utils import *
+
+template = """// @{generatedby}@
+/* ///////////////////////// The MPI Bugs Initiative ////////////////////////
+
+  Origin: MBI
+
+  Description: @{shortdesc}@
+    @{longdesc}@
+
+  Version of MPI: Conforms to MPI 1.1, does not require MPI 2 implementation
+
+BEGIN_MPI_FEATURES
+  P2P!basic: Lacking
+  P2P!nonblocking: Lacking
+  P2P!persistent: Lacking
+  COLL!basic: @{collfeature}@
+  COLL!nonblocking: @{icollfeature}@
+  COLL!persistent: Lacking
+  COLL!tools: @{toolfeature}@
+  RMA: Lacking
+END_MPI_FEATURES
+
+BEGIN_MBI_TESTS
+  $ mpirun -np 2 ${EXE}
+  | @{outcome}@
+  | @{errormsg}@
+END_MBI_TESTS
+//////////////////////       End of MBI headers        /////////////////// */
+
+#include <mpi.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define buff_size 128
+
+int main(int argc, char **argv) {
+  int nprocs = -1;
+  int rank = -1;
+  int root = 0;
+  int size = 1, j=0, color=0;
+
+  MPI_Init(&argc, &argv);
+  MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+  printf("Hello from rank %d \\n", rank);
+
+  if (nprocs < 2)
+    printf("MBI ERROR: This test needs at least 2 processes to produce a bug!\\n");
+
+  MPI_Comm newcom = MPI_COMM_WORLD;
+  MPI_Op op = MPI_SUM;
+  MPI_Datatype type = MPI_INT;
+
+  int dbs = sizeof(int)*nprocs; /* Size of the dynamic buffers for alltoall and friends */
+
+  @{init}@
+  @{start}@
+
+  @{change_arg}@
+  @{operation}@ /* MBIERROR2 */
+  @{fini}@
+  @{free}@
+
+  MPI_Finalize();
+  printf("Rank %d finished normally\\n", rank);
+  return 0;
+}
+"""
+
+#####################################################
+# Generate code with color mismatch in MPI_Comm_split
+#####################################################
+
+for c in tcoll4color:
+    patterns = {}
+    patterns = {'c': c}
+    patterns['generatedby'] = f'DO NOT EDIT: this file was generated by {os.path.basename(sys.argv[0])}. DO NOT EDIT.'
+    patterns['collfeature'] = 'Lacking'
+    patterns['icollfeature'] = 'Lacking'
+    patterns['toolfeature'] = 'Yes' if c in tcoll4color else 'Lacking'
+    patterns['c'] = c
+    patterns['init'] = init[c]("1")
+    patterns['start'] = start[c]("1")
+    patterns['operation'] = operation[c]("1")
+    patterns['fini'] = fini[c]("1")
+    patterns['free'] = free[c]("1")
+    patterns['change_arg'] = ''
+
+    # Generate the code with invalid color
+    replace = patterns
+    replace['shortdesc'] = 'Invalid color in @{c}@'
+    replace['longdesc'] = 'invalid color in @{c}@'
+    replace['outcome'] = 'ERROR: InvalidOtherArg'
+    replace['errormsg'] = 'Invalid Argument in collective. @{c}@ at line @{line:MBIERROR2}@ has an invalid color'
+    replace['change_arg'] = 'color=-10; /* MBIERROR1*/'
+    make_file(template, f'InvalidParam_OtherArg_{c}_nok.c', replace)
+
+
+##################################
+# Generate code with root mismatch
+##################################
+
+for c in coll4root + icoll4root:
+    patterns = {}
+    patterns = {'c': c}
+    patterns['generatedby'] = f'DO NOT EDIT: this file was generated by {os.path.basename(sys.argv[0])}. DO NOT EDIT.'
+    patterns['collfeature'] = 'Yes' if c in coll4root else 'Lacking'
+    patterns['icollfeature'] = 'Yes' if c in icoll4root else 'Lacking'
+    patterns['toolfeature'] = 'Lacking'
+    patterns['c'] = c
+    patterns['init'] = init[c]("1")
+    patterns['start'] = start[c]("1")
+    patterns['fini'] = fini[c]("1")
+    patterns['free'] = free[c]("1")
+    patterns['operation'] = operation[c]("1")
+    patterns['change_arg'] = ''
+
+    # Generate an incorrect root matching (root mismatch)
+    replace = patterns
+    replace['shortdesc'] = 'Collective @{c}@ with a root mismatch'
+    replace['longdesc'] = f'Odd ranks use 0 as a root while even ranks use 1 as a root'
+    replace['outcome'] = 'ERROR: RootMatching'
+    replace['errormsg'] = 'Collective root mistmatch. @{c}@ at @{filename}@:@{line:MBIERROR2}@ has 0 or 1 as a root.'
+    replace['change_arg'] = 'if (rank % 2)\n    root = 1; /* MBIERROR1 */'
+    make_file(template, f'ParamMatching_Root_{c}_nok.c', replace)
+
+    # Generate the call with root=-1 (invalid root)
+    replace = patterns
+    replace['shortdesc'] = f'Collective {c} with root = -1'
+    replace['longdesc'] = f'Collective {c} with root = -1'
+    replace['outcome'] = 'ERROR: InvalidRoot'
+    replace['errormsg'] = 'Invalid collective root.  @{c}@ at @{filename}@:@{line:MBIERROR2}@ has -1 as a root while communicator MPI_COMM_WORLD requires ranks in range 0 to 1.'
+    replace['change_arg'] = 'root = -1; /* MBIERROR1 */'
+    make_file(template, f'InvalidParam_RootNeg_{c}_nok.c', replace)
+
+    # Generate the call with root=2 (root not in communicator)
+    replace = patterns
+    replace['shortdesc'] = f'Collective {c} with root out of the communicator'
+    replace['longdesc'] = f'Collective {c} with root = 2 (there is only 2 ranks)'
+    replace['outcome'] = 'ERROR: InvalidRoot'
+    replace['errormsg'] = 'Invalid collective root.  @{c}@ at @{filename}@:@{line:MBIERROR2}@ has 2 as a root while communicator MPI_COMM_WORLD requires ranks in range 0 to 1.'
+    replace['change_arg'] = 'root = nprocs; /* MBIERROR1 */'
+    make_file(template, f'InvalidParam_RootTooLarge_{c}_nok.c', replace)
+
+
+##################################
+# Generate code with type mismatch
+##################################
+
+for c in coll + icoll:
+  if c != 'MPI_Barrier': # Barrier has no Data to mismatch or to nullify
+    patterns = {}
+    patterns = {'c': c}
+    patterns['generatedby'] = f'DO NOT EDIT: this file was generated by {os.path.basename(sys.argv[0])}. DO NOT EDIT.'
+    patterns['collfeature'] = 'Yes' if c in coll else 'Lacking'
+    patterns['icollfeature'] = 'Yes' if c in icoll + ibarrier else 'Lacking'
+    patterns['toolfeature'] = 'Lacking'
+    patterns['c'] = c
+    patterns['init'] = init[c]("1")
+    patterns['start'] = start[c]("1")
+    patterns['fini'] = fini[c]("1")
+    patterns['operation'] = operation[c]("1")
+    patterns['free'] = free[c]("1")
+    patterns['change_arg'] = ''
+
+    # Generate the incorrect matching (datatype Mmismatch)
+    replace = patterns
+    replace['shortdesc'] = 'Collective @{c}@ with a datatype mismatch'
+    replace['longdesc'] = f'Odd ranks use MPI_INT as the datatype while even ranks use MPI_FLOAT'
+    replace['outcome'] = 'ERROR: DatatypeMatching'
+    replace['errormsg'] = 'Collective datatype mistmatch. @{c}@ at @{filename}@:@{line:MBIERROR2}@ has MPI_INT or MPI_FLOAT as a datatype.'
+    replace['change_arg'] = 'if (rank % 2)\n    type = MPI_FLOAT; /* MBIERROR1 */'
+    make_file(template, f'ParamMatching_Data_{c}_nok.c', replace)
+
+    # Generate the call with null type (invalid datatype)
+    replace = patterns
+    replace['shortdesc'] = 'Collective @{c}@ with an invalid datatype '
+    replace['longdesc'] = 'Collective @{c}@ with an invalid datatype '
+    replace['outcome'] = 'ERROR: InvalidDatatype'
+    replace['errormsg'] = 'Invalid Datatype. @{c}@ at @{filename}@:@{line:MBIERROR2}@ has an invalid datatype.'
+    replace['change_arg'] = 'type=MPI_DATATYPE_NULL; /* MBIERROR1 */'
+    make_file(template, f'InvalidParam_DataNull_{c}_nok.c', replace)
+
+
+##################################
+# Generate code with Op  mismatch
+##################################
+
+for c in coll4op + icoll4op:
+    patterns = {}
+    patterns = {'c': c}
+    patterns['generatedby'] = f'DO NOT EDIT: this file was generated by {os.path.basename(sys.argv[0])}. DO NOT EDIT.'
+    patterns['collfeature'] = 'Yes' if c in  coll4op else 'Lacking'
+    patterns['icollfeature'] = 'Yes' if c in icoll4op else 'Lacking'
+    patterns['toolfeature'] = 'Lacking'
+    patterns['c'] = c
+    patterns['init'] = init[c]("1")
+    patterns['start'] = start[c]("1")
+    patterns['fini'] = fini[c]("1")
+    patterns['operation'] = operation[c]("1")
+    patterns['free'] = free[c]("1")
+    patterns['change_arg'] = ''
+
+    # Generate the incorrect matching (op mismatch)
+    replace = patterns
+    replace['shortdesc'] = 'Collective @{c}@ with an operator  mismatch'
+    replace['longdesc'] = f'Odd ranks use MPI_SUM as the operator while even ranks use MPI_MAX'
+    replace['outcome'] = 'ERROR: OperatorMatching'
+    replace['errormsg'] = 'Collective operator mistmatch. @{c}@ at @{filename}@:@{line:MBIERROR2}@ has MPI_MAX or MPI_SUM as an operator.'
+    replace['change_arg'] = 'if (rank % 2)\n    op = MPI_MAX; /* MBIERROR1 */'
+    make_file(template, f'ParamMatching_Op_{c}_nok.c', replace)
+
+    # Generate the call with Op=MPI_OP_NULL (invalid op)
+    replace = patterns
+    replace['shortdesc'] = 'Collective @{c}@ with an invalid operator '
+    replace['longdesc'] = 'Collective @{c}@ with an invalid operator '
+    replace['outcome'] = 'ERROR: InvalidOperator'
+    replace['errormsg'] = 'Invalid Operator. @{c}@ at @{filename}@:@{line:MBIERROR2}@ has MPI_OP_NULL as an operator.'
+    replace['change_arg'] = 'op = MPI_OP_NULL; /* MBIERROR1 */'
+    make_file(template, f'InvalidParam_OpNull_{c}_nok.c', replace)
diff --git a/teshsuite/smpi/MBI/CollComGenerator.py b/teshsuite/smpi/MBI/CollComGenerator.py
new file mode 100755 (executable)
index 0000000..a01dbe5
--- /dev/null
@@ -0,0 +1,116 @@
+#! /usr/bin/python3
+import os
+import sys
+from generator_utils import *
+
+template = """// @{generatedby}@
+/* ///////////////////////// The MPI Bugs Initiative ////////////////////////
+
+  Origin: MBI
+
+  Description: @{shortdesc}@
+    @{longdesc}@
+
+   Version of MPI: Conforms to MPI 1.1, does not require MPI 2 implementation
+
+BEGIN_MPI_FEATURES
+  P2P!basic: Lacking
+  P2P!nonblocking: Lacking
+  P2P!persistent: Lacking
+  COLL!basic: @{collfeature}@
+  COLL!nonblocking: @{icollfeature}@
+  COLL!persistent: Lacking
+  COLL!tools: Yes
+  RMA: Lacking
+END_MPI_FEATURES
+
+BEGIN_MBI_TESTS
+  $ mpirun -np 2 ${EXE}
+  | @{outcome}@
+  | @{errormsg}@
+END_MBI_TESTS
+//////////////////////       End of MBI headers        /////////////////// */
+
+#include <mpi.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define buff_size 128
+
+int main(int argc, char **argv) {
+  int nprocs = -1;
+  int rank = -1;
+  int root = 0;
+
+  MPI_Init(&argc, &argv);
+  MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+  printf("Hello from rank %d \\n", rank);
+
+  if (nprocs < 2)
+    printf("MBI ERROR: This test needs at least 2 processes to produce a bug!\\n");
+
+  MPI_Op op = MPI_SUM;
+  MPI_Datatype type = MPI_INT;
+  MPI_Comm newcom;
+  MPI_Comm_split(MPI_COMM_WORLD, 0, nprocs - rank, &newcom);
+
+  @{change_com}@
+
+  int dbs = sizeof(int)*nprocs; /* Size of the dynamic buffers for alltoall and friends */
+  @{init}@
+  @{start}@
+  @{operation}@ /* MBIERROR */
+  @{fini}@
+  @{free}@
+
+  if(newcom != MPI_COMM_NULL && newcom != MPI_COMM_WORLD)
+    MPI_Comm_free(&newcom);
+
+  MPI_Finalize();
+  printf("Rank %d finished normally\\n", rank);
+  return 0;
+}
+"""
+
+
+# Generate code with one collective
+for c in coll + icoll + ibarrier:
+    patterns = {}
+    patterns = {'c': c}
+    patterns['generatedby'] = f'DO NOT EDIT: this file was generated by {os.path.basename(sys.argv[0])}. DO NOT EDIT.'
+    patterns['collfeature'] = 'Yes' if c in coll else 'Lacking'
+    patterns['icollfeature'] = 'Yes' if c in icoll + ibarrier else 'Lacking'
+    patterns['c'] = c
+    patterns['init'] = init[c]("1")
+    patterns['start'] = start[c]("1")
+    patterns['fini'] = fini[c]("1")
+    patterns['free'] = free[c]("1")
+    patterns['operation'] = operation[c]("1")
+
+    # Generate the correct code => to remove?
+    replace = patterns
+    replace['shortdesc'] = 'Collective @{c}@ with correct arguments'
+    replace['longdesc'] = f'All ranks in newcom call {c} with correct arguments'
+    replace['outcome'] = 'OK'
+    replace['errormsg'] = ''
+    replace['change_com'] = '/* No error injected here */'
+    make_file(template, f'ParamMatching_Com_{c}_ok.c', replace)
+
+    # Generate the incorrect communicator matching
+    replace = patterns
+    replace['shortdesc'] = 'Collective @{c}@ with a communicator mismatch'
+    replace['longdesc'] = f'Odd ranks call the collective on newcom while even ranks call the collective on MPI_COMM_WORLD'
+    replace['outcome'] = 'ERROR: CommunicatorMatching'
+    replace['errormsg'] = 'Communicator mistmatch in collectives. @{c}@ at @{filename}@:@{line:MBIERROR}@ has newcom or MPI_COMM_WORLD as a communicator.'
+    replace['change_com'] = 'if (rank % 2)\n    newcom = MPI_COMM_WORLD; /* MBIERROR */'
+    make_file(template, f'ParamMatching_Com_{c}_nok.c', replace)
+
+    # Generate the coll with newcom=MPI_COMM_NULL
+    replace = patterns
+    replace['shortdesc'] = f'Collective @{c}@ with newcom=MPI_COMM_NULL'
+    replace['longdesc'] = f'Collective @{c}@ with newcom=MPI_COMM_NULL'
+    replace['outcome'] = 'ERROR: InvalidCommunicator'
+    replace['errormsg'] = 'Invalid communicator. @{c}@ at @{filename}@:@{line:MBIERROR}@ has MPI_COMM_NULL as a communicator.'
+    replace['change_com'] = 'newcom = MPI_COMM_NULL; /* MBIERROR */'
+    make_file(template, f'InvalidParam_ComNull_{c}_nok.c', replace)
diff --git a/teshsuite/smpi/MBI/CollLocalConcurrencyGenerator.py b/teshsuite/smpi/MBI/CollLocalConcurrencyGenerator.py
new file mode 100755 (executable)
index 0000000..4eccf01
--- /dev/null
@@ -0,0 +1,90 @@
+#! /usr/bin/python3
+import os
+import sys
+from generator_utils import *
+
+template = """// @{generatedby}@
+/* ///////////////////////// The MPI Bugs Initiative ////////////////////////
+
+  Origin: MBI
+
+  Description: @{shortdesc}@
+    @{longdesc}@
+
+   Version of MPI: Conforms to MPI 3, requires MPI 3 implementation
+
+BEGIN_MPI_FEATURES
+  P2P!basic: Lacking
+  P2P!nonblocking: Lacking
+  P2P!persistent: Lacking
+  COLL!basic: Lacking
+  COLL!nonblocking: @{icollfeature}@
+  COLL!persistent: @{pcollfeature}@
+  COLL!tools: Lacking
+  RMA: Lacking
+END_MPI_FEATURES
+
+BEGIN_MBI_TESTS
+  $ mpirun -np 2 ${EXE}
+  | @{outcome}@
+  | @{errormsg}@
+END_MBI_TESTS
+//////////////////////       End of MBI headers        /////////////////// */
+
+#include <mpi.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define buff_size 128
+
+int main(int argc, char **argv) {
+  int nprocs = -1;
+  int rank = -1;
+  int root = 0;
+
+  MPI_Init(&argc, &argv);
+  MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+  printf("Hello from rank %d \\n", rank);
+
+  if (nprocs < 2)
+    printf("MBI ERROR: This test needs at least 2 processes to produce a bug!\\n");
+
+  int dbs = sizeof(int)*nprocs; /* Size of the dynamic buffers for alltoall and friends */
+  MPI_Op op = MPI_SUM;
+  MPI_Comm newcom = MPI_COMM_WORLD;
+  MPI_Datatype type = MPI_INT;
+
+  @{init}@
+  @{start}@
+   @{operation}@
+  @{write}@ /* MBIERROR */
+  @{fini}@
+  @{free}@
+
+  MPI_Finalize();
+  printf("Rank %d finished normally\\n", rank);
+  return 0;
+}
+"""
+
+for c in icoll + pcoll:
+    patterns = {}
+    patterns = {'c': c}
+    patterns['generatedby'] = f'DO NOT EDIT: this file was generated by {os.path.basename(sys.argv[0])}. DO NOT EDIT.'
+    patterns['icollfeature'] = 'Yes' if c in icoll else 'Lacking'
+    patterns['pcollfeature'] = 'Yes' if c in pcoll else 'Lacking'
+    patterns['c'] = c
+    patterns['init'] = init[c]("1")
+    patterns['start'] = start[c]("1")
+    patterns['fini'] = fini[c]("1")
+    patterns['operation'] = operation[c]("1")
+    patterns['write'] = write[c]("1")
+    patterns['free'] = free[c]("1")
+
+    replace = patterns
+    replace['shortdesc'] = 'Local concurrency with a collective'
+    replace['longdesc'] = f'The buffer in {c} is modified before the call has been completed.'
+    replace['outcome'] = 'ERROR: LocalConcurrency'
+    replace['errormsg'] = 'Local Concurrency with a collective. The buffer in @{c}@ is modified at @{filename}@:@{line:MBIERROR}@ whereas there is no guarantee the call has been completed.'
+    make_file(template, f'LocalConcurrency_{c}_nok.c', replace)
index 6df18f9..cf4c5bf 100755 (executable)
@@ -3,6 +3,7 @@
 # Copyright 2021-2022. The MBI project. All rights reserved.
 # This program is free software; you can redistribute it and/or modify it under the terms of the license (GNU GPL).
 
+import os
 import sys
 from generator_utils import *
 
@@ -14,17 +15,17 @@ template = """// @{generatedby}@
   Description: @{shortdesc}@
     @{longdesc}@
 
-        Version of MPI: Conforms to MPI 1.1, does not require MPI 2 implementation
+   Version of MPI: Conforms to MPI 1.1, does not require MPI 2 implementation
 
 BEGIN_MPI_FEATURES
-       P2P!basic: Lacking
-       P2P!nonblocking: Lacking
-       P2P!persistent: Lacking
-       COLL!basic: @{collfeature}@
-       COLL!nonblocking: @{icollfeature}@
-       COLL!persistent: Lacking
-       COLL!tools: Lacking
-       RMA: Lacking
+  P2P!basic: Lacking
+  P2P!nonblocking: Lacking
+  P2P!persistent: Lacking
+  COLL!basic: @{collfeature}@
+  COLL!nonblocking: @{icollfeature}@
+  COLL!persistent: Lacking
+  COLL!tools: Lacking
+  RMA: Lacking
 END_MPI_FEATURES
 
 BEGIN_MBI_TESTS
@@ -43,7 +44,7 @@ END_MBI_TESTS
 int main(int argc, char **argv) {
   int nprocs = -1;
   int rank = -1;
-       int root = 0;
+  int root = 0;
 
   MPI_Init(&argc, &argv);
   MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
@@ -53,8 +54,8 @@ int main(int argc, char **argv) {
   if (nprocs < 2)
     printf("MBI ERROR: This test needs at least 2 processes to produce a bug.\\n");
 
-       MPI_Comm newcom = MPI_COMM_WORLD;
-       MPI_Datatype type = MPI_INT;
+  MPI_Comm newcom = MPI_COMM_WORLD;
+  MPI_Datatype type = MPI_INT;
   MPI_Op op = MPI_SUM;
 
   int dbs = sizeof(int)*nprocs; /* Size of the dynamic buffers for alltoall and friends */
@@ -63,19 +64,19 @@ int main(int argc, char **argv) {
 
   if (@{change_cond}@) {
     @{operation1a}@ /* MBIERROR1 */
-       @{fini1a}@
+    @{fini1a}@
     @{operation2a}@
-       @{fini2a}@
+    @{fini2a}@
   } else {
     @{operation1b}@ /* MBIERROR2 */
-       @{fini1b}@
+    @{fini1b}@
     @{operation2b}@
-       @{fini2b}@
+    @{fini2b}@
   }
 
   @{free1}@
   @{free2}@
-  
+
   MPI_Finalize();
   printf("Rank %d finished normally\\n", rank);
   return 0;
@@ -86,7 +87,7 @@ for c1 in coll + icoll + ibarrier:
     for c2 in coll + icoll + ibarrier:
         patterns = {}
         patterns = {'c1': c1, 'c2': c2}
-        patterns['generatedby'] = f'DO NOT EDIT: this file was generated by {sys.argv[0]}. DO NOT EDIT.'
+        patterns['generatedby'] = f'DO NOT EDIT: this file was generated by {os.path.basename(sys.argv[0])}. DO NOT EDIT.'
         patterns['collfeature'] = 'Yes' if c1 in coll or c2 in coll else 'Lacking'
         patterns['icollfeature'] = 'Yes' if c1 in icoll + ibarrier or c2 in icoll + ibarrier else 'Lacking'
         patterns['c1'] = c1
@@ -146,7 +147,7 @@ for c1 in coll + icoll + ibarrier:
             replace['fini2a'] = fini[c2]("2")
             replace['fini1b'] = fini[c2]("2") # Inversion
             replace['fini2b'] = fini[c1]("1")
-            replace['free1'] = free[c2]("2") 
+            replace['free1'] = free[c2]("2")
             replace['free2'] = free[c1]("1")
 
             make_file(template, f'CallOrdering_{c1}_{c2}_nok.c', replace)
diff --git a/teshsuite/smpi/MBI/CollP2PMatchingGenerator.py b/teshsuite/smpi/MBI/CollP2PMatchingGenerator.py
new file mode 100755 (executable)
index 0000000..09e5ff2
--- /dev/null
@@ -0,0 +1,134 @@
+#! /usr/bin/python3
+import os
+import sys
+from generator_utils import *
+
+template = """// @{generatedby}@
+/* ///////////////////////// The MPI Bugs Initiative ////////////////////////
+
+  Origin: MBI
+
+  Description: @{shortdesc}@
+    @{longdesc}@
+
+   Version of MPI: Conforms to MPI 1.1, does not require MPI 2 implementation
+
+BEGIN_MPI_FEATURES
+  P2P!basic: @{p2pfeature}@
+  P2P!nonblocking: @{ip2pfeature}@
+  P2P!persistent: Lacking
+  COLL!basic: @{collfeature}@
+  COLL!nonblocking: Lacking
+  COLL!persistent: Lacking
+  COLL!tools: Lacking
+  RMA: Lacking
+END_MPI_FEATURES
+
+BEGIN_MBI_TESTS
+  $ mpirun -np 2 ${EXE}
+  | @{outcome}@
+  | @{errormsg}@
+END_MBI_TESTS
+//////////////////////       End of MBI headers        /////////////////// */
+
+#include <mpi.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+int main(int argc, char **argv) {
+  int nprocs = -1;
+  int rank = -1;
+  int dest, src;
+  int root = 0;
+  int stag = 0, rtag = 0;
+  int buff_size = 1;
+
+  MPI_Init(&argc, &argv);
+  MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+  printf("Hello from rank %d \\n", rank);
+
+  if (nprocs < 2)
+    printf("MBI ERROR: This test needs at least 2 processes to produce a bug!\\n");
+
+  int dbs = sizeof(int)*nprocs; /* Size of the dynamic buffers for alltoall and friends */
+  MPI_Comm newcom = MPI_COMM_WORLD;
+  MPI_Datatype type = MPI_INT;
+  MPI_Op op = MPI_SUM;
+
+  @{init1}@
+  @{init2}@
+  @{init3}@
+  if (rank == 0) {
+    dest=1;src=1;
+    @{operation3}@ /* MBIERROR1 */
+    @{fini3}@
+    @{operation1}@
+    @{fini1}@
+  }else if (rank==1) {
+    dest=0;src=0;
+    @{operation2}@ /* MBIERROR2 */
+    @{fini2}@
+    @{operation3}@
+    @{fini3}@
+  }
+
+  @{free1}@
+  @{free2}@
+  @{free3}@
+
+  MPI_Finalize();
+  printf("Rank %d finished normally\\n", rank);
+  return 0;
+}
+"""
+
+
+for s in send + isend:
+    for r in recv + irecv:
+        for c in coll:
+            patterns = {}
+            patterns = {'s': s, 'r': r, 'c': c}
+            patterns['generatedby'] = f'DO NOT EDIT: this file was generated by {os.path.basename(sys.argv[0])}. DO NOT EDIT.'
+            patterns['p2pfeature'] = 'Yes' if s in send or r in recv else 'Lacking'
+            patterns['ip2pfeature'] = 'Yes' if s in isend or r in irecv else 'Lacking'
+            patterns['collfeature'] = 'Yes' if c in coll else 'Lacking'
+            patterns['s'] = s
+            patterns['r'] = r
+            patterns['c'] = c
+            patterns['init1'] = init[s]("1")
+            patterns['init2'] = init[r]("2")
+            patterns['init3'] = init[c]("3")
+            patterns['fini1'] = fini[s]("1")
+            patterns['fini2'] = fini[r]("2")
+            patterns['fini3'] = fini[c]("3")
+            patterns['free1'] = free[s]("1")
+            patterns['free2'] = free[r]("2")
+            patterns['free3'] = free[c]("3")
+            patterns['operation1'] = operation[s]("1")
+            patterns['operation2'] = operation[r]("2")
+            patterns['operation3'] = operation[c]("3")
+
+            # Generate the incorrect matching because of the conditional
+            replace = patterns
+            replace['shortdesc'] = 'Point to point & collective mismatch'
+            replace['longdesc'] = 'Point to point @{r}@ is matched with @{c}@ which causes a deadlock.'
+            replace['outcome'] = 'ERROR: CallMatching'
+            replace['errormsg'] = 'P2P & Collective mistmatch. @{r}@ at @{filename}@:@{line:MBIERROR2}@ is matched with @{c}@ at @{filename}@:@{line:MBIERROR1}@ wich causes a deadlock.'
+            make_file(template, f'CallOrdering_{r}_{s}_{c}_nok.c', replace)
+
+            # Generate the incorrect code depending on buffering
+            #  replace = patterns
+            #  replace['shortdesc'] = 'Point to point & collective mismatch'
+            #  replace['longdesc'] = 'Point to point @{s}@ is matched with @{c}@ which causes a deadlock depending on the buffering mode.'
+            #  replace['outcome'] = 'ERROR: BufferingHazard'
+            #  replace['errormsg'] = 'P2P & Collective mistmatch. @{s}@ at @{filename}@:@{line:MBIERROR2}@ is matched with @{c}@ at @{filename}@:@{line:MBIERROR1}@ wich causes a deadlock.'
+            #  replace['init1'] = init[s]("1")
+            #  replace['init2'] = init[r]("2")
+            #  replace['operation1'] = operation[r]("2")
+            #  replace['operation2'] = operation[s]("1")
+            #  replace['fini1'] = fini[r]("2")
+            #  replace['fini2'] = fini[s]("1")
+            #  make_file(template, f'CollP2PBuffering_{r}_{s}_{c}_nok.c', replace)
+
diff --git a/teshsuite/smpi/MBI/CollP2PMessageRaceGenerator.py b/teshsuite/smpi/MBI/CollP2PMessageRaceGenerator.py
new file mode 100755 (executable)
index 0000000..c817f96
--- /dev/null
@@ -0,0 +1,140 @@
+#! /usr/bin/python3
+import os
+import sys
+from generator_utils import *
+
+template = """// @{generatedby}@
+/* ///////////////////////// The MPI Bugs Initiative ////////////////////////
+
+  Origin: MBI
+
+  Description: @{shortdesc}@
+    @{longdesc}@
+
+  Version of MPI: Conforms to MPI 1.1, does not require MPI 2 implementation
+
+BEGIN_MPI_FEATURES
+  P2P!basic: @{p2pfeature}@
+  P2P!nonblocking: @{ip2pfeature}@
+  P2P!persistent: Lacking
+  COLL!basic: @{collfeature}@
+  COLL!nonblocking: Lacking
+  COLL!persistent: Lacking
+  COLL!tools: Lacking
+  RMA: Lacking
+END_MPI_FEATURES
+
+BEGIN_MBI_TESTS
+  $ mpirun -np 4 ${EXE}
+  | @{outcome}@
+  | @{errormsg}@
+END_MBI_TESTS
+//////////////////////       End of MBI headers        /////////////////// */
+
+#include <mpi.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+int main(int argc, char **argv) {
+  int nprocs = -1;
+  int rank = -1;
+  int dest, src;
+  int i=0;
+  int root = 0;
+  int stag = 0, rtag = 0;
+  int buff_size = 1;
+
+  MPI_Init(&argc, &argv);
+  MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+  printf("Hello from rank %d \\n", rank);
+
+  if (nprocs != 4)
+    printf("MBI ERROR: This test needs 4 processes to produce a bug!\\n");
+
+  int dbs = sizeof(int)*nprocs; /* Size of the dynamic buffers for alltoall and friends */
+  MPI_Comm newcom = MPI_COMM_WORLD;
+  MPI_Datatype type = MPI_INT;
+  MPI_Op op = MPI_SUM;
+
+
+  @{init1}@
+  @{init2}@
+  @{init3}@
+  @{init4}@
+  if (rank == 0) {
+    dest=1;
+    @{operation1}@
+    @{fini1}@
+    @{operation2}@
+    @{fini2}@
+  }else if (rank==2) {
+    dest=1;
+    @{operation1}@
+    @{fini1}@
+    @{operation2}@
+    @{fini2}@
+  }else if (rank==1) {
+    src = MPI_ANY_SOURCE;
+    rtag = MPI_ANY_TAG;
+    @{operation3}@ /* MBIERROR1 */
+    @{operation1}@
+    @{fini1}@
+    src = 0;
+    @{operation4}@ /* MBIERROR2 */
+    @{fini3}@
+    @{fini4}@
+  }else if (rank==3) {
+    @{operation1}@
+    @{fini1}@
+  }
+
+  @{free1}@
+  @{free2}@
+  @{free3}@
+  @{free4}@
+
+  MPI_Finalize();
+  printf("Rank %d finished normally\\n", rank);
+  return 0;
+}
+"""
+
+
+for s in send + isend:
+    for r in irecv:
+        for c in coll:
+            patterns = {}
+            patterns = {'s': s, 'r': r, 'c': c}
+            patterns['generatedby'] = f'DO NOT EDIT: this file was generated by {os.path.basename(sys.argv[0])}. DO NOT EDIT.'
+            patterns['p2pfeature'] = 'Yes' if s in send or r in recv else 'Lacking'
+            patterns['ip2pfeature'] = 'Yes' if s in isend or r in irecv else 'Lacking'
+            patterns['collfeature'] = 'Yes' if c in coll else 'Lacking'
+            patterns['s'] = s
+            patterns['r'] = r
+            patterns['c'] = c
+            patterns['init1'] = init[c]("1")
+            patterns['init2'] = init[s]("2")
+            patterns['init3'] = init[r]("3")
+            patterns['init4'] = init[r]("4")
+            patterns['fini1'] = fini[c]("1")
+            patterns['fini2'] = fini[s]("2")
+            patterns['fini3'] = fini[r]("3")
+            patterns['fini4'] = fini[r]("4")
+            patterns['free1'] = free[c]("1")
+            patterns['free2'] = free[s]("2")
+            patterns['free3'] = free[r]("3")
+            patterns['free4'] = free[r]("4")
+            patterns['operation1'] = operation[c]("1")
+            patterns['operation2'] = operation[s]("2")
+            patterns['operation3'] = operation[r]("3")
+            patterns['operation4'] = operation[r]("4")
+
+            # Generate the incorrect matching because of the conditional
+            replace = patterns
+            replace['shortdesc'] = 'Message race'
+            replace['longdesc'] = 'Message race in @{r}@ with @{c}@.'
+            replace['outcome'] = 'ERROR: MessageRace'
+            replace['errormsg'] = 'Message race. The use of wildcard receive calls (@{r}@ at @{filename}@:@{line:MBIERROR1}@ and @{r}@ at @{filename}@:@{line:MBIERROR2}@) leads to nondeterministic matching.'
+            make_file(template, f'MessageRace_{c}_{s}_{r}_nok.c', replace)
diff --git a/teshsuite/smpi/MBI/CollTopoGenerator.py b/teshsuite/smpi/MBI/CollTopoGenerator.py
new file mode 100755 (executable)
index 0000000..4bafe00
--- /dev/null
@@ -0,0 +1,125 @@
+#! /usr/bin/python3
+import os
+import sys
+from generator_utils import *
+
+template = """// @{generatedby}@
+/* ///////////////////////// The MPI Bugs Initiative ////////////////////////
+
+  Origin: MBI
+
+  Description: @{shortdesc}@
+    @{longdesc}@
+
+   Version of MPI: Conforms to MPI 1.1, does not require MPI 2 implementation
+
+BEGIN_MPI_FEATURES
+  P2P!basic: Lacking
+  P2P!nonblocking: Lacking
+  P2P!persistent: Lacking
+  COLL!basic: Lacking
+  COLL!nonblocking: Lacking
+  COLL!persistent: Lacking
+  COLL!tools: @{toolfeature}@
+  RMA: Lacking
+END_MPI_FEATURES
+
+BEGIN_MBI_TESTS
+  $ mpirun -np 2 ${EXE}
+  | @{outcome}@
+  | @{errormsg}@
+END_MBI_TESTS
+//////////////////////       End of MBI headers        /////////////////// */
+
+#include <mpi.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define buff_size 128
+
+int main(int argc, char **argv) {
+  int nprocs = -1;
+  int rank = -1;
+
+  MPI_Init(&argc, &argv);
+  MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+  printf("Hello from rank %d \\n", rank);
+
+  if (nprocs < 2)
+    printf("MBI ERROR: This test needs at least 2 processes to produce a bug!\\n");
+
+   MPI_Comm newcom;
+   int dims[2], periods[2], coords[2];
+   int source, dest;
+   dims[0] = 2;
+   dims[1] = 1;
+   periods[0] = 1;
+   periods[1] = 1;
+
+   @{change_dims}@
+
+   MPI_Cart_create(MPI_COMM_WORLD, 2, dims, periods, 0, &newcom); /* create a cartesian communicator */
+
+   @{change_com}@
+
+   @{init}@
+   @{operation}@ /* MBIERROR2 */
+   @{fini}@
+
+   if (newcom != MPI_COMM_NULL)
+     MPI_Comm_free(&newcom);
+
+  MPI_Finalize();
+  printf("Rank %d finished normally\\n", rank);
+  return 0;
+}
+"""
+
+for c in tcoll4topo:
+    patterns = {}
+    patterns = {'c': c}
+    patterns['generatedby'] = f'DO NOT EDIT: this file was generated by {os.path.basename(sys.argv[0])}. DO NOT EDIT.'
+    patterns['toolfeature'] = 'Yes' if c in tcoll4topo else 'Lacking'
+    patterns['c'] = c
+    patterns['init'] = init[c]("1")
+    patterns['fini'] = fini[c]("1")
+    patterns['operation'] = operation[c]("1")
+
+    # Generate the correct code
+    replace = patterns
+    replace['shortdesc'] = 'Function @{c}@ with correct arguments'
+    replace['longdesc'] = f'All ranks in comm call {c} with correct arguments'
+    replace['outcome'] = 'OK'
+    replace['errormsg'] = ''
+    replace['change_com'] = '/* No error injected here */'
+    replace['change_dims'] = '/* No error injected here */'
+    make_file(template, f'InvalidParam_{c}_ok.c', replace)
+
+    # Generate the incorrect code
+    replace = patterns
+    replace['shortdesc'] = 'The code tries to get cartesian information of MPI_COMM_WORLD.'
+    replace['longdesc'] = 'The code creates a cartesian communicator, and tries to get cartesian information of MPI_COMM_WORLD.'
+    replace['outcome'] = 'ERROR: InvalidCommunicator'
+    replace['errormsg'] = 'Invalid Communicator in a collective. @{c}@ at @{filename}@:@{line:MBIERROR2}@ tries to get cartesian information of MPI_COMM_WORLD.'
+    replace['change_com'] = 'newcom = MPI_COMM_WORLD; /* MBIERROR1 */'
+    make_file(template, f'InvalidParam_Com_{c}_nok.c', replace)
+
+    # Generate the code with newcom=MPI_COMM_NULL
+    replace = patterns
+    replace['shortdesc'] = 'Function @{c}@ called with comm=MPI_COMM_NULL'
+    replace['longdesc'] = 'Function @{c}@ called with comm=MPI_COMM_NULL'
+    replace['outcome'] = 'ERROR: InvalidCommunicator'
+    replace['errormsg'] = 'Invalid communicator. @{c}@ at @{filename}@:@{line:MBIERROR2}@ has MPI_COMM_NULL as a communicator.'
+    replace['change_com'] = 'newcom = MPI_COMM_NULL; /* MBIERROR1 */'
+    make_file(template, f'InvalidParam_ComNull_{c}_nok.c', replace)
+
+    # Generate the code with invalid dimension
+    replace = patterns
+    replace['shortdesc'] = 'Creates a cartesian communicator with a negative entry in the dims attribute'
+    replace['longdesc'] = 'Creates a cartesian communicator with a negative entry in the dims attribute, which is a usage error'
+    replace['outcome'] = 'ERROR: InvalidOtherArg'
+    replace['errormsg'] = 'Invalid Argument. MPI_Cart_create has invalid dimensions.'
+    replace['change_com'] = ""
+    replace['change_dims'] = 'dims[0] = -2; dims[1] = -1; /* MBIERROR1 */'
+    make_file(template, f'InvalidParam_Dim_MPI_Cart_create_nok.c', replace)
index 9c384a4..dd6bd66 100755 (executable)
@@ -1,6 +1,6 @@
 #! /usr/bin/env python3
 
-# Copyright 2021-2022. The SimGrid Team. All rights reserved. 
+# Copyright 2021-2022. 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.
 
index 070d321..43e8789 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright 2021-2022. The MBI project. All rights reserved. 
+# Copyright 2021-2022. The MBI project. All rights reserved.
 # This program is free software; you can redistribute it and/or modify it under the terms of the license (GNU GPL).
 
 import os
@@ -12,14 +12,14 @@ import signal
 import hashlib
 
 class AbstractTool:
-    def ensure_image(self, params=""):
+    def ensure_image(self, params="", dockerparams=""):
         """Verify that this is executed from the right docker image, and complain if not."""
         if os.path.exists("/MBI") or os.path.exists("trust_the_installation"):
             print("This seems to be a MBI docker image. Good.")
         else:
             print("Please run this script in a MBI docker image. Run these commands:")
             print("  docker build -f Dockerfile -t mpi-bugs-initiative:latest . # Only the first time")
-            print(f"  docker run -it --rm --name MIB --volume $(pwd):/MBI mpi-bugs-initiative /MBI/MBI.py {params}")
+            print(f"  docker run -it --rm --name MIB --volume $(pwd):/MBI {dockerparams}mpi-bugs-initiative /MBI/MBI.py {params}")
             sys.exit(1)
 
     def build(self, rootdir, cached=True):
@@ -31,18 +31,18 @@ class AbstractTool:
         Ensure that this tool (previously built) is usable in this environment: setup the PATH, etc.
         This is called only once for all tests, from the logs directory.
         """
-        pass
+        pass
 
-    def run(execcmd, filename, binary, id, timeout):
+    def run(execcmd, filename, binary, num_id, timeout):
         """Compile that test code and anaylse it with the Tool if needed (a cache system should be used)"""
-        pass
+        pass
 
     def teardown(self):
         """
         Clean the results of all test runs: remove temp files and binaries.
         This is called only once for all tests, from the logs directory.
         """
-        pass
+        pass
 
     def parse(self, cachefile):
         """Read the result of a previous run from the cache, and compute the test outcome"""
@@ -52,17 +52,17 @@ class AbstractTool:
 possible_details = {
     # scope limited to one call
     'InvalidBuffer':'AInvalidParam', 'InvalidCommunicator':'AInvalidParam', 'InvalidDatatype':'AInvalidParam', 'InvalidRoot':'AInvalidParam', 'InvalidTag':'AInvalidParam', 'InvalidWindow':'AInvalidParam', 'InvalidOperator':'AInvalidParam', 'InvalidOtherArg':'AInvalidParam', 'ActualDatatype':'AInvalidParam',
-    'InvalidSrcDest':'AInvalidParam', 
+    'InvalidSrcDest':'AInvalidParam',
     # scope: Process-wide
-#    'OutOfInitFini':'BInitFini', 
+#    'OutOfInitFini':'BInitFini',
     'CommunicatorLeak':'BResLeak', 'DatatypeLeak':'BResLeak', 'GroupLeak':'BResLeak', 'OperatorLeak':'BResLeak', 'TypeLeak':'BResLeak', 'RequestLeak':'BResLeak',
     'MissingStart':'BReqLifecycle', 'MissingWait':'BReqLifecycle',
     'LocalConcurrency':'BLocalConcurrency',
     # scope: communicator
-    'CallMatching':'DMatch', 
+    'CallMatching':'DMatch',
     'CommunicatorMatching':'CMatch', 'DatatypeMatching':'CMatch', 'OperatorMatching':'CMatch', 'RootMatching':'CMatch', 'TagMatching':'CMatch',
-    'MessageRace':'DRace', 
-    
+    'MessageRace':'DRace',
+
     'GlobalConcurrency':'DGlobalConcurrency',
     # larger scope
 #    'BufferingHazard':'EBufferingHazard',
@@ -105,10 +105,10 @@ def parse_one_code(filename):
     """
     res = []
     test_num = 0
-    with open(filename, "r") as input:
+    with open(filename, "r") as input_file:
         state = 0  # 0: before header; 1: in header; 2; after header
         line_num = 1
-        for line in input:
+        for line in input_file:
             if re.match(".*BEGIN_MBI_TESTS.*", line):
                 if state == 0:
                     state = 1
@@ -122,7 +122,7 @@ def parse_one_code(filename):
             if state == 1 and re.match("\s+\$ ?.*", line):
                 m = re.match('\s+\$ ?(.*)', line)
                 cmd = m.group(1)
-                nextline = next(input)
+                nextline = next(input_file)
                 detail = 'OK'
                 if re.match('[ |]*OK *', nextline):
                     expect = 'OK'
@@ -169,7 +169,7 @@ def categorize(tool, toolname, test_id, expected):
             diagnostic = f'hard timeout'
         else:
             diagnostic = f'timeout after {elapsed} sec'
-    elif outcome == 'failure':
+    elif outcome == 'failure' or outcome == 'segfault':
         res_category = 'failure'
         diagnostic = f'tool error, or test not run'
     elif outcome == 'UNIMPLEMENTED':
@@ -201,11 +201,11 @@ def categorize(tool, toolname, test_id, expected):
 def run_cmd(buildcmd, execcmd, cachefile, filename, binary, timeout, batchinfo, read_line_lambda=None):
     """
     Runs the test on need. Returns True if the test was ran, and False if it was cached.
-    
+
     The result is cached if possible, and the test is rerun only if the `test.txt` (containing the tool output) or the `test.elapsed` (containing the timing info) do not exist, or if `test.md5sum` (containing the md5sum of the code to compile) does not match.
 
     Parameters:
-     - buildcmd and execcmd are shell commands to run. buildcmd can be any shell line (incuding && groups), but execcmd must be a single binary to run. 
+     - buildcmd and execcmd are shell commands to run. buildcmd can be any shell line (incuding && groups), but execcmd must be a single binary to run.
      - cachefile is the name of the test
      - filename is the source file containing the code
      - binary the file name in which to compile the code
@@ -224,13 +224,12 @@ def run_cmd(buildcmd, execcmd, cachefile, filename, binary, timeout, batchinfo,
         if olddigest == newdigest:
             print(f" (result cached -- digest: {olddigest})")
             return False
-        else:
-            os.remove(f'{cachefile}.txt')
+        os.remove(f'{cachefile}.txt')
 
     print(f"Wait up to {timeout} seconds")
 
     start_time = time.time()
-    if buildcmd == None:
+    if buildcmd is None:
         output = f"No need to compile {binary}.c (batchinfo:{batchinfo})\n\n"
     else:
         output = f"Compiling {binary}.c (batchinfo:{batchinfo})\n\n"
@@ -319,5 +318,5 @@ def run_cmd(buildcmd, execcmd, cachefile, filename, binary, timeout, batchinfo,
             for chunk in iter(lambda: sourcefile.read(4096), b""):
                 hashed.update(chunk)
         outfile.write(hashed.hexdigest())
-    
+
     return True
diff --git a/teshsuite/smpi/MBI/MissingWaitandStartGenerator.py b/teshsuite/smpi/MBI/MissingWaitandStartGenerator.py
new file mode 100755 (executable)
index 0000000..54d4384
--- /dev/null
@@ -0,0 +1,200 @@
+#! /usr/bin/python3
+import os
+import sys
+from generator_utils import *
+
+template = """// @{generatedby}@
+/* ///////////////////////// The MPI Bugs Initiative ////////////////////////
+
+  Origin: MBI
+
+  Description: @{shortdesc}@
+    @{longdesc}@
+
+   Version of MPI: Conforms to MPI 1.1, does not require MPI 2 implementation
+
+BEGIN_MPI_FEATURES
+  P2P!basic: Lacking
+  P2P!nonblocking: @{ip2pfeature}@
+  P2P!persistent: @{persfeature}@
+  COLL!basic: Lacking
+  COLL!nonblocking: @{icollfeature}@
+  COLL!persistent: @{cpersfeature}@
+  COLL!tools: Lacking
+  RMA: Lacking
+END_MPI_FEATURES
+
+BEGIN_MBI_TESTS
+  $ mpirun -np 2 ${EXE}
+  | @{outcome}@
+  | @{errormsg}@
+END_MBI_TESTS
+//////////////////////       End of MBI headers        /////////////////// */
+
+#include <mpi.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+int main(int argc, char **argv) {
+  int nprocs = -1;
+  int rank = -1;
+  int root = 0;
+
+  MPI_Init(&argc, &argv);
+  MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+  printf("Hello from rank %d \\n", rank);
+
+  if (nprocs < 2)
+    printf("MBI ERROR: This test needs at least 2 processes to produce a bug!\\n");
+
+  MPI_Comm newcom = MPI_COMM_WORLD;
+  MPI_Datatype type = MPI_INT;
+  MPI_Op op = MPI_SUM;
+  int stag = 0, rtag = 0;
+  int buff_size = 1;
+
+  int dbs = sizeof(int)*nprocs; /* Size of the dynamic buffers for alltoall and friends */
+
+  int dest = (rank == nprocs - 1) ? (0) : (rank + 1);
+  int src = (rank == 0) ? (nprocs - 1) : (rank - 1);
+
+  @{init1}@
+  @{init2}@
+
+  @{operation1}@ /* MBIERROR */
+  @{start1}@
+  @{operation2}@
+  @{start2}@
+
+  @{fini1}@
+  @{fini2}@
+
+  @{free1}@
+  @{free2}@
+
+  MPI_Finalize();
+  printf("Rank %d finished normally\\n", rank);
+  return 0;
+}
+"""
+
+
+for s in isend + psend:
+    for r in irecv + precv:
+        patterns = {}
+        patterns = {'s': s, 'r': r}
+        patterns['generatedby'] = f'DO NOT EDIT: this file was generated by {os.path.basename(sys.argv[0])}. DO NOT EDIT.'
+        patterns['persfeature'] = 'Yes' if s in psend or r in precv  else 'Lacking'
+        patterns['ip2pfeature'] = 'Yes' if s in isend or r in irecv  else 'Lacking'
+        patterns['icollfeature'] = 'Lacking'
+        patterns['cpersfeature'] = 'Lacking'
+        patterns['s'] = s
+        patterns['r'] = r
+        patterns['init1'] = init[s]("1")
+        patterns['init2'] = init[r]("2")
+        patterns['start1'] = start[s]("1")
+        startPers = patterns['start1']
+        patterns['start2'] = start[r]("2")
+        patterns['operation1'] = operation[s]("1")
+        patterns['operation2'] = operation[r]("2")
+        patterns['fini1'] = fini[s]("1")
+        wait = patterns['fini1']
+        patterns['fini2'] = fini[r]("2")
+        patterns['free1'] = free[s]("1")
+        Reqfree = patterns['free1']
+        patterns['free2'] = free[r]("2")
+
+        # Generate the correct code
+        replace = patterns
+        replace['shortdesc'] = 'Correct matching'
+        replace['longdesc'] = f'No error'
+        replace['outcome'] = 'OK'
+        replace['errormsg'] = 'OK'
+        make_file(template, f'ReqLifecycle_{s}_{r}_ok.c', replace)
+
+        # Generate the code with a missing wait
+        replace = patterns
+        replace['shortdesc'] = 'Missing wait'
+        replace['longdesc'] = 'Missing Wait. @{s}@ at @{filename}@:@{line:MBIERROR}@ has no completion.'
+        replace['outcome'] = 'ERROR: MissingWait'
+        replace['errormsg'] = 'ERROR: MissingWait'
+        replace['fini1'] =  ' /* MBIERROR MISSING: ' + wait + ' */'
+        make_file(template, f'ReqLifecycle_MissingWait_{s}_{r}_nok.c', replace)
+
+        if s in psend:
+            # Generate the code with a missing start - persistent only
+            replace = patterns
+            replace['shortdesc'] = 'Missing start'
+            replace['longdesc'] = 'Missing start. @{s}@ at @{filename}@:@{line:MBIERROR}@ has no start'
+            replace['outcome'] = 'ERROR: MissingStart'
+            replace['errormsg'] = 'ERROR: MissingStart'
+            replace['fini1'] = fini[s]("1")
+            replace['start1'] = ' /* MBIERROR MISSING: ' + startPers + ' */'
+            make_file(template, f'ReqLifecycle_MissingStart_{s}_{r}_nok.c', replace)
+            # Generate the code with a missing free - persistent only
+            replace = patterns
+            replace['shortdesc'] = 'Missing free'
+            replace['longdesc'] = 'Missing free. @{s}@ at @{filename}@:@{line:MBIERROR}@ has no free'
+            replace['outcome'] = 'ERROR: RequestLeak'
+            replace['errormsg'] = 'ERROR: RequestLeak'
+            replace['start1'] = start[s]("1")
+            replace['free1'] = ' /* MBIERROR MISSING: ' + Reqfree + ' */'
+            make_file(template, f'ResLeak_nofree_{s}_{r}_nok.c', replace)
+
+
+# Collectives only
+for c in pcoll + icoll + ibarrier:
+    patterns = {}
+    patterns = {'c': c}
+    patterns['generatedby'] = f'DO NOT EDIT: this file was generated by {os.path.basename(sys.argv[0])}. DO NOT EDIT.'
+    patterns['persfeature'] = 'Lacking'
+    patterns['ip2pfeature'] = 'Lacking'
+    patterns['cpersfeature'] = 'Yes' if c in pcoll else 'Lacking'
+    patterns['icollfeature'] = 'Yes' if c in icoll + ibarrier else 'Lacking'
+    patterns['c'] = c
+    patterns['init1'] = init[c]("1")
+    patterns['operation1'] = operation[c]("1")
+    patterns['start1'] = start[c]("1")
+    patterns['fini1'] = fini[c]("1")
+    patterns['free1'] = free[c]("1")
+    opstart = patterns['start1']
+    opwait = patterns['fini1']
+    opfree = patterns['free1']
+    patterns['init2'] = ""
+    patterns['operation2'] = ""
+    patterns['start2'] = ""
+    patterns['fini2'] = ""
+    patterns['free2'] = ""
+
+    # Generate the code with a missing wait
+    replace = patterns
+    replace['shortdesc'] = 'Missing wait'
+    replace['longdesc'] = 'Missing Wait. @{c}@ at @{filename}@:@{line:MBIERROR}@ has no completion'
+    replace['outcome'] = 'ERROR: MissingWait'
+    replace['errormsg'] = 'ERROR: MissingWait'
+    replace['fini1'] = ' /* MBIERROR MISSING: ' + opwait + ' */'
+    replace['free1'] = ' /* MISSING: ' + replace['free1'] + ' (to not free the buffer before an internal wait */'
+    make_file(template, f'ReqLifecycle_MissingWait_{c}_nok.c', replace)
+
+    if c in pcoll:
+        # Generate the code with a missing start - persistent only
+        replace = patterns
+        replace['shortdesc'] = 'Missing start functio'
+        replace['longdesc'] = 'Missing Start. @{c}@ at @{filename}@:@{line:MBIERROR}@ has no start'
+        replace['outcome'] = 'ERROR: MissingStart'
+        replace['errormsg'] = 'ERROR: MissingStart'
+        replace['fini1'] = fini[c]("1")
+        replace['start1'] = ' /* MBIERROR MISSING: ' + opstart + ' */'
+        make_file(template, f'ReqLifecycle_MissingStart_{c}_nok.c', replace)
+
+        # Generate the code with a resleak (no free) - persistent only
+        replace = patterns
+        replace['shortdesc'] = 'Missing free'
+        replace['longdesc'] = 'Missing free. @{c}@ at @{filename}@:@{line:MBIERROR}@ has no free'
+        replace['outcome'] = 'ERROR: RequestLeak'
+        replace['errormsg'] = 'ERROR: RequestLeak'
+        replace['start1'] = start[c]("1")
+        replace['free1'] = ' /* MBIERROR MISSING: ' + opfree + ' */'
+        make_file(template, f'ResLeak_nofree_{c}_nok.c', replace)
diff --git a/teshsuite/smpi/MBI/P2PArgGenerator.py b/teshsuite/smpi/MBI/P2PArgGenerator.py
new file mode 100755 (executable)
index 0000000..ca790d5
--- /dev/null
@@ -0,0 +1,182 @@
+#! /usr/bin/python3
+import os
+import sys
+from generator_utils import *
+
+template = """// @{generatedby}@
+/* ///////////////////////// The MPI Bugs Initiative ////////////////////////
+
+  Origin: MBI
+
+  Description: @{shortdesc}@
+    @{longdesc}@
+
+   Version of MPI: Conforms to MPI 1.1, does not require MPI 2 implementation
+
+BEGIN_MPI_FEATURES
+  P2P!basic: @{p2pfeature}@
+  P2P!nonblocking: @{ip2pfeature}@
+  P2P!persistent: @{persfeature}@
+  COLL!basic: Lacking
+  COLL!nonblocking: Lacking
+  COLL!persistent: Lacking
+  COLL!tools: Lacking
+  RMA: Lacking
+END_MPI_FEATURES
+
+BEGIN_MBI_TESTS
+  $ mpirun -np 2 ${EXE}
+  | @{outcome}@
+  | @{errormsg}@
+END_MBI_TESTS
+//////////////////////       End of MBI headers        /////////////////// */
+
+#include <mpi.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+int main(int argc, char **argv) {
+  int nprocs = -1;
+  int rank = -1;
+  int src=0, dest=1;
+  int stag=0, rtag=0;
+  int buff_size = 1;
+
+  MPI_Init(&argc, &argv);
+  MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+  printf("Hello from rank %d \\n", rank);
+
+  if (nprocs < 2)
+    printf("MBI ERROR: This test needs at least 2 processes to produce a bug!\\n");
+
+  MPI_Comm newcom = MPI_COMM_WORLD;
+  MPI_Datatype type = MPI_INT;
+
+  @{change_arg}@
+
+  @{init1}@
+  @{init2}@
+  if (rank == 0) {
+    @{operation1}@ /* MBIERROR1 */
+    @{start1}@
+    @{fini1}@
+  }else if (rank == 1) {
+    @{operation2}@ /* MBIERROR2 */
+    @{start2}@
+    @{fini2}@
+  }
+  @{free1}@
+  @{free2}@
+
+  MPI_Finalize();
+  printf("Rank %d finished normally\\n", rank);
+  return 0;
+}
+"""
+
+##################################
+# Generate code with type mismatch
+##################################
+
+for p1 in allsend:
+    for p2 in allrecv:
+        patterns = {}
+        patterns = {'p1': p1, 'p2': p2}
+        patterns['generatedby'] = f'DO NOT EDIT: this file was generated by {os.path.basename(sys.argv[0])}. DO NOT EDIT.'
+        patterns['p2pfeature'] = 'Yes' if p1 in send + ssend + bsend or p2 in recv  else 'Lacking'
+        patterns['ip2pfeature'] = 'Yes' if p1 in isend or p2 in irecv  else 'Lacking'
+        patterns['persfeature'] = 'Yes' if p1 in psend or p2 in precv  else 'Lacking'
+        patterns['p1'] = p1
+        patterns['p2'] = p2
+        patterns['init1'] = init[p1]("1")
+        patterns['init2'] = init[p2]("2")
+        patterns['start1'] = start[p1]("1")
+        patterns['start2'] = start[p2]("2")
+        patterns['fini1'] = fini[p1]("1")
+        patterns['fini2'] = fini[p2]("2")
+        patterns['operation1'] = operation[p1]("1") #send
+        patterns['operation2'] = operation[p2]("2") #recv
+        patterns['free1'] = free[p1]("1")
+        patterns['free2'] = free[p2]("2")
+
+        # Generate the incorrect matching
+        replace = patterns
+        replace['shortdesc'] = 'Point to point @{p1}@ and @{p2}@ have a datatype mismatch'
+        replace['longdesc'] = 'Process 0 uses MPI_FLOAT as the datatype while process 1 uses MPI_INT.'
+        replace['outcome'] = 'ERROR: DatatypeMatching'
+        replace['errormsg'] = 'P2P Datatype mismatch. @{p1}@ at @{filename}@:@{line:MBIERROR1}@ and @{p2}@ at @{filename}@:@{line:MBIERROR2}@ have MPI_INT and MPI_FLOAT as a datatype'
+        replace['change_arg'] = 'if (rank == 0)\n    type = MPI_FLOAT; /* MBIERROR3 */'
+        make_file(template, f'ParamMatching_Data_{p1}_{p2}_nok.c', replace)
+
+        # Generate code with a null type
+        replace = patterns
+        replace['shortdesc'] = 'Use of invalid datatype in point-to-point communication'
+        replace['longdesc'] = 'Point to point @{p1}@ and @{p2}@ have MPI_DATATYPE_NULL as a type'
+        replace['outcome'] = 'ERROR: InvalidDatatype'
+        replace['errormsg'] = 'Invalid datatype in P2P. @{p1}@ at @{filename}@:@{line:MBIERROR1}@ and @{p2}@ at @{filename}@:@{line:MBIERROR2}@ have MPI_DATATYPE_NULL as a type'
+        replace['change_arg'] = 'type = MPI_DATATYPE_NULL; /* MBIERROR3 */'
+        make_file(template, f'InvalidParam_DatatypeNull_{p1}_{p2}_nok.c', replace)
+
+        # Generate code with an invalid datatype
+        replace = patterns
+        replace['shortdesc'] = 'Use of invalid datatype in point-to-point communication'
+        replace['longdesc'] = 'Point to point @{p1}@ and @{p2}@ have an invalid datatype'
+        replace['outcome'] = 'ERROR: InvalidDatatype'
+        replace['errormsg'] = 'Invalid datatype in P2P. @{p1}@ at @{filename}@:@{line:MBIERROR1}@ and @{p2}@ at @{filename}@:@{line:MBIERROR2}@ have an invalid datatype'
+        replace['change_arg'] = 'MPI_Type_contiguous (2, MPI_INT, &type); MPI_Type_commit(&type);MPI_Type_free(&type); /* MBIERROR3 */'
+        make_file(template, f'InvalidParam_Datatype_{p1}_{p2}_nok.c', replace)
+
+#################################
+# Generate code with tag mismatch
+#################################
+
+for p1 in allsend:
+    for p2 in allrecv:
+        patterns = {}
+        patterns = {'p1': p1, 'p2': p2}
+        patterns['generatedby'] = f'DO NOT EDIT: this file was generated by {os.path.basename(sys.argv[0])}. DO NOT EDIT.'
+        patterns['p2pfeature'] = 'Yes' if p1 in send + ssend + bsend or p2 in recv  else 'Lacking'
+        patterns['ip2pfeature'] = 'Yes' if p1 in isend or p2 in irecv  else 'Lacking'
+        patterns['persfeature'] = 'Yes' if p1 in psend or p2 in precv  else 'Lacking'
+        patterns['p1'] = p1
+        patterns['p2'] = p2
+        patterns['init1'] = init[p1]("1")
+        patterns['init2'] = init[p2]("2")
+        patterns['start1'] = start[p1]("1")
+        patterns['start2'] = start[p2]("2")
+        patterns['fini1'] = fini[p1]("1")
+        patterns['fini2'] = fini[p2]("2")
+        patterns['operation1'] = operation[p1]("1") #send
+        patterns['operation2'] = operation[p2]("2") #recv
+        patterns['free1'] = free[p1]("1")
+        patterns['free2'] = free[p2]("2")
+        patterns['change_arg'] = ""
+
+        # Generate the incorrect tag matching
+        replace = patterns
+        replace['shortdesc'] = 'Point to point @{p1}@ and @{p2}@ have a tag mismatch'
+        replace['longdesc'] = 'Point to point @{p1}@ and @{p2}@ have a tag mismatch.'
+        replace['outcome'] = 'ERROR: TagMatching'
+        replace['errormsg'] = 'P2P tag mismatch. @{p1}@ at @{filename}@:@{line:MBIERROR1}@ and @{p2}@ at @{filename}@:@{line:MBIERROR2}@ use different tag.'
+        replace['change_arg'] = 'stag=0; rtag=1;/* MBIERROR */'
+        make_file(template, f'ParamMatching_Tag_{p1}_{p2}_nok.c', replace)
+
+        # Generate the code with an invalid tag
+        replace = patterns
+        replace['shortdesc'] = 'Point to point @{p1}@ and @{p2}@ have an invalid tag'
+        replace['longdesc'] = 'Point to point @{p1}@ and @{p2}@ have an invalid tag.'
+        replace['outcome'] = 'ERROR: InvalidTag'
+        replace['errormsg'] = 'Invalid Tag. @{p1}@ at @{filename}@:@{line:MBIERROR1}@ and @{p2}@ at @{filename}@:@{line:MBIERROR2}@ use an invalid tag.'
+        replace['change_arg'] = 'stag=-1; rtag=-2;/* MBIERROR */'
+        make_file(template, f'InvalidParam_Tag_{p1}_{p2}_nok.c', replace)
+
+        # Generate a correct code using MPI_ANY_TAG
+        replace = patterns
+        replace['shortdesc'] = 'Correct code'
+        replace['longdesc'] = 'Correct code'
+        replace['outcome'] = 'OK'
+        replace['errormsg'] = 'OK'
+        replace['change_arg'] = 'rtag=MPI_ANY_TAG;'
+        make_file(template, f'ParamMatching_Tag_{p1}_{p2}_ok.c', replace)
diff --git a/teshsuite/smpi/MBI/P2PComGenerator.py b/teshsuite/smpi/MBI/P2PComGenerator.py
new file mode 100755 (executable)
index 0000000..1179650
--- /dev/null
@@ -0,0 +1,153 @@
+#! /usr/bin/python3
+import os
+import sys
+from generator_utils import *
+
+template = """// @{generatedby}@
+/* ///////////////////////// The MPI Bugs Initiative ////////////////////////
+
+  Origin: @{origin}@
+
+  Description: @{shortdesc}@
+    @{longdesc}@
+
+   Version of MPI: Conforms to MPI 1.1, does not require MPI 2 implementation
+
+BEGIN_MPI_FEATURES
+  P2P!basic: @{p2pfeature}@
+  P2P!nonblocking: @{ip2pfeature}@
+  P2P!persistent: @{persfeature}@
+  COLL!basic: Lacking
+  COLL!nonblocking: Lacking
+  COLL!persistent: Lacking
+  COLL!tools: Yes
+  RMA: Lacking
+END_MPI_FEATURES
+
+BEGIN_MBI_TESTS
+  $ mpirun -np 2 ${EXE}
+  | @{outcome}@
+  | @{errormsg}@
+END_MBI_TESTS
+//////////////////////       End of MBI headers        /////////////////// */
+
+#include <mpi.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+int main(int argc, char **argv) {
+  int nprocs = -1;
+  int rank = -1;
+  int src=0, dest=1;
+  int stag = 0, rtag = 0;
+  int buff_size = 1;
+
+  MPI_Init(&argc, &argv);
+  MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+  printf("Hello from rank %d \\n", rank);
+
+  if (nprocs < 2)
+    printf("MBI ERROR: This test needs at least 2 processes to produce a bug!\\n");
+
+  MPI_Datatype type = MPI_INT;
+  MPI_Comm newcom;
+  MPI_Comm_split(MPI_COMM_WORLD, 0, nprocs - rank, &newcom);
+  @{change_com}@
+  @{change_srcdest}@
+
+  @{init1}@
+  @{init2}@
+  if (rank == 0) {
+    @{operation1}@ /* MBIERROR1 */
+    @{start1}@
+    @{fini1}@
+  }else if (rank == 1) {
+    @{operation2}@ /* MBIERROR2 */
+    @{start2}@
+    @{fini2}@
+  }
+  @{free1}@
+  @{free2}@
+
+  if(newcom != MPI_COMM_NULL && newcom != MPI_COMM_WORLD)
+    MPI_Comm_free(&newcom);
+
+  MPI_Finalize();
+  printf("Rank %d finished normally\\n", rank);
+  return 0;
+}
+"""
+
+
+for p1 in send + isend + psend:
+    for p2 in recv + irecv + precv:
+        patterns = {}
+        patterns = {'p1': p1, 'p2': p2}
+        patterns['origin'] = "MBI"
+        patterns['generatedby'] = f'DO NOT EDIT: this file was generated by {os.path.basename(sys.argv[0])}. DO NOT EDIT.'
+        patterns['p2pfeature'] = 'Yes' if p1 in send or p2 in recv  else 'Lacking'
+        patterns['ip2pfeature'] = 'Yes' if p1 in isend or p2 in irecv  else 'Lacking'
+        patterns['persfeature'] = 'Yes' if p1 in psend or p2 in precv  else 'Lacking'
+        patterns['p1'] = p1
+        patterns['p2'] = p2
+        patterns['init1'] = init[p1]("1")
+        patterns['init2'] = init[p2]("2")
+        patterns['start1'] = start[p1]("1")
+        patterns['start2'] = start[p2]("2")
+        patterns['fini1'] = fini[p1]("1")
+        patterns['fini2'] = fini[p2]("2")
+        patterns['operation1'] = operation[p1]("1") #send
+        patterns['operation2'] = operation[p2]("2") #recv
+        patterns['free1'] = free[p1]("1")
+        patterns['free2'] = free[p2]("2")
+        patterns['change_srcdest'] = ""
+
+        # Generate the incorrect matching
+        replace = patterns
+        replace['shortdesc'] = 'Point to point @{p1}@ and @{p2}@ have a communicator mismatch'
+        replace['longdesc'] = 'Process 1 uses newcom as the communicator while process 0 uses MPI_COMM_WORLD.'
+        replace['outcome'] = 'ERROR: CommunicatorMatching'
+        replace['errormsg'] = 'P2P Communicator mismatch. @{p1}@ at @{filename}@:@{line:MBIERROR1}@ and @{p2}@ at @{filename}@:@{line:MBIERROR2}@ have newcom or MPI_COMM_WORLD as a communicator.'
+        replace['change_com'] = 'if (rank==0)\n    newcom = MPI_COMM_WORLD; /* MBIERROR */'
+        make_file(template, f'ParamMatching_Com_{p1}_{p2}_nok.c', replace)
+
+        # Generate the code with an invalid communicator
+        replace = patterns
+        replace['shortdesc'] = 'Point to point @{p1}@ and @{p2}@ have an invalid communicator'
+        replace['longdesc'] = 'Point to point @{p1}@ and @{p2}@ have an invalid communicator.'
+        replace['outcome'] = 'ERROR: InvalidCommunicator'
+        replace['errormsg'] = 'Invalid Communicator. @{p1}@ at @{filename}@:@{line:MBIERROR1}@ and @{p2}@ at @{filename}@:@{line:MBIERROR2}@ use a communicator that is freed line @{line:MBIERROR}@.'
+        replace['change_com'] = 'MPI_Comm_free(&newcom);  /* MBIERROR */'
+        make_file(template, f'InvalidParam_Com_{p1}_{p2}_nok.c', replace)
+
+        #  Generate the code with an invalid communicator ==> TO CHECK
+        #replace = patterns
+        #replace['shortdesc'] = 'Point to point @{p1}@ and @{p2}@ have an invalid communicator'
+       # replace['longdesc'] = 'Point to point @{p1}@ and @{p2}@ have an invalid communicator.'
+       # replace['outcome'] = 'ERROR: InvalidCommunicator'
+       # replace['errormsg'] = 'Invalid Communicator. @{p1}@ at @{filename}@:@{line:MBIERROR1}@ and @{p2}@ at @{filename}@:@{line:MBIERROR2}@ use different communicators'
+       # replace['origin'] = "MPI-Corrbench"
+       # replace['change_com'] = ""
+       # make_file(template, f'InvalidParam_Com_{p1}_{p2}_nok.c', replace)
+
+        # Generate the code with an invalid dest
+        replace = patterns
+        replace['origin'] = "MBI"
+        replace['shortdesc'] = 'Point to point @{p1}@ has an invalid argument'
+        replace['longdesc'] = 'Point to point @{p1}@ and @{p2}@ have an invalid communicator.'
+        replace['outcome'] = 'ERROR: InvalidSrcDest'
+        replace['errormsg'] = 'InvalidSrcDest. @{p1}@ at @{filename}@:@{line:MBIERROR1}@ performs a send with a dest not in communicator (dest is changed line @{line:MBIERROR}@).'
+        replace['change_com'] = ""
+        replace['change_srcdest'] = 'dest=4; /* MBIERROR */'
+        make_file(template, f'InvalidParam_Dest_{p1}_{p2}_nok.c', replace)
+
+        # Generate the code with an invalid src
+        replace = patterns
+        replace['shortdesc'] = 'Point to point @{p2}@ has an invalid argument'
+        replace['longdesc'] = 'Point to point @{p1}@ and @{p2}@ have an invalid communicator.'
+        replace['outcome'] = 'ERROR: InvalidSrcDest'
+        replace['errormsg'] = 'InvalidSrcDest. @{p2}@ at @{filename}@:@{line:MBIERROR2}@ performs a recv with a negative integer as source (src is changed line @{line:MBIERROR}@).'
+        replace['change_srcdest'] = 'src=-1; /* MBIERROR */'
+        make_file(template, f'InvalidParam_Src_{p1}_{p2}_nok.c', replace)
diff --git a/teshsuite/smpi/MBI/P2PInvalidComGenerator.py b/teshsuite/smpi/MBI/P2PInvalidComGenerator.py
new file mode 100755 (executable)
index 0000000..ff8453e
--- /dev/null
@@ -0,0 +1,121 @@
+#! /usr/bin/python3
+import os
+import sys
+from generator_utils import *
+
+template = """// @{generatedby}@
+/* ///////////////////////// The MPI Bugs Initiative ////////////////////////
+
+  Origin: @{origin}@
+
+  Description: @{shortdesc}@
+    @{longdesc}@
+
+   Version of MPI: Conforms to MPI 1.1, does not require MPI 2 implementation
+
+BEGIN_MPI_FEATURES
+  P2P!basic: @{p2pfeature}@
+  P2P!nonblocking: @{ip2pfeature}@
+  P2P!persistent: @{persfeature}@
+  COLL!basic: Lacking
+  COLL!nonblocking: Lacking
+  COLL!persistent: Lacking
+  COLL!tools: Yes
+  RMA: Lacking
+END_MPI_FEATURES
+
+BEGIN_MBI_TESTS
+  $ mpirun -np 2 ${EXE}
+  | @{outcome}@
+  | @{errormsg}@
+END_MBI_TESTS
+//////////////////////       End of MBI headers        /////////////////// */
+
+#include <mpi.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+int main(int argc, char **argv) {
+  int nprocs = -1;
+  int rank = -1;
+  int src=0, dest=1;
+  int stag = 0, rtag = 0;
+  int buff_size = 1;
+
+  MPI_Init(&argc, &argv);
+  MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+  printf("Hello from rank %d \\n", rank);
+
+  MPI_Datatype type = MPI_INT;
+  MPI_Comm newcom = MPI_COMM_WORLD;
+
+  @{init1}@
+  @{init2}@
+  if (rank == 0) {
+    @{change_com1}@
+    @{operation1}@ /* MBIERROR1 */
+    @{start1}@
+    @{fini1}@
+  }else if (rank == 1) {
+    @{change_com2}@
+    @{operation2}@ /* MBIERROR2 */
+    @{start2}@
+    @{fini2}@
+  }
+  @{free1}@
+  @{free2}@
+
+  if(newcom != MPI_COMM_NULL && newcom != MPI_COMM_WORLD)
+    MPI_Comm_free(&newcom);
+
+  MPI_Finalize();
+  printf("Rank %d finished normally\\n", rank);
+  return 0;
+}
+"""
+
+
+for p1 in send + isend + psend:
+    for p2 in recv + irecv + precv:
+        patterns = {}
+        patterns = {'p1': p1, 'p2': p2}
+        patterns['origin'] = "MBI"
+        patterns['generatedby'] = f'DO NOT EDIT: this file was generated by {os.path.basename(sys.argv[0])}. DO NOT EDIT.'
+        patterns['p2pfeature'] = 'Yes' if p1 in send or p2 in recv  else 'Lacking'
+        patterns['ip2pfeature'] = 'Yes' if p1 in isend or p2 in irecv  else 'Lacking'
+        patterns['persfeature'] = 'Yes' if p1 in psend or p2 in precv  else 'Lacking'
+        patterns['p1'] = p1
+        patterns['p2'] = p2
+        patterns['init1'] = init[p1]("1")
+        patterns['init2'] = init[p2]("2")
+        patterns['start1'] = start[p1]("1")
+        patterns['start2'] = start[p2]("2")
+        patterns['fini1'] = fini[p1]("1")
+        patterns['fini2'] = fini[p2]("2")
+        patterns['operation1'] = operation[p1]("1") #send
+        patterns['operation2'] = operation[p2]("2") #recv
+        patterns['free1'] = free[p1]("1")
+        patterns['free2'] = free[p2]("2")
+        patterns['change_com1'] = ""
+        patterns['change_com2'] = ""
+
+        replace = patterns
+        replace['origin'] = "inspired from MPI-Corrbench"
+        replace['shortdesc'] = 'Point to point @{p2}@ has an invalid communicator'
+        replace['longdesc'] = 'MPI_COMM_NULL used in point to point @{p2}@'
+        replace['outcome'] = 'ERROR: InvalidCommunicator'
+        replace['errormsg'] = 'Invalid Communicator. @{p2}@ at @{filename}@:@{line:MBIERROR2}@ uses a null communicator.'
+        replace['change_com2'] = 'newcom = MPI_COMM_NULL;'
+        make_file(template, f'InvalidParam_ComNull_{p2}_{p1}nok.c', replace)
+
+        replace = patterns
+        replace['shortdesc'] = 'Point to point @{p2}@ has an invalid communicator'
+        replace['longdesc'] = 'MPI_COMM_NULL used in point to point @{p2}@'
+        replace['outcome'] = 'ERROR: InvalidCommunicator'
+        replace['errormsg'] = 'Invalid Communicator. @{p1}@ at @{filename}@:@{line:MBIERROR1}@ uses a null communicator.'
+        replace['change_com1'] = 'newcom = MPI_COMM_NULL;'
+        replace['change_com2'] = ""
+        make_file(template, f'InvalidParam_ComNull_{p1}_{p2}nok.c', replace)
+
diff --git a/teshsuite/smpi/MBI/P2PLocalConcurrencyGenerator.py b/teshsuite/smpi/MBI/P2PLocalConcurrencyGenerator.py
new file mode 100755 (executable)
index 0000000..460a65f
--- /dev/null
@@ -0,0 +1,126 @@
+#! /usr/bin/python3
+import os
+import sys
+from generator_utils import *
+
+template = """// @{generatedby}@
+/* ///////////////////////// The MPI Bugs Initiative ////////////////////////
+
+  Origin: MBI
+
+  Description: @{shortdesc}@
+    @{longdesc}@
+
+   Version of MPI: Conforms to MPI 1.1, does not require MPI 2 implementation
+
+BEGIN_MPI_FEATURES
+  P2P!basic: @{p2pfeature}@
+  P2P!nonblocking: @{ip2pfeature}@
+  P2P!persistent: @{persfeature}@
+  COLL!basic: Lacking
+  COLL!nonblocking: Lacking
+  COLL!persistent: Lacking
+  COLL!tools: Lacking
+  RMA: Lacking
+END_MPI_FEATURES
+
+BEGIN_MBI_TESTS
+  $ mpirun -np 2 ${EXE}
+  | @{outcome}@
+  | @{errormsg}@
+END_MBI_TESTS
+//////////////////////       End of MBI headers        /////////////////// */
+
+#include <mpi.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+int main(int argc, char **argv) {
+  int nprocs = -1;
+  int rank = -1;
+  int dest=0, src=0;
+  int stag = 0, rtag = 0;
+  int buff_size = 1;
+
+  MPI_Init(&argc, &argv);
+  MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+  printf("Hello from rank %d \\n", rank);
+
+  if (nprocs < 2)
+    printf("MBI ERROR: This test needs at least 2 processes to produce a bug!\\n");
+
+  MPI_Comm newcom = MPI_COMM_WORLD;
+  MPI_Datatype type = MPI_INT;
+
+  @{init1}@
+  @{init2}@
+  if (rank == 0) {
+    dest = 1; src = 1;
+    @{operation1}@
+    @{start1}@
+    @{write1}@ /* MBIERROR1 */
+    @{fini1}@
+    @{free1}@
+  }else if (rank == 1){
+    dest = 0; src = 0;
+    @{operation2}@
+    @{start2}@
+    @{write2}@ /* MBIERROR2 */
+    @{fini2}@
+    @{free2}@
+  }
+
+  MPI_Finalize();
+  printf("Rank %d finished normally\\n", rank);
+  return 0;
+}
+"""
+
+
+for s in send + isend + psend:
+    for r in irecv + precv + recv:
+        patterns = {}
+        patterns = {'s': s, 'r': r}
+        patterns['generatedby'] = f'DO NOT EDIT: this file was generated by {os.path.basename(sys.argv[0])}. DO NOT EDIT.'
+        patterns['p2pfeature'] = 'Yes' if s in send else 'Lacking'
+        patterns['ip2pfeature'] = 'Yes' if r in irecv else 'Lacking'
+        patterns['persfeature'] = 'Yes' if r in precv else 'Lacking'
+        patterns['s'] = s
+        patterns['r'] = r
+        patterns['init1'] = init[s]("1")
+        patterns['init2'] = init[r]("2")
+        patterns['fini1'] = fini[s]("1")
+        patterns['fini2'] = fini[r]("2")
+        patterns['start1'] = start[s]("1")
+        patterns['start2'] = start[r]("2")
+        patterns['operation1'] = operation[s]("1")
+        patterns['operation2'] = operation[r]("2")
+        patterns['write1'] = write[s]("1")
+        patterns['write2'] = write[r]("2")
+        patterns['free1'] = free[s]("1")
+        patterns['free2'] = free[r]("2")
+
+        # Generate a message race
+        if s in send and r in irecv + precv:
+            replace = patterns
+            replace['shortdesc'] = ' Local Concurrency with a P2P'
+            replace['longdesc'] = f'The message buffer in {r} is modified before the call has been completed.'
+            replace['outcome'] = 'ERROR: LocalConcurrency'
+            replace['errormsg'] = 'Local Concurrency with a P2P. The receive buffer in @{r}@ is modified at @{filename}@:@{line:MBIERROR2}@ whereas there is no guarantee the message has been received.'
+            make_file(template, f'LocalConcurrency_{r}_{s}_nok.c', replace)
+        if s in isend + psend and r in recv:
+            replace = patterns
+            replace['shortdesc'] = ' Local Concurrency with a P2P'
+            replace['longdesc'] = f'The message buffer in {s} is modified before the call has been completed.'
+            replace['outcome'] = 'ERROR: LocalConcurrency'
+            replace['errormsg'] = 'Local Concurrency with a P2P. The send buffer in @{s}@ is modified at @{filename}@:@{line:MBIERROR1}@ whereas there is no guarantee the message has been sent.'
+            make_file(template, f'LocalConcurrency_{r}_{s}_nok.c', replace)
+        if s in isend + psend and r in irecv + precv:
+            replace = patterns
+            replace['shortdesc'] = ' Local Concurrency with a P2P'
+            replace['longdesc'] = f'The message buffer in {s} and {r} are modified before the calls have completed.'
+            replace['outcome'] = 'ERROR: LocalConcurrency'
+            replace['errormsg'] = 'Local Concurrency with a P2P. The message buffers in @{s}@ and @{r}@ are modified at @{filename}@:@{line:MBIERROR1}@ and @{filename}@:@{line:MBIERROR2}@ whereas there is no guarantee the calls have been completed.'
+            make_file(template, f'LocalConcurrency_{r}_{s}_nok.c', replace)
diff --git a/teshsuite/smpi/MBI/P2PMatchingANYSRCGenerator.py b/teshsuite/smpi/MBI/P2PMatchingANYSRCGenerator.py
new file mode 100755 (executable)
index 0000000..0090a7c
--- /dev/null
@@ -0,0 +1,109 @@
+#! /usr/bin/python3
+import os
+import sys
+from generator_utils import *
+
+template = """// @{generatedby}@
+/* ///////////////////////// The MPI Bugs Initiative ////////////////////////
+
+  Origin: MBI
+
+  Description: @{shortdesc}@
+    @{longdesc}@
+
+  Version of MPI: Conforms to MPI 1.1, does not require MPI 2 implementation
+
+BEGIN_MPI_FEATURES
+  P2P!basic: @{p2pfeature}@
+  P2P!nonblocking: @{ip2pfeature}@
+  P2P!persistent: Lacking
+  COLL!basic: Lacking
+  COLL!nonblocking: Lacking
+  COLL!persistent: Lacking
+  COLL!tools: Lacking
+  RMA: Lacking
+END_MPI_FEATURES
+
+BEGIN_MBI_TESTS
+  $ mpirun -np 4 ${EXE}
+  | @{outcome}@
+  | @{errormsg}@
+END_MBI_TESTS
+//////////////////////       End of MBI headers        /////////////////// */
+
+#include <mpi.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+int main(int argc, char **argv) {
+  int nprocs = -1;
+  int rank = -1;
+  int src=MPI_ANY_SOURCE, dest=0;
+  int stag = 42, rtag = MPI_ANY_TAG;
+  int buff_size = 1;
+
+  MPI_Init(&argc, &argv);
+  MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+  printf("Hello from rank %d \\n", rank);
+
+  if (nprocs < 2)
+    printf("MBI ERROR: This test needs at least 2 processes to produce a bug!\\n");
+
+  int send_buffer=rank;
+
+  MPI_Datatype type = MPI_INT;
+  MPI_Comm newcom = MPI_COMM_WORLD;
+
+  @{init1}@
+  @{init2}@
+
+  if (rank == 0) {
+    for (int i = 0; i < nprocs - 1; i++) {
+      @{operation1}@ /* MBIERROR */
+      @{fini1}@
+    }
+  if (@{cond}@ != 3) {
+      printf("MBI_MSG_RACE: The last received message is not 3 but %d!\\n", buf1);
+      fflush(stdout);
+      abort();
+    }
+  }else{
+    @{operation2}@
+    @{fini2}@
+  }
+
+
+  MPI_Finalize();
+  printf("Rank %d finished normally\\n", rank);
+  return 0;
+}
+"""
+
+
+for s in send + isend:
+    for r in recv + irecv:
+        patterns = {}
+        patterns = {'s': s, 'r': r}
+        patterns['generatedby'] = f'DO NOT EDIT: this file was generated by {os.path.basename(sys.argv[0])}. DO NOT EDIT.'
+        patterns['p2pfeature'] = 'Yes' if s in send or r in recv else 'Lacking'
+        patterns['ip2pfeature'] = 'Yes' if s in isend or r in irecv else 'Lacking'
+        patterns['s'] = s
+        patterns['r'] = r
+        patterns['cond'] = 'buf1'
+        patterns['init2'] = init[s]("2")
+        patterns['init1'] = init[r]("1")
+        patterns['fini2'] = fini[s]("2")
+        patterns['fini1'] = fini[r]("1")
+        patterns['operation2'] = operation[s]("2")
+        patterns['operation1'] = operation[r]("1")
+
+        # Generate the incorrect matching
+        replace = patterns
+        replace['shortdesc'] = 'The message ordering is non-deterministic.'
+        replace['longdesc'] = f'The code assumes a fixed order in the reception of messages while the message ordering is non-deterministic.'
+        replace['outcome'] = 'ERROR: MessageRace'
+        replace['errormsg'] = 'P2P message race which can cause a deadlock. @{r}@ at @{filename}@:@{line:MBIERROR}@ is called with ANY_SRC.'
+        make_file(template, f'MessageRace_{r}_{s}_nok.c', replace)
+
diff --git a/teshsuite/smpi/MBI/P2PMatchingGenerator.py b/teshsuite/smpi/MBI/P2PMatchingGenerator.py
new file mode 100755 (executable)
index 0000000..0cf3e5a
--- /dev/null
@@ -0,0 +1,136 @@
+#! /usr/bin/python3
+import os
+import sys
+from generator_utils import *
+
+template = """// @{generatedby}@
+/* ///////////////////////// The MPI Bugs Initiative ////////////////////////
+
+  Origin: MBI
+
+  Description: @{shortdesc}@
+    @{longdesc}@
+
+  Version of MPI: Conforms to MPI 1.1, does not require MPI 2 implementation
+
+BEGIN_MPI_FEATURES
+  P2P!basic: @{p2pfeature}@
+  P2P!nonblocking: @{ip2pfeature}@
+  P2P!persistent: @{persfeature}0@
+  COLL!basic: Lacking
+  COLL!nonblocking: Lacking
+  COLL!persistent: Lacking
+  COLL!tools: Lacking
+  RMA: Lacking
+END_MPI_FEATURES
+
+BEGIN_MBI_TESTS
+  $ mpirun -np 2 ${EXE}
+  | @{outcome}@
+  | @{errormsg}@
+END_MBI_TESTS
+//////////////////////       End of MBI headers        /////////////////// */
+
+#include <mpi.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define buff_size 1
+
+int main(int argc, char **argv) {
+  int nprocs = -1;
+  int rank = -1;
+  int its_raining = 0;
+  int src=0, dest=1;
+  int stag=0, rtag=0;
+
+  MPI_Init(&argc, &argv);
+  MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+  printf("Hello from rank %d \\n", rank);
+
+  if (nprocs < 2)
+    printf("MBI ERROR: This test needs at least 2 processes to produce a bug!\\n");
+
+  MPI_Comm newcom = MPI_COMM_WORLD;
+  MPI_Datatype type = MPI_INT;
+
+  @{init1}@
+  @{init2}@
+  if (rank == 0) {
+    @{operation1}@ /* MBIERROR1 */
+    @{fini1}@
+  }else if (@{change_cond}@){
+    @{operation2}@ /* MBIERROR2 */
+    @{fini2}@
+  }
+
+  MPI_Finalize();
+  printf("Rank %d finished normally\\n", rank);
+  return 0;
+}
+"""
+
+
+for p in send + ssend + bsend + recv + irecv + isend:
+    patterns = {}
+    patterns = {'p': p}
+    patterns['generatedby'] = f'DO NOT EDIT: this file was generated by {os.path.basename(sys.argv[0])}. DO NOT EDIT.'
+    patterns['p2pfeature'] = 'Yes' if p in send + bsend + ssend + recv else 'Lacking'
+    patterns['ip2pfeature'] = 'Yes' if p in isend + irecv else 'Lacking'
+    patterns['persfeature'] = 'Lacking'
+    #patterns['persfeature'] = 'Yes' if p in psend + precv else 'Lacking'
+    patterns['p'] = p
+    patterns['init1'] = init[p]("1")
+    patterns['init2'] = '' #init[p2]("2")
+    patterns['fini1'] = fini[p]("1")
+    patterns['fini2'] = '' #fini[p2]("2")
+    patterns['operation1'] = operation[p]("1")
+    patterns['operation2'] = '' #operation[p2]("2")
+    patterns['change_cond'] = 'rank == 1'
+
+    # Generate the incorrect matching with one call
+    replace = patterns
+    replace['shortdesc'] = 'Point to point @{p}@ is not matched'
+    replace['longdesc'] = 'Process 0 calls @{p}@ and is not matched'
+    replace['outcome'] = 'ERROR: CallMatching'
+    replace['errormsg'] = 'P2P mistmatch. @{p}@ at @{filename}@:@{line:MBIERROR1}@ is not matched.'
+    make_file(template, f'CallOrdering_{p}_nok.c', replace)
+
+    # Generate the incorrect matching with two calls
+    replace = patterns
+    replace['shortdesc'] = 'Both point to point @{p}@ are not matched'
+    replace['longdesc'] = 'Processes 0 and 1 both call @{p}@ which are not matched'
+    replace['outcome'] = 'ERROR: CallMatching'
+    replace['errormsg'] = 'P2P mismatch. @{p}@ at @{filename}@:@{line:MBIERROR1}@ and @{p}@ at @{filename}@:@{line:MBIERROR2}@ are not matched.'
+    replace['operation2'] = operation[p]("1")
+    replace['fini2'] = fini[p]("1")
+    make_file(template, f'CallOrdering_{p}_{p}_nok.c', replace)
+
+for s in send + isend + ssend + bsend:
+    for r in recv + irecv:
+        patterns = {}
+        patterns = {'s': s, 'r': r}
+        patterns['generatedby'] = f'DO NOT EDIT: this file was generated by {os.path.basename(sys.argv[0])}. DO NOT EDIT.'
+        patterns['p2pfeature'] = 'Yes' if s in send or r in recv else 'Lacking'
+        patterns['ip2pfeature'] = 'Yes' if s in isend or r in irecv else 'Lacking'
+        patterns['s'] = s
+        patterns['r'] = r
+        patterns['init1'] = init[s]("1")
+        patterns['init2'] = init[r]("2")
+        patterns['fini1'] = fini[s]("1")
+        patterns['fini2'] = fini[r]("2")
+        patterns['operation1'] = operation[s]("1")
+        patterns['operation2'] = operation[r]("2")
+        patterns['change_cond'] = '(rank == 1) && (its_raining)'
+
+        # Generate the incorrect matching because of the conditional
+        replace = patterns
+        replace['shortdesc'] = 'Point to point @{r}@ is never called.'
+        replace['longdesc'] = 'Point to point @{r}@ is never executed. Process 1 calls MPI_Finalize and causes a deadlock.'
+        replace['outcome'] = 'ERROR: CallMatching'
+        replace['errormsg'] = 'P2P mistmatch. @{r}@ at @{filename}@:@{line:MBIERROR2}@ is never called because of the conditional (@{change_cond}@).'
+        replace['operation1'] =  operation[s]("1")
+        replace['operation2'] = operation[r]("2")
+        make_file(template, f'CallOrdering_{r}_{s}_nok.c', replace)
+
diff --git a/teshsuite/smpi/MBI/P2PProbeGenerator.py b/teshsuite/smpi/MBI/P2PProbeGenerator.py
new file mode 100755 (executable)
index 0000000..a5bc12f
--- /dev/null
@@ -0,0 +1,148 @@
+#! /usr/bin/python3
+import os
+import sys
+from generator_utils import *
+
+template = """// @{generatedby}@
+/* ///////////////////////// The MPI Bugs Initiative ////////////////////////
+
+  Origin: MBI
+
+  Description: @{shortdesc}@
+    @{longdesc}@
+
+  Version of MPI: Conforms to MPI 1.1, does not require MPI 2 implementation
+
+BEGIN_MPI_FEATURES
+  P2P!basic: @{p2pfeature}@
+  P2P!nonblocking: @{ip2pfeature}@
+  P2P!persistent: Lacking
+  COLL!basic: Lacking
+  COLL!nonblocking: Lacking
+  COLL!persistent: Lacking
+  COLL!tools: Lacking
+  RMA: Lacking
+END_MPI_FEATURES
+
+BEGIN_MBI_TESTS
+  $ mpirun -np 2 ${EXE}
+  | @{outcome}@
+  | @{errormsg}@
+END_MBI_TESTS
+//////////////////////       End of MBI headers        /////////////////// */
+
+#include <mpi.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+int main(int argc, char **argv) {
+  int nprocs = -1;
+  int rank = -1;
+  MPI_Status sta;
+  int src,dest;
+  int stag=0, rtag=0;
+  int buff_size = 1;
+
+  MPI_Init(&argc, &argv);
+  MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+  printf("Hello from rank %d \\n", rank);
+
+  if (nprocs < 2)
+    printf("MBI ERROR: This test needs at least 2 processes to produce a bug!\\n");
+
+  MPI_Comm newcom = MPI_COMM_WORLD;
+  MPI_Datatype type = MPI_INT;
+
+  @{init1a}@
+  @{init1b}@
+  @{init1c}@
+  @{init2a}@
+  @{init2b}@
+  @{init2c}@
+
+  if (rank == 0) {
+    dest=1, src=1;
+    @{operation1a}@ /* MBIERROR1 */
+    @{operation1b}@
+    @{operation1c}@
+    @{fini1a}@
+    @{fini1b}@
+    @{fini1c}@
+  }else if (rank == 1){
+    dest=0, src=0;
+    @{operation2a}@ /* MBIERROR2 */
+    @{operation2b}@
+    @{operation2c}@
+    @{fini2a}@
+    @{fini2b}@
+    @{fini2c}@
+  }
+  @{free1a}@
+  @{free1b}@
+  @{free1c}@
+  @{free2a}@
+  @{free2b}@
+  @{free2c}@
+
+  MPI_Finalize();
+  printf("Rank %d finished normally\\n", rank);
+  return 0;
+}
+"""
+
+
+for p in probe:
+    for s in send + isend:
+        for r in recv + irecv:
+            patterns = {}
+            patterns = {'p':p, 's': s, 'r': r}
+            patterns['generatedby'] = f'DO NOT EDIT: this file was generated by {os.path.basename(sys.argv[0])}. DO NOT EDIT.'
+            patterns['p2pfeature'] = 'Yes' if s in send or r in recv else 'Lacking'
+            patterns['ip2pfeature'] = 'Yes' if s in isend or r in irecv else 'Lacking'
+            patterns['s'] = s
+            patterns['r'] = r
+            patterns['p'] = p
+            patterns['init1a'] = init[p]("1")
+            patterns['init1b'] = init[s]("1")
+            patterns['init1c'] = init[r]("2")
+            patterns['init2a'] = init[p]("1")
+            patterns['init2b'] = init[r]("3")
+            patterns['init2c'] = init[s]("4")
+            patterns['fini1a'] = fini[p]("1")
+            patterns['fini1b'] = fini[s]("1")
+            patterns['fini1c'] = fini[r]("2")
+            patterns['fini2a'] = fini[p]("1")
+            patterns['fini2b'] = fini[r]("3")
+            patterns['fini2c'] = fini[s]("4")
+            patterns['free1a'] = free[p]("1")
+            patterns['free1b'] = free[s]("1")
+            patterns['free1c'] = free[r]("2")
+            patterns['free2a'] = free[p]("1")
+            patterns['free2b'] = free[r]("3")
+            patterns['free2c'] = free[s]("4")
+            patterns['operation1a'] = operation[p]("1")
+            patterns['operation1b'] = operation[s]("1")
+            patterns['operation1c'] = operation[r]("2")
+            patterns['operation2a'] = operation[p]("1")
+            patterns['operation2b'] = operation[r]("3")
+            patterns['operation2c'] = operation[s]("4")
+
+            # Generate the incorrect matching
+            replace = patterns
+            replace['shortdesc'] = 'MPI_Probe is called before MPI_Recv.'
+            replace['longdesc'] = 'MPI_Probe is a blocking call that returns only after a matching message has been found. By calling MPI_Probe before MPI_Recv, a deadlock is created.'
+            replace['outcome'] = 'ERROR: CallMatching'
+            replace['errormsg'] = 'P2P mistmatch. @{p}@ at @{filename}@:@{line:MBIERROR1}@ and @{filename}@:@{line:MBIERROR2}@ are called before @{r}@.'
+            make_file(template, f'CallOrdering_{p}_{r}_{s}_nok.c', replace)
+
+            # Generate a correct matching
+            replace = patterns
+            replace['shortdesc'] = 'Correct use of MPI_Probe.'
+            replace['longdesc'] = 'Correct use of MPI_Probe.'
+            replace['outcome'] = 'OK'
+            replace['errormsg'] = 'OK'
+            replace['operation1a'] = operation[s]("1")
+            replace['operation1b'] = operation[p]("1")
+            make_file(template, f'CallOrdering_{p}_{r}_{s}_ok.c', replace)
diff --git a/teshsuite/smpi/MBI/RMAArgGenerator.py b/teshsuite/smpi/MBI/RMAArgGenerator.py
new file mode 100755 (executable)
index 0000000..e8a8ca3
--- /dev/null
@@ -0,0 +1,110 @@
+#! /usr/bin/python3
+import os
+import sys
+from generator_utils import *
+
+template = """// @{generatedby}@
+/* ///////////////////////// The MPI Bugs Initiative ////////////////////////
+
+  Origin: @{origin}@
+
+  Description: @{shortdesc}@
+    @{longdesc}@
+
+
+BEGIN_MPI_FEATURES
+  P2P!basic: Lacking
+  P2P!nonblocking: Lacking
+  P2P!persistent: Lacking
+  COLL!basic: Lacking
+  COLL!nonblocking: Lacking
+  COLL!persistent: Lacking
+  COLL!tools: Lacking
+  RMA: @{rmafeature}@
+END_MPI_FEATURES
+
+BEGIN_MBI_TESTS
+  $ mpirun -np 2 ${EXE}
+  | @{outcome}@
+  | @{errormsg}@
+END_MBI_TESTS
+//////////////////////       End of MBI headers        /////////////////// */
+
+#include <mpi.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define N 10
+
+int main(int argc, char **argv) {
+  int rank, numProcs;
+
+  MPI_Init(&argc, &argv);
+  MPI_Comm_size(MPI_COMM_WORLD, &numProcs);
+  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+  int *winbuf = malloc(N * sizeof(int));
+
+  MPI_Win win;
+  MPI_Win_create(&winbuf, N * sizeof(int), 1, MPI_INFO_NULL, MPI_COMM_WORLD, &win);
+
+  MPI_Datatype type = MPI_INT;
+  int target = (rank + 1) % numProcs;
+
+  if(rank == 0){
+    @{epoch}@
+    @{change_arg}@
+    @{init}@
+     @{operation}@ /* MBIERROR2 */
+
+    @{finEpoch}@
+  } else {
+    @{epoch}@
+
+    @{finEpoch}@
+  }
+
+  MPI_Win_free(&win);
+
+  free(winbuf);
+
+  MPI_Finalize();
+  return 0;
+}
+"""
+
+
+for e in epoch:
+    for p in rma:
+        patterns = {}
+        patterns = {'e': e, 'p': p}
+        patterns['origin'] = "MBI"
+        patterns['generatedby'] = f'DO NOT EDIT: this file was generated by {os.path.basename(sys.argv[0])}. DO NOT EDIT.'
+        patterns['rmafeature'] = 'Yes'
+        patterns['p'] = p
+        patterns['e'] = e
+        patterns['epoch'] = epoch[e]("1")
+        patterns['finEpoch'] = finEpoch[e]("1")
+        patterns['init'] = init[p]("1")
+        patterns['operation'] = operation[p]("1")
+        patterns['change_arg'] = ""
+
+        # Generate a code with a null type
+        replace = patterns
+        replace['shortdesc'] = 'Invalid argument in one-sided operation.'
+        replace['longdesc'] = 'A one-sided operation has MPI_DATATYPE_NULL as a type.'
+        replace['outcome'] = 'ERROR: InvalidDatatype'
+        replace['change_arg'] = 'type = MPI_DATATYPE_NULL;'
+        replace['errormsg'] = '@{p}@ at @{filename}@:@{line:MBIERROR}@ has MPI_DATATYPE_NULL as a type'
+        make_file(template, f'InvalidParam_BufferNullCond_{e}_{p}_nok.c', replace)
+
+        # Generate a code with an invalid type
+        replace = patterns
+        replace['shortdesc'] = 'Invalid argument in one-sided operation.'
+        replace['longdesc'] = 'Use of an invalid datatype in one-sided operation.'
+        replace['outcome'] = 'ERROR: InvalidDatatype'
+        replace['change_arg'] = 'MPI_Type_contiguous (2, MPI_INT, &type); MPI_Type_commit(&type);MPI_Type_free(&type); /* MBIERROR2 */'
+        replace['errormsg'] = 'Invalid Datatype in @{p}@ at @{filename}@:@{line:MBIERROR}@'
+        make_file(template, f'InvalidParam_DatatypeCond_{e}_{p}_nok.c', replace)
+
diff --git a/teshsuite/smpi/MBI/RMAInvalidArgGenerator.py b/teshsuite/smpi/MBI/RMAInvalidArgGenerator.py
new file mode 100755 (executable)
index 0000000..8160671
--- /dev/null
@@ -0,0 +1,133 @@
+#! /usr/bin/python3
+import os
+import sys
+from generator_utils import *
+
+template = """// @{generatedby}@
+/* ///////////////////////// The MPI Bugs Initiative ////////////////////////
+
+  Origin: @{origin}@
+
+  Description: @{shortdesc}@
+    @{longdesc}@
+
+    Version of MPI: Conforms to MPI 1.1, does not require MPI 2 implementation
+
+BEGIN_MPI_FEATURES
+    P2P!basic: Lacking
+    P2P!nonblocking: Lacking
+    P2P!persistent: Lacking
+    COLL!basic: Lacking
+    COLL!nonblocking: Lacking
+    COLL!persistent: Lacking
+    COLL!tools: Lacking
+    RMA: @{rmafeature}@
+END_MPI_FEATURES
+
+BEGIN_MBI_TESTS
+  $ mpirun -np 2 ${EXE}
+  | @{outcome}@
+  | @{errormsg}@
+END_MBI_TESTS
+//////////////////////       End of MBI headers        /////////////////// */
+
+#include <mpi.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define N 10
+
+int main(int argc, char **argv) {
+  int nprocs = -1 , rank = -1;
+  MPI_Win win;
+  int *winbuf = @{malloc}@ // Window buffer
+
+  MPI_Init(&argc, &argv);
+  MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+  if (nprocs < 2)
+    printf("MBI ERROR: This test needs at least 2 processes to produce a bug!\\n");
+
+  MPI_Datatype type = MPI_INT;
+  int target = (rank + 1) % nprocs;
+
+  MPI_Win_create(winbuf, N * sizeof(int), 1, MPI_INFO_NULL, MPI_COMM_WORLD, &win);
+
+
+  @{epoch}@
+
+  @{init}@
+  @{change_arg}@
+  @{operation}@ /* MBIERROR */
+
+  @{finEpoch}@
+
+  MPI_Win_free(&win);
+  free(winbuf);
+
+  MPI_Finalize();
+  printf("Rank %d finished normally\\n", rank);
+  return 0;
+}
+"""
+
+
+for e in epoch:
+    for p in rma:
+        patterns = {}
+        patterns = {'e': e, 'p': p}
+        patterns['origin'] = "MBI"
+        patterns['generatedby'] = f'DO NOT EDIT: this file was generated by {os.path.basename(sys.argv[0])}. DO NOT EDIT.'
+        patterns['rmafeature'] = 'Yes'
+        patterns['p'] = p
+        patterns['e'] = e
+        patterns['epoch'] = epoch[e]("1")
+        patterns['finEpoch'] = finEpoch[e]("1")
+        patterns['init'] = init[p]("1")
+        patterns['operation'] = operation[p]("1")
+        patterns['change_arg'] = ""
+        patterns['malloc'] = "malloc(N * sizeof(int));"
+
+        # Generate a code with a null type
+        replace = patterns
+        replace['shortdesc'] = 'Invalid argument in one-sided operation.'
+        replace['longdesc'] = 'A one-sided operation has MPI_DATATYPE_NULL as a type.'
+        replace['outcome'] = 'ERROR: InvalidDatatype'
+        replace['change_arg'] = 'type = MPI_DATATYPE_NULL;'
+        replace['errormsg'] = '@{p}@ at @{filename}@:@{line:MBIERROR}@ has MPI_DATATYPE_NULL as a type'
+        make_file(template, f'InvalidParam_DatatypeNull_{e}_{p}_nok.c', replace)
+
+        # Generate a code with a null buffer (move to RMAWinBufferGenerator)
+        # replace = patterns
+        # replace['origin'] = 'MPI-Corrbench'
+        # replace['shortdesc'] = 'nullptr is invalid in one-sided operation.'
+        # replace['longdesc'] = 'A one-sided operation has an invalid buffer.'
+        # replace['outcome'] = 'ERROR: InvalidBuffer'
+        # replace['init'] = 'int * localbuf1 = malloc(sizeof(int));'
+        # replace['change_arg'] = 'localbuf1 = NULL;'
+        # replace['operation'] = operation[p]("1").replace('&localbuf1', 'localbuf1')
+        # replace['errormsg'] = '@{p}@ at @{filename}@:@{line:MBIERROR}@ has an invalid buffer'
+        # make_file(template, f'InvalidParam_BufferNull_{e}_{p}_nok.c', replace)
+
+        # Generate a code with an invalid type
+        replace = patterns
+        replace['origin'] = 'MBI'
+        replace['shortdesc'] = 'Invalid argument in one-sided operation.'
+        replace['longdesc'] = 'Use of an invalid datatype in one-sided operation.'
+        replace['outcome'] = 'ERROR: InvalidDatatype'
+        replace['change_arg'] = 'MPI_Type_contiguous (2, MPI_INT, &type); MPI_Type_commit(&type);MPI_Type_free(&type); /* MBIERROR2 */'
+        replace['errormsg'] = 'Invalid Datatype in @{p}@ at @{filename}@:@{line:MBIERROR}@'
+        make_file(template, f'InvalidParam_Datatype_{e}_{p}_nok.c', replace)
+
+        # Generate a code with invalid buffer
+        replace = patterns
+        patterns['origin'] = "MPI-Corrbench"
+        replace['shortdesc'] = 'Invalid invalid buffer (buffer must be allocated)'
+        replace['longdesc'] = 'Use of an invalid buffer in MPI_Win_create.'
+        replace['outcome'] = 'ERROR: InvalidBuffer'
+        patterns['malloc'] = "NULL; /* MBIERROR2 */"
+        patterns['operation'] = ""
+        replace['change_arg'] = ""
+        replace['errormsg'] = 'Invalid buffer in Win_create at @{filename}@:@{line:MBIERROR2}@'
+        make_file(template, f'InvalidParam_InvalidBufferWinCreate_{e}_{p}_nok.c', replace)
diff --git a/teshsuite/smpi/MBI/RMALocalLocalConcurrencyGenerator.py b/teshsuite/smpi/MBI/RMALocalLocalConcurrencyGenerator.py
new file mode 100755 (executable)
index 0000000..f24d5f3
--- /dev/null
@@ -0,0 +1,164 @@
+#! /usr/bin/python3
+import os
+import sys
+from generator_utils import *
+
+template = """// @{generatedby}@
+/* ///////////////////////// The MPI Bugs Initiative ////////////////////////
+
+  Origin: MBI
+
+  Description: @{shortdesc}@
+    @{longdesc}@
+
+  Version of MPI: Conforms to MPI 2, requires MPI 3 implementation (for lock_all/unlock_all epochs)
+
+BEGIN_MPI_FEATURES
+  P2P!basic: Lacking
+  P2P!nonblocking: Lacking
+  P2P!persistent: Lacking
+  COLL!basic: Lacking
+  COLL!nonblocking: Lacking
+  COLL!persistent: Lacking
+  COLL!tools: Lacking
+  RMA: @{rmafeature}@
+END_MPI_FEATURES
+
+BEGIN_MBI_TESTS
+  $ mpirun -np 2 ${EXE}
+  | @{outcome}@
+  | @{errormsg}@
+END_MBI_TESTS
+//////////////////////       End of MBI headers        /////////////////// */
+
+#include <mpi.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define N 1
+
+int main(int argc, char **argv) {
+  int nprocs = -1;
+  int rank = -1;
+  MPI_Win win;
+  int winbuf[100] = {0};
+
+  MPI_Init(&argc, &argv);
+  MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+  printf("Hello from rank %d \\n", rank);
+
+  if (nprocs < 2)
+    printf("MBI ERROR: This test needs at least 2 processes to produce a bug!\\n");
+
+  MPI_Datatype type = MPI_INT;
+  int target = 1;
+
+  MPI_Win_create(&winbuf, 100 * sizeof(int), sizeof(int), MPI_INFO_NULL, MPI_COMM_WORLD, &win);
+
+  winbuf[0] = 12345;
+  @{init1}@
+
+  @{epoch}@
+
+  if (rank == 0) {
+    @{operation1}@ /* MBIERROR1 */
+    @{operation2}@ /* MBIERROR2 */
+  }
+
+  @{finEpoch}@
+
+  MPI_Win_free(&win);
+
+  MPI_Finalize();
+  return 0;
+}
+"""
+
+
+for e in epoch:
+    for p1 in get:
+        for p2 in put + store + load + get + loadstore:
+            patterns = {}
+            patterns = {'e': e, 'p1': p1, 'p2': p2}
+            patterns['generatedby'] = f'DO NOT EDIT: this file was generated by {os.path.basename(sys.argv[0])}. DO NOT EDIT.'
+            patterns['rmafeature'] = 'Yes'
+            patterns['p1'] = p1
+            patterns['p2'] = p2
+            patterns['e'] = e
+            patterns['epoch'] = epoch[e]("1")
+            patterns['finEpoch'] = finEpoch[e]("1")
+            patterns['init1'] = init[p1]("1")
+            patterns['operation1'] = operation[p1]("1")
+            patterns['operation2'] = operation[p2]("1")
+
+            # Generate a data race (Get + Get/load/store/Put)
+            replace = patterns
+            replace['shortdesc'] = 'Local Concurrency error.'
+            replace['longdesc'] = 'Local Concurrency error. @{p2}@ conflicts with @{p1}@'
+            replace['outcome'] = 'ERROR: LocalConcurrency'
+            replace['errormsg'] = 'Local Concurrency error. @{p2}@ at @{filename}@:@{line:MBIERROR2}@ conflicts with @{p1}@ line @{line:MBIERROR1}@'
+            make_file(template, f'LocalConcurrency_lloutwindow_{e}_{p1}_{p2}_nok.c', replace)
+            # Generate a correct code by switching operation1 and  operation2
+            if p2 in store + load + loadstore:
+                  replace = patterns
+                  replace['shortdesc'] = 'Correct code using RMA operations'
+                  replace['longdesc'] = 'Correct code using RMA operations'
+                  replace['outcome'] = 'OK'
+                  replace['errormsg'] = 'OK'
+                  replace['operation1'] = operation[p2]("1")
+                  replace['operation2'] = operation[p1]("1")
+                  make_file(template, f'LocalConcurrency_lloutwindow_{e}_{p2}_{p1}_ok.c', replace)
+        # Generate a correct code by removing operation2
+        replace = patterns
+        replace['shortdesc'] = 'Correct code using RMA operations'
+        replace['longdesc'] = 'Correct code using RMA operations'
+        replace['outcome'] = 'OK'
+        replace['errormsg'] = 'OK'
+        replace['operation1'] = operation[p1]("1")
+        replace['operation2'] = ''
+        make_file(template, f'LocalConcurrency_{e}_{p1}_ok.c', replace)
+
+
+for e in epoch:
+    for p1 in put:
+        for p2 in store:
+            patterns = {}
+            patterns = {'e': e, 'p1': p1, 'p2': p2}
+            patterns['generatedby'] = f'DO NOT EDIT: this file was generated by {os.path.basename(sys.argv[0])}. DO NOT EDIT.'
+            patterns['rmafeature'] = 'Yes'
+            patterns['p1'] = p1
+            patterns['p2'] = p2
+            patterns['e'] = e
+            patterns['epoch'] = epoch[e]("1")
+            patterns['finEpoch'] = finEpoch[e]("1")
+            patterns['init1'] = init[p1]("1")
+            patterns['operation1'] = operation[p1]("1")
+            patterns['operation2'] = operation[p2]("1")
+
+            # Generate a data race (Put + store)
+            replace = patterns
+            replace['shortdesc'] = 'Local Concurrency error.'
+            replace['longdesc'] = 'Local Concurrency error. @{p2}@ conflicts with @{p1}@'
+            replace['outcome'] = 'ERROR: LocalConcurrency'
+            replace['errormsg'] = 'Local Concurrency error. @{p2}@ at @{filename}@:@{line:MBIERROR2}@ conflicts with @{p1}@ line @{line:MBIERROR1}@'
+            make_file(template, f'LocalConcurrency_lloutwindow_{e}_{p1}_{p2}_nok.c', replace)
+            # Generate a correct code by switching operation1 and operation2
+            replace = patterns
+            replace['shortdesc'] = 'Correct code using RMA operations'
+            replace['longdesc'] = 'Correct code using RMA operations'
+            replace['outcome'] = 'OK'
+            replace['errormsg'] = 'OK'
+            replace['operation1'] = operation[p2]("1")
+            replace['operation2'] = operation[p1]("1")
+            make_file(template, f'LocalConcurrency_lloutwindow_{e}_{p2}_{p1}_ok.c', replace)
+
+            # Generate a correct code by removing operation2
+            replace = patterns
+            replace['shortdesc'] = 'Correct code using RMA operations'
+            replace['longdesc'] = 'Correct code using RMA operations'
+            replace['outcome'] = 'OK'
+            replace['errormsg'] = 'OK'
+            replace['operation1'] = operation[p1]("1")
+            replace['operation2'] = ''
+            make_file(template, f'LocalConcurrency_{e}_{p1}_ok.c', replace)
diff --git a/teshsuite/smpi/MBI/RMAP2PGlobalConcurrencyGenerator.py b/teshsuite/smpi/MBI/RMAP2PGlobalConcurrencyGenerator.py
new file mode 100755 (executable)
index 0000000..b9535e1
--- /dev/null
@@ -0,0 +1,121 @@
+#! /usr/bin/python3
+import os
+import sys
+from generator_utils import *
+
+template = """// @{generatedby}@
+/* ///////////////////////// The MPI Bugs Initiative ////////////////////////
+
+  Origin: MBI
+
+  Description: @{shortdesc}@
+    @{longdesc}@
+
+  Version of MPI: Conforms to MPI 2, does not require MPI 3 implementation
+
+BEGIN_MPI_FEATURES
+  P2P!basic: @{p2pfeature}@
+  P2P!nonblocking: @{ip2pfeature}@
+  P2P!persistent: Lacking
+  COLL!basic: Lacking
+  COLL!nonblocking: Lacking
+  COLL!persistent: Lacking
+  COLL!tools: Lacking
+  RMA: @{rmafeature}@
+END_MPI_FEATURES
+
+BEGIN_MBI_TESTS
+  $ mpirun -np 4 ${EXE}
+  | @{outcome}@
+  | @{errormsg}@
+END_MBI_TESTS
+//////////////////////       End of MBI headers        /////////////////// */
+
+#include <mpi.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define N 1
+
+int main(int argc, char **argv) {
+  int nprocs = -1;
+  int rank = -1;
+  MPI_Win win;
+  int * winbuf = malloc(N * sizeof(int)); // Window buffer
+  int buff_size = 1;
+
+  MPI_Init(&argc, &argv);
+  MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+  printf("Hello from rank %d \\n", rank);
+
+  if (nprocs < 4)
+    printf("MBI ERROR: This test needs at least 4 processes to produce a bug!\\n");
+
+  MPI_Comm newcom = MPI_COMM_WORLD;
+  MPI_Datatype type = MPI_INT;
+  int stag=0, rtag=0;
+  winbuf[0] = nprocs;
+
+  MPI_Win_create(winbuf, N*sizeof(int), sizeof(int), MPI_INFO_NULL, MPI_COMM_WORLD, &win);
+
+
+  @{init1}@
+  @{init2}@
+  @{init3}@
+
+  if (rank == 0) {
+    int target=1;
+    MPI_Win_lock(MPI_LOCK_EXCLUSIVE, 1, 0, win);
+    @{operation1}@
+    localbuf1[0] = 12345; /* MBIERROR1 */
+    MPI_Win_unlock(1, win);
+  }else if (rank == 2){
+    int dest=1;
+    @{operation2}@
+    @{fini2}@
+  }else if (rank == 1){
+    int src=2;
+    buf3 = winbuf[0];
+    @{operation3}@
+    winbuf[0] = buf3; /* MBIERROR2 */
+    @{fini3}@
+  }
+
+  MPI_Win_free(&win);
+  free(winbuf);
+
+  MPI_Finalize();
+  printf("Rank %d finished normally\\n", rank);
+  return 0;
+}
+"""
+
+
+for p in put + get:
+    for s in send + isend:
+         for r in recv + irecv:
+             patterns = {}
+             patterns = {'p': p, 's': s, 'r': r}
+             patterns['generatedby'] = f'DO NOT EDIT: this file was generated by {os.path.basename(sys.argv[0])}. DO NOT EDIT.'
+             patterns['rmafeature'] = 'Yes'
+             patterns['p2pfeature'] = 'Yes' if s in send or r in recv  else 'Lacking'
+             patterns['ip2pfeature'] = 'Yes' if s in isend or r in irecv  else 'Lacking'
+             patterns['p'] = p
+             patterns['s'] = s
+             patterns['r'] = r
+             patterns['init1'] = init[p]("1")
+             patterns['init2'] = init[s]("2")
+             patterns['init3'] = init[r]("3")
+             patterns['fini2'] = fini[s]("2")
+             patterns['fini3'] = fini[r]("3")
+             patterns['operation1'] = operation[p]("1") #put or get
+             patterns['operation2'] = operation[s]("2") #send
+             patterns['operation3'] = operation[r]("3") #recv
+
+             replace = patterns
+             replace['shortdesc'] = 'Global Concurrency error.'
+             replace['longdesc'] = 'Global Concurrency error. Concurrent access of variable winbuf by @{p}@ and @{r}@'
+             replace['outcome'] = 'ERROR: GlobalConcurrency'
+             replace['errormsg'] = 'Global Concurrency error. @{p}@ at @{filename}@:@{line:MBIERROR1}@ accesses the window of process 1. Process 1 receives data from process 2 and uses variable winbuf. winbuf in process 1 is then nondeterministic.'
+             make_file(template, f'GlobalConcurrency_{p}_{s}_{r}_nok.c', replace)
diff --git a/teshsuite/smpi/MBI/RMARemoteLocalConcurrencyGenerator.py b/teshsuite/smpi/MBI/RMARemoteLocalConcurrencyGenerator.py
new file mode 100755 (executable)
index 0000000..928d5b7
--- /dev/null
@@ -0,0 +1,140 @@
+#! /usr/bin/python3
+import os
+import sys
+from generator_utils import *
+
+template = """// @{generatedby}@
+/* ///////////////////////// The MPI Bugs Initiative ////////////////////////
+
+  Origin: MBI
+
+  Description: @{shortdesc}@
+    @{longdesc}@
+
+  Version of MPI: Conforms to MPI 2, requires MPI 3 implementation (for lock_all/unlock_all epochs)
+
+BEGIN_MPI_FEATURES
+  P2P!basic: Lacking
+  P2P!nonblocking: Lacking
+  P2P!persistent: Lacking
+  COLL!basic: Lacking
+  COLL!nonblocking: Lacking
+  COLL!persistent: Lacking
+  COLL!tools: Lacking
+  RMA: @{rmafeature}@
+END_MPI_FEATURES
+
+BEGIN_MBI_TESTS
+  $ mpirun -np 2 ${EXE}
+  | @{outcome}@
+  | @{errormsg}@
+END_MBI_TESTS
+//////////////////////       End of MBI headers        /////////////////// */
+
+#include <mpi.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define N 1
+
+int main(int argc, char **argv) {
+  int nprocs = -1;
+  int rank = -1;
+  MPI_Win win;
+  int winbuf[100] = {0};
+
+  MPI_Init(&argc, &argv);
+  MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+  printf("Hello from rank %d \\n", rank);
+
+  if (nprocs < 2)
+    printf("MBI ERROR: This test needs at least 2 processes to produce a bug!\\n");
+
+  MPI_Datatype type = MPI_INT;
+  int target = 1;
+
+  MPI_Win_create(&winbuf, 100 * sizeof(int), sizeof(int), MPI_INFO_NULL, MPI_COMM_WORLD, &win);
+
+  @{init1}@
+
+  @{epoch}@
+
+  if (rank == 0) {
+    @{operation1}@ /* MBIERROR1 */
+  }
+  if(rank == 1){
+    target = 0;
+    @{operation2}@ /* MBIERROR2 */
+  }
+
+  @{finEpoch}@
+
+  MPI_Win_free(&win);
+
+  MPI_Finalize();
+  return 0;
+}
+"""
+
+
+for e in epoch:
+    for p1 in get:
+        for p2 in put + rstore + rload + get :
+            patterns = {}
+            patterns = {'e': e, 'p1': p1, 'p2': p2}
+            patterns['generatedby'] = f'DO NOT EDIT: this file was generated by {os.path.basename(sys.argv[0])}. DO NOT EDIT.'
+            patterns['rmafeature'] = 'Yes'
+            patterns['p1'] = p1
+            patterns['p2'] = p2
+            patterns['e'] = e
+            patterns['epoch'] = epoch[e]("1")
+            patterns['finEpoch'] = finEpoch[e]("1")
+            patterns['init1'] = init[p1]("1")
+            patterns['operation1'] = operation[p1]("1")
+            patterns['operation2'] = operation[p2]("1")
+
+            # Generate a data race (Get + Get/load/store/Put)
+            replace = patterns
+            replace['shortdesc'] = 'Global Concurrency error.'
+            replace['longdesc'] = 'Global Concurrency error. @{p2}@ conflicts with @{p1}@'
+            replace['outcome'] = 'ERROR: GlobalConcurrency'
+            replace['errormsg'] = 'Global Concurrency error. @{p2}@ at @{filename}@:@{line:MBIERROR2}@ conflicts with @{p1}@ line @{line:MBIERROR1}@'
+
+            # Replace Put and Get first argument
+            if p2 in put:
+                replace['operation2'] = 'MPI_Put(&winbuf[20], N, MPI_INT, target, 0, N, type, win);'
+            if p2 in get:
+                replace['operation2'] = 'MPI_Get(&winbuf[20], N, MPI_INT, target, 0, N, type, win);'
+
+            make_file(template, f'GlobalConcurrency_rl_{e}_{p1}_{p2}_nok.c', replace)
+
+
+for e in epoch:
+    for p1 in put:
+        for p2 in rstore + rload + put:
+            patterns = {}
+            patterns = {'e': e, 'p1': p1, 'p2': p2}
+            patterns['generatedby'] = f'DO NOT EDIT: this file was generated by {os.path.basename(sys.argv[0])}. DO NOT EDIT.'
+            patterns['rmafeature'] = 'Yes'
+            patterns['p1'] = p1
+            patterns['p2'] = p2
+            patterns['e'] = e
+            patterns['epoch'] = epoch[e]("1")
+            patterns['finEpoch'] = finEpoch[e]("1")
+            patterns['init1'] = init[p1]("1")
+            patterns['operation1'] = operation[p1]("1")
+            patterns['operation2'] = operation[p2]("1")
+
+            # Generate a data race (Put + store)
+            replace = patterns
+            replace['shortdesc'] = 'Global Concurrency error.'
+            replace['longdesc'] = 'Global Concurrency error. @{p2}@ conflicts with @{p1}@'
+            replace['outcome'] = 'ERROR: GlobalConcurrency'
+            replace['errormsg'] = 'Global Concurrency error. @{p2}@ at @{filename}@:@{line:MBIERROR2}@ conflicts with @{p1}@ line @{line:MBIERROR1}@'
+
+            # Replace Put first argument
+            if p2 in put:
+              replace['operation2'] = 'MPI_Put(&winbuf[20], N, MPI_INT, target, 0, N, type, win);'
+
+            make_file(template, f'GlobalConcurrency_rl_{e}_{p1}_{p2}_nok.c', replace)
diff --git a/teshsuite/smpi/MBI/RMARemoteRemoteConcurrencyGenerator.py b/teshsuite/smpi/MBI/RMARemoteRemoteConcurrencyGenerator.py
new file mode 100755 (executable)
index 0000000..10e421c
--- /dev/null
@@ -0,0 +1,97 @@
+#! /usr/bin/python3
+import os
+import sys
+from generator_utils import *
+
+template = """// @{generatedby}@
+/* ///////////////////////// The MPI Bugs Initiative ////////////////////////
+
+  Origin: MBI
+
+  Description: @{shortdesc}@
+    @{longdesc}@
+
+  Version of MPI: Conforms to MPI 2, requires MPI 3 implementation (for lock_all/unlock_all epochs)
+
+BEGIN_MPI_FEATURES
+  P2P!basic: Lacking
+  P2P!nonblocking: Lacking
+  P2P!persistent: Lacking
+  COLL!basic: Lacking
+  COLL!nonblocking: Lacking
+  COLL!persistent: Lacking
+  COLL!tools: Lacking
+  RMA: @{rmafeature}@
+END_MPI_FEATURES
+
+BEGIN_MBI_TESTS
+  $ mpirun -np 2 ${EXE}
+  | @{outcome}@
+  | @{errormsg}@
+END_MBI_TESTS
+//////////////////////       End of MBI headers        /////////////////// */
+
+#include <mpi.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define N 1
+
+int main(int argc, char **argv) {
+  int nprocs = -1;
+  int rank = -1;
+  MPI_Win win;
+  int winbuf[100] = {0};
+
+  MPI_Init(&argc, &argv);
+  MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+  printf("Hello from rank %d \\n", rank);
+
+  if (nprocs < 2)
+    printf("MBI ERROR: This test needs at least 2 processes to produce a bug!\\n");
+
+  MPI_Datatype type = MPI_INT;
+  int target = 1;
+
+  MPI_Win_create(&winbuf, 100 * sizeof(int), sizeof(int), MPI_INFO_NULL, MPI_COMM_WORLD, &win);
+
+  @{init1}@
+
+  @{epoch}@
+
+  if (rank == 0 || rank == 2) {
+    @{operation1}@ /* MBIERROR1 */
+  }
+
+  @{finEpoch}@
+
+  MPI_Win_free(&win);
+
+  MPI_Finalize();
+  return 0;
+}
+"""
+
+
+for e in epoch:
+    for p1 in get + put:
+        patterns = {}
+        patterns = {'e': e, 'p1': p1}
+        patterns['generatedby'] = f'DO NOT EDIT: this file was generated by {os.path.basename(sys.argv[0])}. DO NOT EDIT.'
+        patterns['rmafeature'] = 'Yes'
+        patterns['p1'] = p1
+        patterns['e'] = e
+        patterns['epoch'] = epoch[e]("1")
+        patterns['finEpoch'] = finEpoch[e]("1")
+        patterns['init1'] = init[p1]("1")
+        patterns['operation1'] = operation[p1]("1")
+
+        # Generate a data race (Get + Get/load/store/Put)
+        replace = patterns
+        replace['shortdesc'] = 'Global Concurrency error.'
+        replace['longdesc'] = 'Global Concurrency error. Both processes 0 and 2 access the window in process 1 with @{p1}@'
+        replace['outcome'] = 'ERROR: GlobalConcurrency'
+        replace['errormsg'] = 'Global Concurrency error. @{p1}@ at @{filename}@:@{line:MBIERROR1}@ conflicts in process 1'
+        make_file(template, f'GlobalConcurrency_rr_{e}_{p1}_nok.c', replace)
+
diff --git a/teshsuite/smpi/MBI/RMAReqLifecycleGenerator.py b/teshsuite/smpi/MBI/RMAReqLifecycleGenerator.py
new file mode 100755 (executable)
index 0000000..5044792
--- /dev/null
@@ -0,0 +1,150 @@
+#! /usr/bin/python3
+import os
+import sys
+from generator_utils import *
+
+template = """// @{generatedby}@
+/* ///////////////////////// The MPI Bugs Initiative ////////////////////////
+
+  Origin: @{origin}@
+
+  Description: @{shortdesc}@
+    @{longdesc}@
+
+    Version of MPI: Conforms to MPI 1.1, does not require MPI 2 implementation
+
+BEGIN_MPI_FEATURES
+    P2P!basic: Lacking
+    P2P!nonblocking: Lacking
+    P2P!persistent: Lacking
+    COLL!basic: Lacking
+    COLL!nonblocking: Lacking
+    COLL!persistent: Lacking
+    COLL!tools: Lacking
+    RMA: @{rmafeature}@
+END_MPI_FEATURES
+
+BEGIN_MBI_TESTS
+  $ mpirun -np 2 ${EXE}
+  | @{outcome}@
+  | @{errormsg}@
+END_MBI_TESTS
+//////////////////////       End of MBI headers        /////////////////// */
+
+#include <mpi.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define N 20
+
+int main(int argc, char **argv) {
+  int rank, numProcs;
+
+  MPI_Init(&argc, &argv);
+  MPI_Comm_size(MPI_COMM_WORLD, &numProcs);
+  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+  if (numProcs < 2)
+    printf("MBI ERROR: This test needs at least 2 processes to produce a bug!\\n");
+
+  int *winbuf = malloc(N * sizeof(int));
+
+  MPI_Win win;
+  MPI_Win_create(winbuf, N * sizeof(int), 1, MPI_INFO_NULL, MPI_COMM_WORLD, &win);
+
+  MPI_Datatype type = MPI_INT;
+  int target = 1;
+
+  @{epoch}@
+
+  if (rank == 0) {
+    @{epoch2}@
+
+    @{init}@
+    @{operation}@
+
+    @{finEpoch2}@
+  }
+
+  @{finEpoch}@
+
+  MPI_Win_free(&win);
+
+  free(winbuf);
+
+  MPI_Finalize();
+
+  printf("Rank %d finished normally\\n", rank);
+  return 0;
+}
+"""
+
+
+for e1 in epoch:
+    for p in rma:
+        patterns = {}
+        patterns = {'e1': e1, 'p': p}
+        patterns['origin'] = "MPI-Corrbench"
+        patterns['generatedby'] = f'DO NOT EDIT: this file was generated by {os.path.basename(sys.argv[0])}. DO NOT EDIT.'
+        patterns['rmafeature'] = 'Yes'
+        patterns['p'] = p
+        patterns['e1'] = e1
+        patterns['epoch'] = epoch[e1]("1")
+        patterns['finEpoch'] = finEpoch[e1]("1")
+        patterns['epoch2'] = ""
+        patterns['finEpoch2'] = ""
+        patterns['init'] = init[p]("1")
+        patterns['operation'] = operation[p]("1")
+
+        # Generate a code correct
+        replace = patterns
+        replace['shortdesc'] = 'Correct code'
+        replace['longdesc'] = 'Correct code'
+        replace['outcome'] = 'OK'
+        replace['errormsg'] = 'OK'
+        make_file(template, f'ReqLifecycle_RMA_{e1}_{p}_ok.c', replace)
+
+        # Generate a code with missing open epoch
+        replace = patterns
+        replace['shortdesc'] = f"Request lifecycle, missing open {e1} epoch"
+        replace['longdesc'] = f"Request lifecycle, missing open {e1} epoch"
+        replace['outcome'] = 'ERROR: MissingStart'
+        replace['errormsg'] = '@{e1}@ at @{filename}@:@{line:MBIERROR}@ has missing'
+        replace['epoch'] = f"/* MBIERROR MISSING: {epoch[e1]('1')} */"
+        make_file(template, f'ReqLifecycle_RMA_MissingOpen_{e1}_{p}_nok.c', replace)
+
+        # Generate a code with missing close epoch
+        replace = patterns
+        replace['shortdesc'] = f"Request lifecycle, missing close {e1} epoch"
+        replace['longdesc'] = f"Request lifecycle, missing close {e1} epoch"
+        replace['outcome'] = 'ERROR: MissingWait'
+        replace['errormsg'] = '@{e1}@ at @{filename}@:@{line:MBIERROR}@ has missing'
+        replace['epoch'] = epoch[e1]("1")
+        replace['finEpoch'] = f"/* MBIERROR MISSING: {finEpoch[e1]('1')} */"
+        make_file(template, f'ReqLifecycle_RMA_MissingClose_{e1}_{p}_nok.c', replace)
+
+for e1 in epoch:
+    for e2 in epoch:
+        for p in rma:
+            patterns = {}
+            patterns = {'e1': e1, 'e2': e2, 'p': p}
+            patterns['origin'] = "MPI-Corrbench"
+            patterns['generatedby'] = f'DO NOT EDIT: this file was generated by {os.path.basename(sys.argv[0])}. DO NOT EDIT.'
+            patterns['rmafeature'] = 'Yes'
+            patterns['p'] = p
+            patterns['e1'] = e1
+            patterns['e2'] = e2
+            patterns['epoch'] = epoch[e1]("1")
+            patterns['finEpoch'] = finEpoch[e1]("1")
+            patterns['epoch2'] = epoch[e2]("1") + " /* MBIERROR */"
+            patterns['finEpoch2'] = finEpoch[e2]("1") + " /* MBIERROR */"
+            patterns['init'] = init[p]("1")
+            patterns['operation'] = operation[p]("1")
+
+            # Generate a code with epoch into an epoch
+            replace = patterns
+            replace['shortdesc'] = f"Request lifecycle, {e2} epoch into {e1} epoch"
+            replace['longdesc'] = f"Request lifecycle, {e2} epoch into {e1} epoch"
+            replace['outcome'] = 'ERROR: MissingWait' #FIXME: New type of error
+            replace['errormsg'] = '@{e2}@ at @{filename}@:@{line:MBIERROR}@ has in an other epoch'
+            make_file(template, f'ReqLifecycle_RMA_TwoEpoch_{e1}_{e2}_{p}_nok.c', replace)
diff --git a/teshsuite/smpi/MBI/RMAWinBufferGenerator.py b/teshsuite/smpi/MBI/RMAWinBufferGenerator.py
new file mode 100755 (executable)
index 0000000..5ed8b28
--- /dev/null
@@ -0,0 +1,121 @@
+#! /usr/bin/python3
+import os
+import sys
+from generator_utils import *
+
+template = """// @{generatedby}@
+/* ///////////////////////// The MPI Bugs Initiative ////////////////////////
+
+  Origin: @{origin}@
+
+  Description: @{shortdesc}@
+    @{longdesc}@
+
+
+BEGIN_MPI_FEATURES
+  P2P!basic: Lacking
+  P2P!nonblocking: Lacking
+  P2P!persistent: Lacking
+  COLL!basic: Lacking
+  COLL!nonblocking: Lacking
+  COLL!persistent: Lacking
+  COLL!tools: Lacking
+  RMA: @{rmafeature}@
+END_MPI_FEATURES
+
+BEGIN_MBI_TESTS
+  $ mpirun -np 2 ${EXE}
+  | @{outcome}@
+  | @{errormsg}@
+END_MBI_TESTS
+//////////////////////       End of MBI headers        /////////////////// */
+
+#include <mpi.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define N 10
+
+int * buffer;
+
+void get_win(MPI_Win *win) {
+  @{bufferalloc}@
+
+  MPI_Win_create(@{buffer}@, N * sizeof(int), 1, MPI_INFO_NULL, MPI_COMM_WORLD, win);
+
+  return;
+}
+
+int main(int argc, char *argv[]) {
+  int rank, numProcs;
+
+  MPI_Init(&argc, &argv);
+  MPI_Comm_size(MPI_COMM_WORLD, &numProcs);
+  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+  printf("Hello from rank %d \\n", rank);
+
+  if (numProcs < 2)
+    printf("MBI ERROR: This test needs at least 2 processes to produce a bug!\\n");
+
+  MPI_Win win;
+
+  get_win(&win);
+
+  MPI_Win_fence(0, win);
+
+  if (rank == 0) {
+    int localbuf[N] = {12345};
+    MPI_Put(&localbuf, N, MPI_INT, 1, 0, N, MPI_INT, win);
+  }
+
+  MPI_Win_fence(0, win);
+
+  MPI_Win_free(&win);
+
+  @{bufferfree}@
+
+  MPI_Finalize();
+  printf("Rank %d finished normally\\n", rank);
+  return 0;
+}
+
+"""
+
+
+for b in ['missing', 'null',  'malloc', 'bufferSize']:
+    patterns = {}
+    patterns = {'b': b}
+    patterns['origin'] = "MPI-CorrBench"
+    patterns['generatedby'] = f'DO NOT EDIT: this file was generated by {os.path.basename(sys.argv[0])}. DO NOT EDIT.'
+    patterns['rmafeature'] = 'Yes'
+
+    replace = patterns
+    replace['shortdesc'] = 'Invalid buffer in window creation.'
+    replace['longdesc'] = 'Invalid buffer in window creation.'
+    replace['outcome'] = 'ERROR: InvalidBuffer'
+    replace['errormsg'] = '@{b}@ at @{filename}@:@{line:MBIERROR}@ has an invalid buffer'
+    replace['bufferfree'] = ''
+
+    ok = 'nok'
+    replace['buffer'] = 'buffer'
+
+    if b == 'missing':
+        replace['bufferalloc'] = '/* MBIERROR1 */'
+        replace['longdesc'] = 'Uninitialized buffer in window creation.'
+    elif b == 'null':
+        replace['bufferalloc'] = 'buffer = NULL; /* MBIERROR1 */'
+        replace['longdesc'] = 'Use NULL buffer in window creation.'
+    elif b == 'bufferSize':
+        replace['bufferalloc'] = 'buffer = malloc((N/2) * sizeof(int)); /* MBIERROR1 */'
+        replace['bufferfree'] = 'free(buffer);'
+        replace['longdesc'] = 'Unmatched size of buffer in window creation.'
+    else:
+        replace['bufferalloc'] = 'buffer = malloc(N * sizeof(int));'
+        replace['bufferfree'] = 'free(buffer);'
+        replace['longdesc'] = 'Correct initialized buffer in window creation.'
+        replace['outcome'] = 'OK'
+        replace['errormsg'] = ''
+        ok = 'ok'
+
+    make_file(template, f'InvalidParam_WinBuffer_{b}_{ok}.c', replace)
index e344cbb..13fc716 100755 (executable)
@@ -3,6 +3,7 @@
 # Copyright 2021-2022. The MBI project. All rights reserved.
 # This program is free software; you can redistribute it and/or modify it under the terms of the license (GNU GPL).
 
+import os
 import sys
 from generator_utils import *
 
@@ -14,17 +15,17 @@ template = """// @{generatedby}@
   Description: @{shortdesc}@
     @{longdesc}@
 
-       Version of MPI: Conforms to MPI 1.1, does not require MPI 2 implementation
+  Version of MPI: Conforms to MPI 1.1, does not require MPI 2 implementation
 
 BEGIN_MPI_FEATURES
-       P2P!basic: Lacking
-       P2P!nonblocking: Lacking
-       P2P!persistent: Lacking
-       COLL!basic: Lacking
-       COLL!nonblocking: Lacking 
-       COLL!persistent: Lacking
-       COLL!tools: @{toolfeature}@
-       RMA: Lacking
+  P2P!basic: Lacking
+  P2P!nonblocking: Lacking
+  P2P!persistent: Lacking
+  COLL!basic: Lacking
+  COLL!nonblocking: Lacking
+  COLL!persistent: Lacking
+  COLL!tools: @{toolfeature}@
+  RMA: Lacking
 END_MPI_FEATURES
 
 BEGIN_MBI_TESTS
@@ -41,7 +42,7 @@ END_MBI_TESTS
 #define PARAM_PER_ITERATION 3
 #define PARAM_LOST_PER_ITERATION 1
 
-void myOp(int *invec, int *inoutvec, int *len, MPI_Datatype *dtype) {
+static void myOp(int *invec, int *inoutvec, int *len, MPI_Datatype *dtype) {
   for (int i = 0; i < *len; i++)
     inoutvec[i] += invec[i];
 }
@@ -49,8 +50,8 @@ void myOp(int *invec, int *inoutvec, int *len, MPI_Datatype *dtype) {
 int main(int argc, char **argv) {
   int nprocs = -1;
   int rank = -1;
-       int i=1, j=1, size=1;
-       int color =0;
+  int i=1, j=1, size=1;
+  int color =0;
 
   MPI_Init(&argc, &argv);
   MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
@@ -60,15 +61,15 @@ int main(int argc, char **argv) {
   if (nprocs < 2)
     printf("MBI ERROR: This test needs at least 2 processes to produce a bug!\\n");
 
-       @{change_size}@
+  @{change_size}@
   @{init}@
-       @{loop}@        
-  @{operation}@ 
-       @{cond}@        
-       @{fini}@
-       @{end}@ 
+  @{loop}@
+  @{operation}@
+  @{cond}@
+  @{fini}@
+  @{end}@
 
-       @{free}@
+  @{free}@
 
   MPI_Finalize();
   printf("Rank %d finished normally\\n", rank);
@@ -80,8 +81,8 @@ int main(int argc, char **argv) {
 for call in tcoll:
     patterns = {}
     patterns = {'call': call}
-    patterns['generatedby'] = f'DO NOT EDIT: this file was generated by {sys.argv[0]}. DO NOT EDIT.'
-    patterns['toolfeature'] = 'Yes' 
+    patterns['generatedby'] = f'DO NOT EDIT: this file was generated by {os.path.basename(sys.argv[0])}. DO NOT EDIT.'
+    patterns['toolfeature'] = 'Yes'
     patterns['call'] = call
     patterns['operation'] = operation[call]("1")
     patterns['init'] = init[call]("1")
@@ -95,8 +96,8 @@ for call in tcoll:
 
     # Generate the correct code
     replace = patterns
-    replace['shortdesc'] = '@{call}@ is correctly used' 
-    replace['longdesc'] = f'{call} correctly used' 
+    replace['shortdesc'] = '@{call}@ is correctly used'
+    replace['longdesc'] = f'{call} correctly used'
     replace['outcome'] = 'OK'
     replace['errormsg'] = ''
     make_file(template, f'ResLeak_{call}_ok.c', replace)
@@ -117,8 +118,8 @@ for call in tcoll:
     replace['outcome'] = f'ERROR: {error[call]}'
     replace['errormsg'] = 'Resleak. @{call}@ at @{filename}@:@{line:MBIERROR}@ lacks several free.'
     replace['change_size'] = 'size=PARAM_PER_ITERATION;'
-    replace['loop'] = 'for (i = 0; i < ITERATIONS; i++) {\n            for (j = 0; j < PARAM_PER_ITERATION; j++) {'
-    replace['cond'] = '                        if (j < PARAM_PER_ITERATION - PARAM_LOST_PER_ITERATION) {'
+    replace['loop'] = 'for (i = 0; i < ITERATIONS; i++) {\n    for (j = 0; j < PARAM_PER_ITERATION; j++) {'
+    replace['cond'] = '      if (j < PARAM_PER_ITERATION - PARAM_LOST_PER_ITERATION) {'
     replace['fini'] = fini[call]("1") + ' /* MBIERROR */'
-    replace['end'] = '                 }\n             }\n     }'
+    replace['end'] = '      }\n     }\n   }'
     make_file(template, f'ResLeak_multiple_{call}_nok.c', replace)
index 3ef5d5c..8e5444c 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright 2021-2022. The MBI project. All rights reserved. 
+# Copyright 2021-2022. The MBI project. All rights reserved.
 # This program is free software; you can redistribute it and/or modify it under the terms of the license (GNU GPL).
 
 # This is a simple templating system, dedicated to the systematic generation of MPI source code
@@ -15,30 +15,28 @@ icoll4op = ['MPI_Ireduce', 'MPI_Iallreduce']
 coll4root =  ['MPI_Reduce', 'MPI_Bcast', 'MPI_Gather', 'MPI_Scatter']
 icoll4root = ['MPI_Ireduce', 'MPI_Ibcast', 'MPI_Igather', 'MPI_Iscatter']
 pcoll = []
-tcoll = ['MPI_Comm_split', 'MPI_Op_create', 'MPI_Comm_group', 'MPI_Comm_dup', 'MPI_Type_contiguous', 'MPI_Comm_create', 'MPI_Group_excl']
-tcoll4color = ['MPI_Comm_split'] 
+tcoll = ['MPI_Comm_split', 'MPI_Op_create', 'MPI_Comm_dup', 'MPI_Type_contiguous', 'MPI_Comm_create', 'MPI_Group_excl'] # MPI_Comm_dup removed
+tcoll4color = ['MPI_Comm_split']
 tcoll4topo = ['MPI_Cart_get']
 
 # P2P
 allsend = ['MPI_Send', 'MPI_Isend', 'MPI_Ssend', 'MPI_Bsend','MPI_Send_init']
-allrecv = ['MPI_Recv', 'MPI_Irecv', 'MPI_Recv_init'] 
+allrecv = ['MPI_Recv', 'MPI_Irecv', 'MPI_Recv_init']
 send = ['MPI_Send']
 ssend = ['MPI_Ssend']
 bsend = ['MPI_Bsend']
 isend = ['MPI_Isend']
 psend = ['MPI_Send_init']
-recv = ['MPI_Recv'] 
-irecv = ['MPI_Irecv'] 
-precv = ['MPI_Recv_init'] 
+recv = ['MPI_Recv']
+irecv = ['MPI_Irecv']
+precv = ['MPI_Recv_init']
 probe = ['MPI_Probe']
 
 # RMA
 epoch = ['MPI_Win_fence', 'MPI_Win_lock', 'MPI_Win_lock_all']
 rma = ['MPI_Get', 'MPI_Put']
 get = ['MPI_Get']
-rget = ['MPI_RGet']
-put = ['MPI_Put'] 
-rput = ['MPI_RPut'] 
+put = ['MPI_Put']
 store = ['store']
 load = ['load']
 rstore = ['rstore']
@@ -51,7 +49,7 @@ init = {}
 start = {}
 operation = {}
 fini = {}
-free = {} 
+free = {}
 write = {}
 error = {}
 epoch = {}
@@ -117,11 +115,11 @@ free['MPI_Exscan'] = lambda n: ""
 write['MPI_Exscan'] = lambda n: ""
 
 init['MPI_Allgather'] = lambda n: f"int val{n}=1, *rbuf{n} = (int*)malloc(dbs);"
-start['MPI_Allgather'] = lambda n: "" 
+start['MPI_Allgather'] = lambda n: ""
 operation['MPI_Allgather'] = lambda n: f"MPI_Allgather(&val{n}, 1, type, rbuf{n}, 1, type, newcom);"
 fini['MPI_Allgather'] = lambda n: ""
-free['MPI_Allgather'] = lambda n: f"free(rbuf{n});" 
-write['MPI_Allgather'] = lambda n: "" 
+free['MPI_Allgather'] = lambda n: f"free(rbuf{n});"
+write['MPI_Allgather'] = lambda n: ""
 
 init['MPI_Alltoallv'] = lambda n: (f"int *sbuf{n}=(int*)malloc(dbs*2), *rbuf{n}=(int*)malloc(dbs*2), *scounts{n}=(int*)malloc(dbs), *rcounts{n}=(int*)malloc(dbs), *sdispls{n}=(int*)malloc(dbs), *rdispls{n}=(int*)malloc(dbs);\n"
   +  "  for (int i = 0; i < nprocs; i++) {\n"
@@ -130,29 +128,29 @@ init['MPI_Alltoallv'] = lambda n: (f"int *sbuf{n}=(int*)malloc(dbs*2), *rbuf{n}=
   + f"    sdispls{n}[i] = (nprocs - (i + 1)) * 2;\n"
   + f"    rdispls{n}[i] = i * 2;\n"
   +  "  }")
-start['MPI_Alltoallv'] = lambda n: "" 
+start['MPI_Alltoallv'] = lambda n: ""
 operation['MPI_Alltoallv'] = lambda n: f"MPI_Alltoallv(sbuf{n}, scounts{n}, sdispls{n}, type, rbuf{n}, rcounts{n}, rdispls{n}, type, newcom);"
-fini['MPI_Alltoallv'] = lambda n: "" 
+fini['MPI_Alltoallv'] = lambda n: ""
 free['MPI_Alltoallv'] = lambda n: f"free(sbuf{n});free(rbuf{n});free(scounts{n});free(rcounts{n});free(sdispls{n});free(rdispls{n});"
-write['MPI_Alltoallv'] = lambda n: "" 
+write['MPI_Alltoallv'] = lambda n: ""
 
 init['MPI_Alltoall'] = lambda n: f"int *sbuf{n} = (int*)malloc(dbs), *rbuf{n} = (int*)malloc(dbs);"
-start['MPI_Alltoall'] = lambda n: "" 
+start['MPI_Alltoall'] = lambda n: ""
 operation['MPI_Alltoall'] = lambda n: f"MPI_Alltoall(sbuf{n}, 1, type, rbuf{n}, 1, type, newcom);"
-fini['MPI_Alltoall'] = lambda n: "" 
+fini['MPI_Alltoall'] = lambda n: ""
 free['MPI_Alltoall'] = lambda n: f"free(sbuf{n});free(rbuf{n});"
-write['MPI_Alltoall'] = lambda n: "" 
+write['MPI_Alltoall'] = lambda n: ""
 
-init['MPI_Allgatherv'] = lambda n: (f"int *rbuf{n} = (int*)malloc(dbs*2), *rcounts{n}=(int*)malloc(dbs),  *displs{n}=(int*)malloc(dbs);\n" 
+init['MPI_Allgatherv'] = lambda n: (f"int *rbuf{n} = (int*)malloc(dbs*2), *rcounts{n}=(int*)malloc(dbs),  *displs{n}=(int*)malloc(dbs);\n"
   +  "  for (int i = 0; i < nprocs; i++) {\n"
   + f"    rcounts{n}[i] = 1;\n"
   + f"    displs{n}[i] = 2 * (nprocs - (i + 1));\n"
   +  "  }")
-start['MPI_Allgatherv'] = lambda n: "" 
+start['MPI_Allgatherv'] = lambda n: ""
 operation['MPI_Allgatherv'] = lambda n: f"MPI_Allgatherv(&rank, 1, type, rbuf{n}, rcounts{n}, displs{n}, type, newcom);"
-fini['MPI_Allgatherv'] = lambda n: "" 
+fini['MPI_Allgatherv'] = lambda n: ""
 free['MPI_Allgatherv'] = lambda n: f"free(rbuf{n});free(rcounts{n});free(displs{n});"
-write['MPI_Allgatherv'] = lambda n: "" 
+write['MPI_Allgatherv'] = lambda n: ""
 
 
 ### COLL:nonblocking
@@ -167,7 +165,7 @@ write['MPI_Ibarrier'] = lambda n: ""
 init['MPI_Ireduce'] = lambda n: f"MPI_Request req{n}=MPI_REQUEST_NULL; MPI_Status stat{n}; int sum{n}, val{n} = 1;"
 start['MPI_Ireduce'] = lambda n: ""
 operation['MPI_Ireduce'] = lambda n: f"MPI_Ireduce(&val{n}, &sum{n}, 1, type, op, root, newcom, &req{n});"
-fini['MPI_Ireduce'] = lambda n: f"MPI_Wait(&req{n}, &stat{n});" 
+fini['MPI_Ireduce'] = lambda n: f"MPI_Wait(&req{n}, &stat{n});"
 free['MPI_Ireduce'] = lambda n: f'if(req{n} != MPI_REQUEST_NULL) MPI_Request_free(&req{n});'
 write['MPI_Ireduce'] = lambda n: f"sum{n}++;"
 
@@ -186,11 +184,11 @@ free['MPI_Ibcast'] = lambda n: f'if(req{n} != MPI_REQUEST_NULL) MPI_Request_free
 write['MPI_Ibcast'] = lambda n: f'buf{n}[0]++;'
 
 init['MPI_Igather'] = lambda n: f"int val{n}=1, buf{n}[buff_size];MPI_Request req{n}=MPI_REQUEST_NULL;MPI_Status sta{n};"
-start['MPI_Igather'] = lambda n: "" 
+start['MPI_Igather'] = lambda n: ""
 operation['MPI_Igather'] = lambda n: f'MPI_Igather(&val{n}, 1, type, &buf{n},1, type, root, newcom, &req{n});'
 write['MPI_Igather'] = lambda n: f'val{n}=3;'
 fini['MPI_Igather'] = lambda n: f'MPI_Wait(&req{n},&sta{n});'
-free['MPI_Igather'] = lambda n: f'if(req{n} != MPI_REQUEST_NULL) MPI_Request_free(&req{n});' 
+free['MPI_Igather'] = lambda n: f'if(req{n} != MPI_REQUEST_NULL) MPI_Request_free(&req{n});'
 
 init['MPI_Iscatter'] = lambda n: f"MPI_Request req{n}=MPI_REQUEST_NULL;MPI_Status sta{n};int val{n}, buf{n}[buff_size];"
 start['MPI_Iscatter'] = lambda n: ""
@@ -214,25 +212,25 @@ free['MPI_Iexscan'] = lambda n: f'if(req{n} != MPI_REQUEST_NULL) MPI_Request_fre
 write['MPI_Iexscan'] = lambda n: f'outbuf{n}[0]++;'
 
 init['MPI_Iallgather'] = lambda n: f"MPI_Request req{n}=MPI_REQUEST_NULL;MPI_Status sta{n};int val{n}=1, *rbuf{n} = (int*)malloc(dbs);"
-start['MPI_Iallgather'] = lambda n: "" 
+start['MPI_Iallgather'] = lambda n: ""
 operation['MPI_Iallgather'] = lambda n: f"MPI_Iallgather(&val{n}, 1, type, rbuf{n}, 1, type, newcom,&req{n});"
 fini['MPI_Iallgather'] = lambda n: f"MPI_Wait(&req{n},&sta{n});"
-free['MPI_Iallgather'] = lambda n: f"free(rbuf{n});" 
+free['MPI_Iallgather'] = lambda n: f"free(rbuf{n});"
 write['MPI_Iallgather'] = lambda n: f'val{n}++;'
 
-init['MPI_Iallgatherv'] = lambda n: (f"MPI_Request req{n}=MPI_REQUEST_NULL;MPI_Status sta{n};int *rbuf{n} = (int*)malloc(dbs*2), *rcounts{n}=(int*)malloc(dbs),  *displs{n}=(int*)malloc(dbs);\n" 
+init['MPI_Iallgatherv'] = lambda n: (f"MPI_Request req{n}=MPI_REQUEST_NULL;MPI_Status sta{n};int *rbuf{n} = (int*)malloc(dbs*2), *rcounts{n}=(int*)malloc(dbs),  *displs{n}=(int*)malloc(dbs);\n"
   +  "  for (int i = 0; i < nprocs; i++) {\n"
   + f"    rcounts{n}[i] = 1;\n"
   + f"    displs{n}[i] = 2 * (nprocs - (i + 1));\n"
   +  "  }")
-start['MPI_Iallgatherv'] = lambda n: "" 
+start['MPI_Iallgatherv'] = lambda n: ""
 operation['MPI_Iallgatherv'] = lambda n: f"MPI_Iallgatherv(&rank, 1, type, rbuf{n}, rcounts{n}, displs{n}, type, newcom,&req{n});"
-fini['MPI_Iallgatherv'] = lambda n: f"MPI_Wait(&req{n},&sta{n});" 
+fini['MPI_Iallgatherv'] = lambda n: f"MPI_Wait(&req{n},&sta{n});"
 free['MPI_Iallgatherv'] = lambda n: f"free(rbuf{n});free(rcounts{n});free(displs{n});"
-write['MPI_Iallgatherv'] = lambda n: f"rbuf{n}[0]++;" 
+write['MPI_Iallgatherv'] = lambda n: f"rbuf{n}[0]++;"
 
 init['MPI_Ialltoall'] = lambda n: f"MPI_Request req{n}=MPI_REQUEST_NULL;MPI_Status sta{n};int *sbuf{n} = (int*)malloc(dbs), *rbuf{n} = (int*)malloc(dbs);"
-start['MPI_Ialltoall'] = lambda n: "" 
+start['MPI_Ialltoall'] = lambda n: ""
 operation['MPI_Ialltoall'] = lambda n: f"MPI_Ialltoall(sbuf{n}, 1, type, rbuf{n}, 1, type, newcom, &req{n});"
 fini['MPI_Ialltoall'] = lambda n: f"MPI_Wait(&req{n},&sta{n});"
 free['MPI_Ialltoall'] = lambda n: f"free(sbuf{n});free(rbuf{n});"
@@ -245,7 +243,7 @@ init['MPI_Ialltoallv'] = lambda n: (f"MPI_Request req{n}=MPI_REQUEST_NULL;MPI_St
   + f"    sdispls{n}[i] = (nprocs - (i + 1)) * 2;\n"
   + f"    rdispls{n}[i] = i * 2;\n"
   +  "  }")
-start['MPI_Ialltoallv'] = lambda n: "" 
+start['MPI_Ialltoallv'] = lambda n: ""
 operation['MPI_Ialltoallv'] = lambda n: f"MPI_Ialltoallv(sbuf{n}, scounts{n}, sdispls{n}, type, rbuf{n}, rcounts{n}, rdispls{n}, type, newcom,&req{n});"
 fini['MPI_Ialltoallv'] = lambda n: f"MPI_Wait(&req{n},&sta{n});"
 free['MPI_Ialltoallv'] = lambda n: f"free(sbuf{n});free(rbuf{n});free(scounts{n});free(rcounts{n});free(sdispls{n});free(rdispls{n});"
@@ -283,10 +281,10 @@ init['MPI_Comm_group'] = lambda n: 'MPI_Group grp[size];'
 operation['MPI_Comm_group'] = lambda n: 'MPI_Comm_group(MPI_COMM_WORLD, &grp[j]);'
 error['MPI_Comm_group'] = 'GroupLeak'
 fini['MPI_Comm_group'] = lambda n: "MPI_Group_free(&grp[j]);"
-free['MPI_Comm_group'] = lambda n: "" 
+free['MPI_Comm_group'] = lambda n: ""
 
 init['MPI_Group_excl'] = lambda n: 'MPI_Group worldgroup, grp[size];\n MPI_Comm_group(MPI_COMM_WORLD, &worldgroup);'
-operation['MPI_Group_excl'] = lambda n: 'MPI_Group_excl(worldgroup, 1, &rank, &grp[j]);' 
+operation['MPI_Group_excl'] = lambda n: 'MPI_Group_excl(worldgroup, 1, &rank, &grp[j]);'
 error['MPI_Group_excl'] = 'GroupLeak'
 fini['MPI_Group_excl'] = lambda n: "MPI_Group_free(&grp[j]);"
 free['MPI_Group_excl'] = lambda n: "MPI_Group_free(&worldgroup);"
@@ -301,18 +299,18 @@ init['MPI_Comm_dup'] = lambda n: f'MPI_Comm com[size];'
 operation['MPI_Comm_dup'] = lambda n: 'MPI_Comm_dup(MPI_COMM_WORLD, &com[j]);'
 error['MPI_Comm_dup'] = 'CommunicatorLeak'
 fini['MPI_Comm_dup'] = lambda n: "MPI_Comm_free(&com[j]);"
-free['MPI_Comm_dup'] = lambda n: "" 
+free['MPI_Comm_dup'] = lambda n: ""
 
 init['MPI_Type_contiguous'] = lambda n: 'MPI_Datatype type[size];'
 operation['MPI_Type_contiguous'] = lambda n: 'MPI_Type_contiguous(2, MPI_DOUBLE, &type[j]);'
 error['MPI_Type_contiguous'] = 'TypeLeak'
 fini['MPI_Type_contiguous'] = lambda n: "MPI_Type_free(&type[j]);"
-free['MPI_Type_contiguous'] = lambda n: "" 
+free['MPI_Type_contiguous'] = lambda n: ""
 
 
 
 
-### P2P:basic 
+### P2P:basic
 
 init['MPI_Send'] = lambda n: f'int buf{n}=rank;'
 start['MPI_Send'] = lambda n: ""
@@ -329,7 +327,7 @@ free['MPI_Ssend'] = lambda n: ""
 write['MPI_Ssend'] = lambda n: ""
 
 init['MPI_Bsend'] = lambda n: (f'int buf{n}=rank;\n'
-            + f'int buffer_attached_size{n} = MPI_BSEND_OVERHEAD + sizeof(int);\n' 
+            + f'int buffer_attached_size{n} = MPI_BSEND_OVERHEAD + sizeof(int);\n'
             + f'char* buffer_attached{n} = (char*)malloc(buffer_attached_size{n});\n'
             + f'MPI_Buffer_attach(buffer_attached{n}, buffer_attached_size{n});')
 start['MPI_Bsend'] = lambda n: ""
@@ -358,34 +356,34 @@ write['MPI_Probe'] = lambda n: ""
 ### P2P:nonblocking
 
 init['MPI_Isend'] = lambda n: f'int buf{n}=rank; MPI_Request req{n}=MPI_REQUEST_NULL;'
-start['MPI_Isend'] = lambda n: "" 
+start['MPI_Isend'] = lambda n: ""
 operation['MPI_Isend'] = lambda n: f'MPI_Isend(&buf{n}, buff_size, type, dest, stag, newcom, &req{n});'
 fini['MPI_Isend'] = lambda n: f'MPI_Wait(&req{n}, MPI_STATUS_IGNORE);'
 free['MPI_Isend'] = lambda n: f'if(req{n} != MPI_REQUEST_NULL) MPI_Request_free(&req{n});'
 write['MPI_Isend'] = lambda n: f'buf{n}=4;'
 
 init['MPI_Irecv'] = lambda n: f'int buf{n}=-1; MPI_Request req{n}=MPI_REQUEST_NULL;'
-start['MPI_Irecv'] = lambda n: "" 
+start['MPI_Irecv'] = lambda n: ""
 operation['MPI_Irecv'] = lambda n: f'MPI_Irecv(&buf{n}, buff_size, type, src, rtag, newcom, &req{n});'
 fini['MPI_Irecv'] = lambda n: f' MPI_Wait(&req{n}, MPI_STATUS_IGNORE);'
 free['MPI_Irecv'] = lambda n: f'if(req{n} != MPI_REQUEST_NULL) MPI_Request_free(&req{n});'
-write['MPI_Irecv'] = lambda n: f'buf{n}++;' 
+write['MPI_Irecv'] = lambda n: f'buf{n}++;'
 
 ### P2P:persistent
 
 init['MPI_Send_init'] = lambda n: f'int buf{n}=rank; MPI_Request req{n}=MPI_REQUEST_NULL;'
-operation['MPI_Send_init'] = lambda n: f'MPI_Send_init(&buf{n}, buff_size, type, dest, stag, newcom, &req{n});' 
+operation['MPI_Send_init'] = lambda n: f'MPI_Send_init(&buf{n}, buff_size, type, dest, stag, newcom, &req{n});'
 start['MPI_Send_init'] = lambda n: f'MPI_Start(&req{n});'
 fini['MPI_Send_init'] = lambda n: f'MPI_Wait(&req{n}, MPI_STATUS_IGNORE);'
 free['MPI_Send_init'] = lambda n: f'if(req{n} != MPI_REQUEST_NULL) MPI_Request_free(&req{n});'
-write['MPI_Send_init'] = lambda n: f'buf{n}=4;' 
+write['MPI_Send_init'] = lambda n: f'buf{n}=4;'
 
 init['MPI_Recv_init'] = lambda n: f'int buf{n}=-1; MPI_Request req{n}=MPI_REQUEST_NULL;'
 start['MPI_Recv_init'] = lambda n: f'MPI_Start(&req{n});'
 operation['MPI_Recv_init'] = lambda n: f'MPI_Recv_init(&buf{n}, buff_size, type, src, rtag, newcom, &req{n});'
 fini['MPI_Recv_init'] = lambda n: f'MPI_Wait(&req{n}, MPI_STATUS_IGNORE);'
 free['MPI_Recv_init'] = lambda n: f'if(req{n} != MPI_REQUEST_NULL) MPI_Request_free(&req{n});'
-write['MPI_Recv_init'] = lambda n: f'buf{n}++;' 
+write['MPI_Recv_init'] = lambda n: f'buf{n}++;'
 
 ### RMA
 
@@ -396,32 +394,26 @@ finEpoch['MPI_Win_lock'] =lambda n: 'MPI_Win_unlock(target, win);'
 epoch['MPI_Win_lock_all'] =lambda n: 'MPI_Win_lock_all(0,win);'
 finEpoch['MPI_Win_lock_all'] =lambda n: 'MPI_Win_unlock_all(win);'
 
-init['MPI_Put'] = lambda n: f'int localbuf{n} = 12345;'
+init['MPI_Put'] = lambda n: f'int localbuf{n}[N] = {{12345}};'
 operation['MPI_Put'] = lambda n: f'MPI_Put(&localbuf{n}, N, MPI_INT, target, 0, N, type, win);'
 
-init['MPI_RPut'] = lambda n: "" 
-operation['MPI_RPut'] = lambda n: f'MPI_Put(&winbuf[20], N, MPI_INT, target, 0, N, type, win);'
+init['MPI_Get'] = lambda n: f'int localbuf{n}[N] = {{54321}};'
+operation['MPI_Get'] = lambda n: f'MPI_Get(&localbuf{n}, N, MPI_INT, target, 0, N, type, win);'
 
-init['MPI_Get'] = lambda n: f'int localbuf{n} = 54321;'
-operation['MPI_Get'] = lambda n: f'MPI_Get(&localbuf{n}, N, MPI_INT, target, 0, N, type, win);' 
-
-init['MPI_RGet'] = lambda n: ""
-operation['MPI_RGet'] = lambda n: f'MPI_Get(&winbuf[20], N, MPI_INT, target, 0, N, type, win);' 
-
-init['store'] = lambda n: f'int localbuf{n} = 0;'
-operation['store'] = lambda n: f'localbuf{n} = 8;'
+init['store'] = lambda n: f'int localbuf{n}[N] = {{0}};'
+operation['store'] = lambda n: f'localbuf{n}[0] = 8;'
 
 init['rstore'] = lambda n: ""
 operation['rstore'] = lambda n: f'winbuf[20] = 12346;'
 
-init['load'] = lambda n: f'int localbuf{n} = 0;'
-operation['load'] = lambda n: f'int load = localbuf{n};'
+init['load'] = lambda n: f'int localbuf{n}[N] = {{0}};'
+operation['load'] = lambda n: f'int load = localbuf{n}[0];'
 
-init['rload'] = lambda n: "" 
+init['rload'] = lambda n: ""
 operation['rload'] = lambda n: "int load = winbuf[20];"
 
-init['loadstore'] = lambda n: f'int localbuf{n} = 0;'
-operation['loadstore'] = lambda n: f'if (localbuf{n} % 2 == 0)  localbuf{n}++; '
+init['loadstore'] = lambda n: f'int localbuf{n}[N] = {{0}};'
+operation['loadstore'] = lambda n: f'if (localbuf{n}[0] % 2 == 0)  localbuf{n}[0]++; '
 
 
 
index 049ece1..8d84521 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright 2021-2022. The MBI project. All rights reserved. 
+# Copyright 2021-2022. The MBI project. All rights reserved.
 # This program is free software; you can redistribute it and/or modify it under the terms of the license (GNU GPL).
 
 import re
@@ -37,8 +37,8 @@ class Tool(AbstractTool):
         os.environ['PATH'] = os.environ['PATH'] + ":" + rootdir + "/builds/SimGrid/bin"
         os.environ['VERBOSE'] = '1'
 
-    def run(self, execcmd, filename, binary, id, timeout, batchinfo):
-        cachefile = f'{binary}_{id}'
+    def run(self, execcmd, filename, binary, num_id, timeout, batchinfo):
+        cachefile = f'{binary}_{num_id}'
 
         if not os.path.exists("cluster.xml"):
             with open('cluster.xml', 'w') as outfile:
@@ -49,8 +49,6 @@ class Tool(AbstractTool):
                 outfile.write('</platform>\n')
 
         execcmd = execcmd.replace("mpirun", "smpirun -wrapper simgrid-mc -platform ./cluster.xml -analyze --cfg=smpi/finalization-barrier:on --cfg=smpi/list-leaks:10 --cfg=model-check/max-depth:10000")
-        if re.search("Concurrency", binary):  # DPOR reduction in simgrid cannot deal with RMA calls as they contain mutexes
-            execcmd = execcmd.replace("smpirun", "smpirun --cfg=model-check/reduction:none")
         execcmd = execcmd.replace('${EXE}', binary)
         execcmd = execcmd.replace('$zero_buffer', "--cfg=smpi/buffering:zero")
         execcmd = execcmd.replace('$infty_buffer', "--cfg=smpi/buffering:infty")
@@ -64,9 +62,9 @@ class Tool(AbstractTool):
             timeout=timeout,
             batchinfo=batchinfo)
 
-    def teardown(self): 
+    def teardown(self):
         subprocess.run("find -type f -a -executable | xargs rm -f", shell=True, check=True) # Remove generated cruft (binary files)
-        subprocess.run("rm -f smpitmp-* core", shell=True, check=True) 
+        subprocess.run("rm -f smpitmp-* core", shell=True, check=True)
 
     def parse(self, cachefile):
         if os.path.exists(f'{cachefile}.timeout') or os.path.exists(f'logs/simgrid/{cachefile}.timeout'):
@@ -86,6 +84,9 @@ class Tool(AbstractTool):
         if re.search('MC is currently not supported here', output):
             return 'failure'
 
+        if re.search('Collective communication mismatch', output):
+            return 'Collective mismatch'
+
         if re.search('DEADLOCK DETECTED', output):
             return 'deadlock'
         if re.search('returned MPI_ERR', output):
index 25c5561..8c55e68 100644 (file)
@@ -18,13 +18,13 @@ $ $VALGRIND_NO_LEAK_CHECK ${bindir:=.}/../../../smpi_script/bin/smpirun -map -ho
 > [0.000000] [smpi/INFO] [rank 13] -> Ginette
 > [0.000000] [smpi/INFO] [rank 14] -> Ginette
 > [0.000000] [smpi/INFO] [rank 15] -> Ginette
-> [0.023780] [smpi_utils/INFO] Probable memory leaks in your code: SMPI detected 32 unfreed MPI handles:
-> [0.023780] [smpi_utils/INFO] 16 leaked handles of type MPI_Comm at coll-allreduce-with-leaks.c:23
-> [0.023780] [smpi_utils/INFO] 16 leaked handles of type MPI_Group at coll-allreduce-with-leaks.c:23
-> [0.023780] [smpi_utils/INFO] Probable memory leaks in your code: SMPI detected 32 unfreed buffers:
-> [0.023780] [smpi_utils/INFO] coll-allreduce-with-leaks.c:28: leaked allocations of total size 1504, called 16 times, with minimum size 64 and maximum size 124
-> [0.023780] [smpi_utils/INFO] coll-allreduce-with-leaks.c:27: leaked allocations of total size 1024, called 16 times, each with size 64
-> [0.023780] [smpi_utils/INFO] Memory Usage: Simulated application allocated 2528 bytes during its lifetime through malloc/calloc calls.
+> [0.015765] [smpi_utils/INFO] Probable memory leaks in your code: SMPI detected 32 unfreed MPI handles:
+> [0.015765] [smpi_utils/INFO] 16 leaked handles of type MPI_Comm at coll-allreduce-with-leaks.c:23
+> [0.015765] [smpi_utils/INFO] 16 leaked handles of type MPI_Group at coll-allreduce-with-leaks.c:23
+> [0.015765] [smpi_utils/INFO] Probable memory leaks in your code: SMPI detected 32 unfreed buffers:
+> [0.015765] [smpi_utils/INFO] coll-allreduce-with-leaks.c:28: leaked allocations of total size 1504, called 16 times, with minimum size 64 and maximum size 124
+> [0.015765] [smpi_utils/INFO] coll-allreduce-with-leaks.c:27: leaked allocations of total size 1024, called 16 times, each with size 64
+> [0.015765] [smpi_utils/INFO] Memory Usage: Simulated application allocated 2528 bytes during its lifetime through malloc/calloc calls.
 > Largest allocation at once from a single process was 124 bytes, at coll-allreduce-with-leaks.c:28. It was called 1 times during the whole simulation.
 > If this is too much, consider sharing allocations for computation buffers.
 > This can be done automatically by setting --cfg=smpi/auto-shared-malloc-thresh to the minimum size wanted size (this can alter execution if data content is necessary)
index a5f2183..4ffce51 100644 (file)
@@ -17,28 +17,6 @@ $ $VALGRIND_NO_LEAK_CHECK ${bindir:=.}/../../../smpi_script/bin/smpirun -wrapper
 > Largest allocation at once from a single process was 28 bytes, at coll-allreduce-with-leaks.c:28. It was called 1 times during the whole simulation.
 > If this is too much, consider sharing allocations for computation buffers.
 > This can be done automatically by setting --cfg=smpi/auto-shared-malloc-thresh to the minimum size wanted size (this can alter execution if data content is necessary)
->
-> [0.000000] [smpi_utils/INFO] Probable memory leaks in your code: SMPI detected 8 unfreed MPI handles:
-> [0.000000] [smpi_utils/WARNING] To get more information (location of allocations), compile your code with -trace-call-location flag of smpicc/f90
-> [0.000000] [smpi_utils/INFO] 4 leaked handles of type MPI_Comm
-> [0.000000] [smpi_utils/INFO] 4 leaked handles of type MPI_Group
-> [0.000000] [smpi_utils/INFO] Probable memory leaks in your code: SMPI detected 8 unfreed buffers:
-> [0.000000] [smpi_utils/INFO] leaked allocations of total size 152, called 8 times, with minimum size 16 and maximum size 28
-> [0.000000] [smpi_utils/INFO] Memory Usage: Simulated application allocated 152 bytes during its lifetime through malloc/calloc calls.
-> Largest allocation at once from a single process was 28 bytes, at coll-allreduce-with-leaks.c:28. It was called 1 times during the whole simulation.
-> If this is too much, consider sharing allocations for computation buffers.
-> This can be done automatically by setting --cfg=smpi/auto-shared-malloc-thresh to the minimum size wanted size (this can alter execution if data content is necessary)
->
-> [0.000000] [smpi_utils/INFO] Probable memory leaks in your code: SMPI detected 8 unfreed MPI handles:
-> [0.000000] [smpi_utils/WARNING] To get more information (location of allocations), compile your code with -trace-call-location flag of smpicc/f90
-> [0.000000] [smpi_utils/INFO] 4 leaked handles of type MPI_Comm
-> [0.000000] [smpi_utils/INFO] 4 leaked handles of type MPI_Group
-> [0.000000] [smpi_utils/INFO] Probable memory leaks in your code: SMPI detected 8 unfreed buffers:
-> [0.000000] [smpi_utils/INFO] leaked allocations of total size 152, called 8 times, with minimum size 16 and maximum size 28
-> [0.000000] [smpi_utils/INFO] Memory Usage: Simulated application allocated 152 bytes during its lifetime through malloc/calloc calls.
-> Largest allocation at once from a single process was 28 bytes, at coll-allreduce-with-leaks.c:28. It was called 1 times during the whole simulation.
-> If this is too much, consider sharing allocations for computation buffers.
-> This can be done automatically by setting --cfg=smpi/auto-shared-malloc-thresh to the minimum size wanted size (this can alter execution if data content is necessary)
 > 
 > [0.000000] [smpi_utils/INFO] Probable memory leaks in your code: SMPI detected 8 unfreed MPI handles:
 > [0.000000] [smpi_utils/WARNING] To get more information (location of allocations), compile your code with -trace-call-location flag of smpicc/f90
@@ -51,4 +29,4 @@ $ $VALGRIND_NO_LEAK_CHECK ${bindir:=.}/../../../smpi_script/bin/smpirun -wrapper
 > If this is too much, consider sharing allocations for computation buffers.
 > This can be done automatically by setting --cfg=smpi/auto-shared-malloc-thresh to the minimum size wanted size (this can alter execution if data content is necessary)
 > 
-> [0.000000] [mc_dfs/INFO] DFS exploration ended. 73 unique states visited; 18 backtracks (592 transition replays, 502 states visited overall)
+> [0.000000] [mc_dfs/INFO] DFS exploration ended. 33 unique states visited; 7 backtracks (140 transition replays, 101 states visited overall)
index ed293d2..f58c024 100755 (executable)
@@ -161,7 +161,7 @@ foreach $_ (@ARGV) {
     elsif (/--?platformfile=(.*)/) { $platformfile = $1; }
     elsif (/--?hostfile=(.*)/) { $hostfile = $1; }
     elsif (/--?srcdir=(.*)/) { $srcdir = $1;
-       $mpiexec="$mpiexec  -platform ${srcdir}/$platformfile -hostfile ${srcdir}/$hostfile --log=root.thr:critical --log=smpi_kernel.thr:warning --cfg=smpi/host-speed:1e9f  --cfg=smpi/async-small-thresh:65536"; }
+       $mpiexec="$mpiexec  -platform ${srcdir}/$platformfile -hostfile ${srcdir}/$hostfile --log=root.thr:critical --log=smpi_kernel.thr:warning --cfg=smpi/host-speed:1e9f  --cfg=smpi/async-small-thresh:65536 --cfg=smpi/os:1:0.0000003:0.0000002 --cfg=smpi/ois:1:0.0000003:0.0000002"; }
     elsif (/--?verbose/) { $verbose = 1; }
     elsif (/--?showprogress/) { $showProgress = 1; }
     elsif (/--?debug/) { $debug = 1; }
index 6b240b2..91c8915 100755 (executable)
@@ -72,7 +72,7 @@ cmake -Denable_documentation=OFF \
       -Denable_ns3=ON \
       -Denable_smpi=ON -Denable_smpi_MPICH3_testsuite=ON -Denable_model-checking=ON \
       -Denable_smpi_papi=ON \
-      -Denable_memcheck=OFF -Denable_memcheck_xml=OFF -Denable_smpi_MBI_testsuite=OFF \
+      -Denable_memcheck=OFF -Denable_memcheck_xml=OFF -Denable_smpi_MBI_testsuite=ON \
       -Denable_coverage=ON -DLTO_EXTRA_FLAG="auto" -DCMAKE_EXPORT_COMPILE_COMMANDS=ON "$WORKSPACE"
 
 #build with sonarqube scanner wrapper
@@ -110,7 +110,7 @@ if [ -f Testing/TAG ] ; then
 
   cd "$WORKSPACE"
   #convert all gcov reports to xml cobertura reports
-  gcovr -r . --xml-pretty -e teshsuite -e examples/smpi/NAS -e examples/smpi/mc -u -o "$BUILDFOLDER"/xml_coverage.xml
+  gcovr -r . --xml-pretty -e teshsuite -e build/MBI -e examples/smpi/NAS -e examples/smpi/mc -u -o "$BUILDFOLDER"/xml_coverage.xml
   xsltproc "$WORKSPACE"/tools/jenkins/ctest2junit.xsl build/Testing/"$( head -n 1 < build/Testing/TAG )"/Test.xml > CTestResults_memcheck.xml
 
   #generate sloccount report
index c48a771..8a70894 100755 (executable)
@@ -22,7 +22,6 @@
 #   * teshsuite/s4u/monkey-masterworkers: tests synchronous comms and execs (C++ and python)
 #   * teshsuite/s4u/monkey-semaphore: tests async semaphores (C++ only)
 
-import multiprocessing as mp
 import sys
 import os
 import argparse
@@ -111,7 +110,6 @@ def do_run(cmd, extra_params, test_todo):
 
 def doit():
     prev_time = 0
-    test_count = 0
     test_todo = 2 * len(timestamps) * (host_count + link_count)
     for pos in range(len(timestamps)):
         now = timestamps[pos]