Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' of git+ssh://scm.gforge.inria.fr//gitroot/simgrid/simgrid
authorFrederic Suter <frederic.suter@cc.in2p3.fr>
Thu, 16 Jun 2016 08:11:33 +0000 (10:11 +0200)
committerFrederic Suter <frederic.suter@cc.in2p3.fr>
Thu, 16 Jun 2016 08:11:33 +0000 (10:11 +0200)
35 files changed:
doc/Doxyfile.in
doc/doxygen/index.doc
doc/doxygen/inside_doxygen.doc
doc/doxygen/inside_extending.doc
doc/doxygen/module-s4u.doc [new file with mode: 0644]
examples/msg/actions-comm/actions-comm.c
examples/s4u/CMakeLists.txt
examples/s4u/basic/s4u_basic.cpp
examples/s4u/io/s4u_io.cpp
examples/s4u/mutex/.gitignore [new file with mode: 0644]
examples/s4u/mutex/s4u_mutex.cpp [new file with mode: 0644]
examples/s4u/mutex/s4u_mutex.tesh [new file with mode: 0644]
include/simgrid/s4u.h
include/simgrid/s4u/actor.hpp
include/simgrid/s4u/mutex.hpp [new file with mode: 0644]
include/simgrid/simix.h
include/xbt/synchro_core.h
src/mc/Client.cpp
src/mc/mc_base.cpp
src/mc/mc_request.cpp
src/s4u/s4u_actor.cpp
src/s4u/s4u_mutex.cpp [new file with mode: 0644]
src/simix/Context.cpp
src/simix/smx_network.cpp
src/simix/smx_process.cpp
src/simix/smx_process_private.h
src/simix/smx_synchro.cpp
src/simix/smx_synchro_private.h
src/smpi/smpi_base.cpp
src/smpi/smpirun.in
src/xbt/xbt_os_synchro.c
tools/cmake/DefinePackages.cmake
tools/internal/spell_comments.pl
tools/internal/spell_dict.txt
tools/jenkins/Flags.sh [new file with mode: 0755]

index a935ef6..bde45d2 100644 (file)
@@ -678,6 +678,7 @@ INPUT                  = doxygen/index.doc \
                         doxygen/module-sd.doc \
                         doxygen/module-index.doc \
                            doxygen/module-xbt.doc \
+                           doxygen/module-s4u.doc \
                            doxygen/module-surf.doc \
                            doxygen/module-simix.doc \
                            doxygen/module-smpi.doc \
index e63863b..1dc3e3d 100644 (file)
@@ -14,6 +14,7 @@
   - @subpage install
   - @subpage install_yours
 - @subpage application
+  - @subpage s4u_api
   - @subpage MSG_API
   - @subpage SD_API
   - @subpage SMPI_API
index d69105e..0aadd25 100644 (file)
@@ -3,7 +3,7 @@
 
 \tableofcontents
 
-We use doxygen for our documentation. This tool is sometimes anoying
+We use doxygen for our documentation. This tool is sometimes annoying
 but that's the best we've found so far. Remember, we all bitch about
 doxygen, but at the end of the day, it kinda delivers what we need. So
 stop bitching about the doc or the tools, and start improving the
@@ -12,7 +12,7 @@ documentation text itself.
 Good documentation is rare and there is not much project of which we
 can get inspiration. The best exception I know is TikZ and
 latex-beamer. I'd be so happy if SimGrid documentation could follow
-the organisation (and reach half the quality) of the TikZ one. But
+the organization (and reach half the quality) of the TikZ one. But
 anyway. As they say: Documentation is like sex; when it's not good
 it's still better than nothing and when it's good it's very very good.
 
@@ -25,23 +25,23 @@ possible.
 \subsection inside_doxygen_module_create Declaring the module to doxygen
 
 First declare your sub-module in the corresponding
-(project)/doc/doxygen/module-(englobingmodule).doc Two edits are
+(project)/doc/doxygen/module-(enclosing module).doc Two edits are
 needed in this file: 
 
-@li Most of the englobing modules (xbt, msg, sd, etc) have a manually
+@li Most of the enclosing modules (xbt, msg, sd, etc) have a manually
     maintained table of contents as content of the module main page,
     at the top of the corresponding file. You want to add a reference to
-    your submodule there. For that, simply add something like the
+    your sub-module there. For that, simply add something like the
     following. The dash (-) will help building item lists. The ref
     command requests for a link to your module, that is identified
-    with the word after that (here, I used xbt_cunit as a submodule
+    with the word after that (here, I used xbt_cunit as a sub-module
     identifier.
 @verbatim
  - @ref XBT_cunit
 @endverbatim
 
 @li Create your module below in the file as follows. the first world
-after the defgroup keyword must be the submodule identifier you used
+after the defgroup keyword must be the sub-module identifier you used
 above.
 @verbatim
      /** @defgroup XBT_cunit Unit testing support */
@@ -72,7 +72,7 @@ to add something like this near the top.
 Any informative stuff is welcomed in the module introduction, on top.
 This includes examples that the users can copy/paste to fit their
 needs. If your module is too large to be nicely documented on one
-unique page, you may want to split its documentation in submodules.
+unique page, you may want to split its documentation in sub-modules.
 See dynar.h for an example of how to do so. 
 
 Make sure to only include the public declarations of your module. For
@@ -119,11 +119,11 @@ something like the following:
 
 @tableofcontents
 
-blabla bla
+blah blah blah
 
 @section <short_name_of_section> <title>
 
-bliblublo
+blah blah blah
 
 @subsection <short_name_of_subsection> <title>
 
index e16c1e6..9c7466e 100644 (file)
@@ -1,14 +1,14 @@
-/*!
-\page inside_extending Extending SimGrid
+/**
+@page inside_extending Extending SimGrid
 
 \tableofcontents
 
-\section simgrid_dev_guide_model How to add a new model in surf?
+\section simgrid_dev_guide_model How to add a new model?
 The figure below shows the architecture of the SURF layer. This layer is composed
 of different kinds of models representing the different systems we want to
 model (i.e., cpu, network, storage, workstation, virtual machine).
 
-A model in simgrid is composed of three classes: Model, Resource and Action
+A model in SimGrid is composed of three classes: Model, Resource and Action
 (\ref SURF_interface "surf_interface.hpp").
 
 \image html surf++.png
@@ -27,7 +27,7 @@ that is defined as follows:
 
 s_surf_model_description_t surf_network_model_description[] = {
 
-\subsection simgrid_dev_guide_model_implem How to add a new model implementation in surf?
+\subsection simgrid_dev_guide_model_implem How to implement a new model?
 
 If you want to create a new implementation of a kind of model you must extend
 the classes of the corresponding interfaces.
@@ -64,7 +64,7 @@ s_surf_model_description_t surf_cpu_model_description[] = {
 };
 ~~~~
 
-\subsection simgrid_dev_guide_model_kind How to add a new kind of model in surf?
+\subsection simgrid_dev_guide_model_kind How to add a new kind of model?
 
 If you want to create a new kind of model, you must create a new interface
 where you extend the classes Model, Resource and Action, and then create an
@@ -120,7 +120,14 @@ s_surf_model_description_t surf_plugin_description[] = {
 
 A simcall is used to go from user mode to kernel mode. There is some
 sort of popping dance involved, as we want to isolate the user
-contextes from their environment (so that they can run in parallel).
+contextes from their environment (so that they can run in parallel and
+so that we can model-check them).
+
+In short, just add a line to src/simix/simcalls.in and run the
+src/simix/simcalls.py script. It will guide you about how to implement
+your simcall. Please keep reading this section (only) if you want to
+understand how it goes.
+
 
 The workflow of a simcall is the following:
 
@@ -162,32 +169,10 @@ generates the following files:
 
 The simcall.in file list all the simcalls in sections. A line starting by "##"
 define a new section which will be replace by a "ifdef" in the generated code.
-There is a simcall by line which follow this format:
-
-~~~~
-Simcall -> Name HasAnswer Res Args
-Name -> [a-z0-9_]+
-Has_Answer -> "True" | "False"
-Res -> "(" Type MaybeCast ")"
-Args -> Args Arg | Arg
-Arg -> "(" Name "," Type MaybeCast ")"
-Type -> "char" | "const char*" | "int" | "long" | "unsigned char" | "unsigned short" | "unsigned int" | "unsigned long" | "float" | "double" | "void*" | "FPtr" | "const void*" | "size_t" | "sg_size_t" | "void" | "void*"
-MaybeCast -> "," Cast | ""
-Cast -> [a-z0-9_* ]+
-~~~~
 
 \section simgrid_dev_guide_tag What is How to add a new tag for xml files?
-Search for expression \"TUTORIAL: New TAG\".
-\verbatim
-user@caraja:~/workspace/simgrid/src$ cg "TUTORIAL: New TAG"
-0 surf/sg_platf.c                    43 /* TUTORIAL: New TAG*/
-1 surf/sg_platf.c                    89 /* TUTORIAL: New TAG*/
-2 surf/sg_platf.c                   124 /* TUTORIAL: New TAG*/
-3 surf/sg_platf.c                   337 /* TUTORIAL: New TAG*/
-4 surf/surfxml_parse.c              769 /* TUTORIAL: New TAG*/
-5 surf/surf_private.h               205 /* TUTORIAL: New TAG*/
-6 surf/surfxml_parseplatf.c          64 /* TUTORIAL: New TAG*/
-7 surf/surfxml_parseplatf.c          85 /* TUTORIAL: New TAG*/
-8 include/simgrid/platf_interface.h  42 /* TUTORIAL: New TAG*/
-\endverbatim
-*/
+
+You should not do something like that. Please work instead to make XML
+avoidable, ie to make the C++ interface nice and usable.
+
+*/
\ No newline at end of file
diff --git a/doc/doxygen/module-s4u.doc b/doc/doxygen/module-s4u.doc
new file mode 100644 (file)
index 0000000..9e629e1
--- /dev/null
@@ -0,0 +1,137 @@
+/**
+@defgroup s4u_api  S4U: Next Generation SimGrid API
+@brief Future core API, mixing the full power of SimGrid to the power of C++. 
+
+The S4U API is currently under heavy work, but will eventually
+deprecate the MSG and SimDag APIs. Everything that you can do in
+SimGrid will be possible in S4U. 
+
+@warning <b>S4U is not ready for public use yet</b>. You should not go
+        that path unless you know what you are doing.  If unsure,
+        proceed to @ref MSG_API instead.
+
+@section s4u_funct Offered functionalities
+
+Unsurprisingly, the S4U interface matches the concepts presented in 
+@ref starting_components "the introduction":
+
+  - @ref s4u_actor
+
+  @{
+*/
+
+/** @defgroup  s4u_actor Actors: simulation agents */
+
+/** @} */
+
+   - \ref msg_simulation
+   - \ref m_process_management
+   - \ref m_host_management
+   - \ref m_task_management
+   - \ref msg_mailbox_management
+   - @ref msg_file
+   - \ref msg_task_usage
+   - \ref msg_VMs
+   - \ref msg_synchro
+   - \ref msg_trace_driven
+   - \ref MSG_examples
+
+@defgroup msg_simulation   Main MSG simulation Functions
+@ingroup MSG_API
+@brief How to setup and control your simulation.
+
+The basic workflow is the following (check the \ref MSG_examples for
+details).
+
+ -# Initialize the library with #MSG_init
+ -# Create a platform (usually by parsing a file with
+    #MSG_create_environment)
+ -# Register the functions that your processes are supposed to run with
+    #MSG_function_register (and maybe #MSG_function_register_default)
+ -# Launch your processes from a deployment file with #MSG_launch_application
+ -# Run the simulation with #MSG_main
+*
+
+** @defgroup m_process_management Process Management Functions
+ *  @ingroup MSG_API
+ *  @brief This section describes the process structure of MSG
+ *         (#msg_process_t) and the functions for managing it.
+ */
+
+** @defgroup m_host_management Host Management Functions
+ *  @ingroup MSG_API
+ *  @brief Host structure of MSG
+ *
+
+** @defgroup m_task_management Task Management Functions
+ *  @ingroup MSG_API
+ *  @brief Task structure of MSG (#msg_task_t) and associated functions. See
+ *         \ref msg_task_usage to see how to put the tasks in action.
+ *
+
+** @defgroup msg_mailbox_management Mailbox Management Functions
+ *  @ingroup MSG_API
+ *  @brief Mailbox structure of MSG (#msg_mailbox_t) and associated functions.
+ *
+
+** @defgroup msg_task_usage Task Actions
+ *  @ingroup MSG_API
+ *  @brief This section describes the functions that can be used
+ *         by a process to execute, communicate or otherwise handle some task.
+ *
+
+** @defgroup msg_synchro Explicit Synchronization Functions
+ *  @ingroup MSG_API
+ *  @brief Explicit synchronization mechanisms: semaphores (#msg_sem_t) and friends.
+ *
+ * In some situations, these things are very helpful to synchronize processes without message exchanges.
+ *
+
+** @defgroup msg_VMs VMs
+ *  @ingroup MSG_API
+ *  @brief Interface created to mimic IaaS clouds.
+ *
+ *  With it, you can create virtual machines to put your processes
+ *  into, and interact directly with the VMs to manage groups of
+ *  processes.
+ *
+ *  This interface is highly experimental at this point. Testing is
+ *  welcomed, but do not expect too much of it right now. Even the
+ *  interfaces may be changed in future releases of SimGrid (although
+ *  things are expected to stabilize nicely before SimGrid v3.8).
+ *  There is no guaranty on the rest of SimGrid, and there is less
+ *  than that on this part.
+ *
+ *
+
+** @defgroup msg_storage_management Storage Management Functions
+ *  @ingroup MSG_API
+ *  @brief Storage structure of MSG (#msg_storage_t) and associated functions, inspired from POSIX.
+ *
+
+** @defgroup msg_file File Management Functions
+    @ingroup MSG_API
+    @brief MSG files (#msg_file_t) and associated functions, inspired from POSIX.
+*
+
+**
+@defgroup msg_trace_driven Trace-driven simulations
+@ingroup MSG_API
+@brief This section describes the functions allowing to build trace-driven simulations.
+
+This is very handy when you want to test an algorithm or protocol that
+does nothing unless it receives some events from outside. For example,
+a P2P protocol reacts to requests from the user, but does nothing if
+there is no such event.
+
+In such situations, SimGrid allows to write your protocol in your C
+file, and the events to react to in a separate text file. Declare a
+function handling each of the events that you want to accept in your
+trace files, register them using #xbt_replay_action_register in your main,
+and then use #MSG_action_trace_run to launch the simulation. You can
+either have one trace file containing all your events, or a file per
+simulated process.
+
+Check the examples in <b>examples/msg/actions/actions.c</b> for details.
+
+ *
index 126936b..86486d2 100644 (file)
@@ -183,7 +183,7 @@ static void action_barrier(const char *const *action)
   processes_arrived_sofar--;
   if (processes_arrived_sofar<=0) {
     SIMIX_cond_destroy(cond);
-    SIMIX_mutex_destroy(mutex);
+    SIMIX_mutex_unref(mutex);
     mutex = NULL;
   }
 }
index 686defd..e90125e 100644 (file)
@@ -1,4 +1,4 @@
-foreach (example basic io)
+foreach (example basic io mutex)
   add_executable       (s4u_${example}  ${example}/s4u_${example}.cpp)
   target_link_libraries(s4u_${example}  simgrid)
   set_target_properties(s4u_${example}  PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${example})
@@ -13,3 +13,4 @@ set(txt_files     ${txt_files}    ${CMAKE_CURRENT_SOURCE_DIR}/README  PARENT_SCO
 
 ADD_TESH_FACTORIES(s4u-basic "thread;ucontext;raw;boost" --setenv bindir=${CMAKE_BINARY_DIR}/examples/s4u/basic --cd ${CMAKE_HOME_DIRECTORY}/examples/s4u/basic s4u_basic.tesh)
 ADD_TESH_FACTORIES(s4u-io    "thread;ucontext;raw;boost" --setenv bindir=${CMAKE_BINARY_DIR}/examples/s4u/io    --cd ${CMAKE_HOME_DIRECTORY}/examples/s4u/io    s4u_io.tesh)
+ADD_TESH_FACTORIES(s4u-mutex    "thread;ucontext;raw;boost" --setenv bindir=${CMAKE_BINARY_DIR}/examples/s4u/mutex    --cd ${CMAKE_HOME_DIRECTORY}/examples/s4u/mutex    s4u_mutex.tesh)
index 13d0103..c08cd6d 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2006-2015. The SimGrid Team. All rights reserved.          */
+/* Copyright (c) 2006-2016. The SimGrid Team. All rights reserved.          */
 
 /* This program is free software; you can redistribute it and/or modify it
  * under the terms of the license (GNU LGPL) which comes with this package. */
@@ -34,8 +34,8 @@ public:
 int main(int argc, char **argv) {
   simgrid::s4u::Engine *e = new simgrid::s4u::Engine(&argc,argv);
   e->loadPlatform("../../platforms/two_hosts.xml");
-  new simgrid::s4u::Actor("worker", simgrid::s4u::Host::by_name("Tremblay"), Worker());
-  new simgrid::s4u::Actor("master", simgrid::s4u::Host::by_name("Jupiter"), 0, Master());
+  simgrid::s4u::Actor("worker", simgrid::s4u::Host::by_name("Tremblay"), Worker());
+  simgrid::s4u::Actor("master", simgrid::s4u::Host::by_name("Jupiter"), 0, Master());
   e->run();
   return 0;
 }
index c4494a3..b3aaa11 100644 (file)
@@ -104,7 +104,7 @@ int main(int argc, char **argv)
 {
   simgrid::s4u::Engine *e = new simgrid::s4u::Engine(&argc,argv);
   e->loadPlatform("../../platforms/storage/storage.xml");
-  new simgrid::s4u::Actor("host", simgrid::s4u::Host::by_name("denise"), MyHost());
+  simgrid::s4u::Actor("host", simgrid::s4u::Host::by_name("denise"), MyHost());
   e->run();
   return 0;
 }
diff --git a/examples/s4u/mutex/.gitignore b/examples/s4u/mutex/.gitignore
new file mode 100644 (file)
index 0000000..0ace5ca
--- /dev/null
@@ -0,0 +1 @@
+s4u_actor
diff --git a/examples/s4u/mutex/s4u_mutex.cpp b/examples/s4u/mutex/s4u_mutex.cpp
new file mode 100644 (file)
index 0000000..3d0ba54
--- /dev/null
@@ -0,0 +1,92 @@
+/* Copyright (c) 2006-2015. The SimGrid Team. All rights reserved.          */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include <xbt/sysdep.h>
+#include <mutex>
+
+#include "simgrid/s4u.h"
+
+#define NB_ACTOR 2
+
+XBT_LOG_NEW_DEFAULT_CATEGORY(s4u_test, "a sample log category");
+
+// simgrid::s4u::Mutex mtx; //FIXME generate error -> You must run MSG_init before using MSG
+
+//Create an actor as a c++ functor
+class Worker {
+  simgrid::s4u::Mutex mutex_;
+  int *results_;
+public:
+  Worker(int  *res, simgrid::s4u::Mutex mutex) :
+    mutex_(std::move(mutex)),  results_(res) {};
+  // Define the code of the actor
+  void operator()() {
+    // Do the calculation
+    simgrid::s4u::this_actor::execute(1000);
+
+    // lock the mutex before enter in the critical section
+    std::lock_guard<simgrid::s4u::Mutex> lock(mutex_);
+    XBT_INFO("Hello s4u, I'm ready to compute");
+
+    // And finaly add it to the results
+    *results_ += 1;
+    XBT_INFO("I'm done, good bye");
+  }
+};
+
+// This class is an example of how to use lock_guard with simgrid mutex
+class WorkerLockGuard {
+  simgrid::s4u::Mutex mutex_;
+  int *results_;
+public:
+  WorkerLockGuard(int  *res, simgrid::s4u::Mutex mutex) :
+    mutex_(std::move(mutex)),  results_(res) {};
+  void operator()() {
+
+    simgrid::s4u::this_actor::execute(1000);
+
+    // Simply use the std::lock_guard like this
+    std::lock_guard<simgrid::s4u::Mutex> lock(mutex_);
+
+    // then you are in a safe zone
+    XBT_INFO("Hello s4u, I'm ready to compute");
+    // update the results
+    *results_ += 1;
+    XBT_INFO("I'm done, good bye");
+  }
+};
+
+class MainActor {
+public:
+  void operator()() {
+    int res = 0;
+    simgrid::s4u::Mutex mutex;
+    simgrid::s4u::Actor workers[NB_ACTOR*2];
+
+    for (int i = 0; i < NB_ACTOR * 2 ; i++) {
+      // To create a worker use the static method simgrid::s4u::Actor.
+      if((i % 2) == 0 )
+        workers[i] = simgrid::s4u::Actor("worker",
+          simgrid::s4u::Host::by_name("Jupiter"),
+          WorkerLockGuard(&res, mutex));
+      else
+        workers[i] = simgrid::s4u::Actor("worker",
+          simgrid::s4u::Host::by_name("Tremblay"),
+          Worker(&res, mutex));
+    }
+
+    simgrid::s4u::this_actor::sleep(10);
+    XBT_INFO("Results is -> %d", res);
+  }
+};
+
+
+int main(int argc, char **argv) {
+  simgrid::s4u::Engine *e = new simgrid::s4u::Engine(&argc,argv);
+  e->loadPlatform("../../platforms/two_hosts.xml");
+  simgrid::s4u::Actor("main", simgrid::s4u::Host::by_name("Tremblay"), 0, MainActor());
+  e->run();
+  return 0;
+}
diff --git a/examples/s4u/mutex/s4u_mutex.tesh b/examples/s4u/mutex/s4u_mutex.tesh
new file mode 100644 (file)
index 0000000..e0f1040
--- /dev/null
@@ -0,0 +1,12 @@
+#! ./tesh
+
+$ $SG_TEST_EXENV ${bindir:=.}/s4u_mutex
+>[Tremblay:worker:(0) 0.000080] [s4u_test/INFO] Hello s4u, I'm ready to compute
+>[Tremblay:worker:(0) 0.000080] [s4u_test/INFO] I'm done, good bye
+>[Tremblay:worker:(0) 0.000080] [s4u_test/INFO] Hello s4u, I'm ready to compute
+>[Tremblay:worker:(0) 0.000080] [s4u_test/INFO] I'm done, good bye
+>[Jupiter:worker:(0) 0.000160] [s4u_test/INFO] Hello s4u, I'm ready to compute
+>[Jupiter:worker:(0) 0.000160] [s4u_test/INFO] I'm done, good bye
+>[Jupiter:worker:(0) 0.000160] [s4u_test/INFO] Hello s4u, I'm ready to compute
+>[Jupiter:worker:(0) 0.000160] [s4u_test/INFO] I'm done, good bye
+>[Tremblay:main:(0) 10.000000] [s4u_test/INFO] Results is -> 4
index 42cb73b..dde3205 100644 (file)
@@ -11,6 +11,7 @@
 #include "s4u/engine.hpp"
 #include "s4u/host.hpp"
 
+#include "s4u/mutex.hpp"
 #include "s4u/Activity.hpp"
 #include "s4u/comm.hpp"
 
index f479cf5..aa5877d 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2006-2015. The SimGrid Team. All rights reserved.          */
+/* Copyright (c) 2006-2016. The SimGrid Team. All rights reserved.          */
 
 /* This program is free software; you can redistribute it and/or modify it
  * under the terms of the license (GNU LGPL) which comes with this package. */
 namespace simgrid {
 namespace s4u {
 
-/** @brief Simulation Agent
- *
- * An actor may be defined as a code executing in a location (host).
- *
- * All actors should be started from the XML deployment file (using the @link{s4u::Engine::loadDeployment()}),
- * even if you can also start new actors directly.
- * Separating the deployment in the XML from the logic in the code is a good habit as it makes your simulation easier
- * to adapt to new settings.
- *
- * The code that you define for a given actor should be placed in the main method that is virtual.
- * For example, a Worker actor should be declared as follows:
+/** @addtogroup s4u_actor
+ * 
+ * @tableofcontents
+ * 
+ * An actor is an independent stream of execution in your distributed application.
  *
- * \verbatim
+ * You can think of an actor as a process in your distributed application, or as a thread in a multithreaded program.
+ * This is the only component in SimGrid that actually does something on its own, executing its own code. 
+ * A resource will not get used if you don't schedule activities on them. This is the code of Actors that create and schedule these activities.
+ * 
+ * An actor is located on a (simulated) host, but it can interact
+ * with the whole simulated platform.
+ * 
+ * The s4u::Actor API is strongly inspired from the C++11 threads.
+ * The <a href="http://en.cppreference.com/w/cpp/thread">documentation 
+ * of this standard</a> may help to understand the philosophy of the S4U
+ * Actors. 
+ * 
+ * (back to the @ref s4u_api "S4U documentation")
+ * 
+ * @section s4u_actor_def Defining the skeleton of an Actor
+ * 
+ * %As in the <a href="http://en.cppreference.com/w/cpp/thread">C++11
+ * standard</a>, you can declare the code of your actor either as a
+ * pure function or as an object. It is very simple with functions:
+ * 
+ * @code{.cpp}
+ * // Declare the code of your worker
+ * void worker() {
+ *   printf("Hello s4u");
+ *   simgrid::s4u::this_actor::execute(5*1024*1024); // Get the worker executing a task of 5 MFlops
+ * };
+ * 
+ * // From your main or from another actor, create your actor on the host Jupiter
+ * Actor("worker", simgrid::s4u::Host::by_name("Jupiter"), worker);
+ * @endcode
+ * 
+ * But some people prefer to encapsulate their actors in classes and
+ * objects to save the actor state in a cleanly dedicated location.
+ * The syntax is slightly more complicated, but not much.
+ * 
+ * @code{.cpp}
  * #include "s4u/actor.hpp"
  * 
+ * // Declare the class representing your actors
  * class Worker {
- *   void operator()() {
+ * public:
+ *   void operator()() { // Two pairs of () because this defines the method called ()
  *     printf("Hello s4u");
- *     return 0;
+ *     simgrid::s4u::this_actor::execute(5*1024*1024); // Get the worker executing a task of 5 MFlops
  *   }
  * };
+ * 
+ * // From your main or from another actor, create your actor. Note the () after Worker
+ * Actor("worker", simgrid::s4u::Host::by_name("Jupiter"), Worker());
+ * @endcode
+ * 
+ * @section s4u_actor_flesh Fleshing your actor
+ * 
+ * The body of your actor can use the functions of the
+ * simgrid::s4u::this_actor namespace to interact with the world.
+ * This namespace contains the methods to start new activities
+ * (executions, communications, etc), and to get informations about
+ * the currently running thread (its location, etc).
+ * 
+ * Please refer to the @link simgrid::s4u::this_actor full API @endlink.
  *
- * new Actor("worker", host, Worker());
- * \endverbatim
- *
+ * 
+ * @section s4u_actor_deploy Using a deployment file
+ * 
+ * @warning This is currently not working with S4U. Sorry about that.
+ * 
+ * The best practice is to use an external deployment file as
+ * follows, because it makes it easier to test your application in
+ * differing settings. Load this file with
+ * s4u::Engine::loadDeployment() before the simulation starts. 
+ * Refer to the @ref deployment section for more information.
+ * 
+ * @code{.xml}
+ * <?xml version='1.0'?>
+ * <!DOCTYPE platform SYSTEM "http://simgrid.gforge.inria.fr/simgrid/simgrid.dtd">
+ * <platform version="4">
+ * 
+ *   <!-- Start a process called 'master' on the host called 'Tremblay' -->
+ *   <process host="Tremblay" function="master">
+ *      <!-- Here come the parameter that you want to feed to this instance of master -->
+ *      <argument value="20"/>        <!-- argv[1] -->
+ *      <argument value="50000000"/>  <!-- argv[2] -->
+ *      <argument value="1000000"/>   <!-- argv[3] -->
+ *      <argument value="5"/>         <!-- argv[4] -->
+ *   </process>
+ * 
+ *   <!-- Start a process called 'worker' on the host called 'Jupiter' -->
+ *   <process host="Jupiter" function="worker"/> <!-- Don't provide any parameter ->>
+ * 
+ * </platform>
+ * @endcode
+ * 
+ *  @{
  */
+   
+/** @brief Simulation Agent (see \ref s4u_actor)*/
 XBT_PUBLIC_CLASS Actor {
-  explicit Actor(smx_process_t smx_proc);
 public:
+  Actor() : pimpl_(nullptr) {}
+  Actor(smx_process_t smx_proc) :
+    pimpl_(SIMIX_process_ref(smx_proc)) {}
+  ~Actor()
+  {
+    SIMIX_process_unref(pimpl_);
+  }
+
+  // Copy+move (with the copy-and-swap idiom):
+  Actor(Actor const& actor) : pimpl_(SIMIX_process_ref(actor.pimpl_)) {}
+  friend void swap(Actor& first, Actor& second)
+  {
+    using std::swap;
+    swap(first.pimpl_, second.pimpl_);
+  }
+  Actor& operator=(Actor actor)
+  {
+    swap(*this, actor);
+    return *this;
+  }
+  Actor(Actor&& actor) : pimpl_(nullptr)
+  {
+    swap(*this, actor);
+  }
+
   Actor(const char* name, s4u::Host *host, double killTime, std::function<void()> code);
   Actor(const char* name, s4u::Host *host, std::function<void()> code)
     : Actor(name, host, -1, std::move(code)) {};
   template<class C>
   Actor(const char* name, s4u::Host *host, C code)
     : Actor(name, host, -1, std::function<void()>(std::move(code))) {}
-  ~Actor();
 
   /** Retrieves the actor that have the given PID (or NULL if not existing) */
   //static Actor *byPid(int pid); not implemented
@@ -87,16 +186,13 @@ public:
   /** Ask kindly to all actors to die. Only the issuer will survive. */
   static void killAll();
 
-protected:
-  smx_process_t getInferior() {return pimpl_;}
 private:
   smx_process_t pimpl_ = nullptr;
 };
 
+/** @brief Static methods working on the current actor (see @ref s4u_actor) */
 namespace this_actor {
 
-  // Static methods working on the current actor:
-
   /** Block the actor sleeping for that amount of seconds (may throws hostFailure) */
   XBT_PUBLIC(void) sleep(double duration);
 
@@ -117,16 +213,9 @@ namespace this_actor {
 
 };
 
-}} // namespace simgrid::s4u
+/** @} */
 
-#endif /* SIMGRID_S4U_ACTOR_HPP */
-
-#if 0
+}} // namespace simgrid::s4u
 
-public final class Actor {
-  
-  public Actor(String name, Host host, double killTime, Runnable code);
-  // ....
 
-}
-#endif
+#endif /* SIMGRID_S4U_ACTOR_HPP */
diff --git a/include/simgrid/s4u/mutex.hpp b/include/simgrid/s4u/mutex.hpp
new file mode 100644 (file)
index 0000000..201f071
--- /dev/null
@@ -0,0 +1,61 @@
+/* Copyright (c) 2006-2015. The SimGrid Team. All rights reserved.          */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#ifndef SIMGRID_S4U_MUTEX_HPP
+#define SIMGRID_S4U_MUTEX_HPP
+
+#include <utility>
+
+#include <boost/intrusive_ptr.hpp>
+#include <xbt/base.h>
+#include "simgrid/simix.h"
+
+namespace simgrid {
+namespace s4u {
+
+XBT_PUBLIC_CLASS Mutex {
+
+public:
+  Mutex() :
+    mutex_(simcall_mutex_init()) {}
+  Mutex(simgrid::simix::Mutex* mutex) : mutex_(SIMIX_mutex_ref(mutex)) {}
+  ~Mutex()
+  {
+    SIMIX_mutex_unref(mutex_);
+  }
+
+  // Copy+move (with the copy-and-swap idiom):
+  Mutex(Mutex const& mutex) : mutex_(SIMIX_mutex_ref(mutex.mutex_)) {}
+  friend void swap(Mutex& first, Mutex& second)
+  {
+    using std::swap;
+    swap(first.mutex_, second.mutex_);
+  }
+  Mutex& operator=(Mutex mutex)
+  {
+    swap(*this, mutex);
+    return *this;
+  }
+  Mutex(Mutex&& mutex) : mutex_(nullptr)
+  {
+    swap(*this, mutex);
+  }
+
+  bool valid() const
+  {
+    return mutex_ != nullptr;
+  }
+
+public:
+  void lock();
+  void unlock();
+  bool try_lock();
+
+private:
+  simgrid::simix::Mutex* mutex_;
+};
+}} // namespace simgrid::s4u
+
+#endif /* SIMGRID_S4U_MUTEX_HPP */
index bc07ffe..e95b78c 100644 (file)
@@ -32,24 +32,26 @@ namespace simix {
   class Process;
   class Context;
   class ContextFactory;
-
+  class Mutex;
 }
 }
 
 typedef simgrid::simix::Context *smx_context_t;
 typedef simgrid::simix::Process *smx_process_t;
 
+/**
+ * \ingroup simix_synchro_management
+ */
+typedef simgrid::simix::Mutex   *smx_mutex_t;
+
 #else
 
 typedef struct s_smx_context *smx_context_t;
 typedef struct s_smx_process *smx_process_t;
+typedef struct s_smx_mutex   *smx_mutex_t;
 
 #endif
 
-
-
-SG_BEGIN_DECL()
-
 /**************************** Scalar Values **********************************/
 
 typedef union u_smx_scalar u_smx_scalar_t;
@@ -83,10 +85,7 @@ typedef enum {
 /** @} */
 
 /* ******************************** Synchro ************************************ */
-/**
- * \ingroup simix_synchro_management
- */
-typedef struct s_smx_mutex *smx_mutex_t;
+
 /**
  * \ingroup simix_synchro_management
  */
@@ -127,6 +126,8 @@ extern int smx_context_stack_size_was_set;
 extern int smx_context_guard_size;
 extern int smx_context_guard_size_was_set;
 
+SG_BEGIN_DECL()
+
 XBT_PUBLIC(xbt_dynar_t) SIMIX_process_get_runnable(void);
 XBT_PUBLIC(smx_process_t) SIMIX_process_from_PID(int PID);
 XBT_PUBLIC(xbt_dynar_t) SIMIX_processes_as_dynar(void);
@@ -213,6 +214,8 @@ XBT_PUBLIC(void) SIMIX_host_self_set_data(void *data);
 XBT_PUBLIC(void*) SIMIX_host_self_get_data(void);
 
 /********************************* Process ************************************/
+XBT_PUBLIC(smx_process_t) SIMIX_process_ref(smx_process_t process);
+XBT_PUBLIC(void) SIMIX_process_unref(smx_process_t process);
 XBT_PUBLIC(int) SIMIX_process_count(void);
 XBT_PUBLIC(smx_process_t) SIMIX_process_self(void);
 XBT_PUBLIC(const char*) SIMIX_process_self_get_name(void);
@@ -373,7 +376,8 @@ XBT_PUBLIC(void) simcall_set_category(smx_synchro_t synchro, const char *categor
 
 /************************** Synchro simcalls **********************************/
 XBT_PUBLIC(smx_mutex_t) simcall_mutex_init(void);
-XBT_PUBLIC(void) SIMIX_mutex_destroy(smx_mutex_t mutex);
+XBT_PUBLIC(smx_mutex_t) SIMIX_mutex_ref(smx_mutex_t mutex);
+XBT_PUBLIC(void) SIMIX_mutex_unref(smx_mutex_t mutex);
 XBT_PUBLIC(void) simcall_mutex_lock(smx_mutex_t mutex);
 XBT_PUBLIC(int) simcall_mutex_trylock(smx_mutex_t mutex);
 XBT_PUBLIC(void) simcall_mutex_unlock(smx_mutex_t mutex);
index 50684ed..b859f17 100644 (file)
@@ -13,6 +13,8 @@
 #ifndef _XBT_THREAD_H
 #define _XBT_THREAD_H
 
+#include <simgrid/simix.h>
+
 #include "xbt/misc.h"           /* SG_BEGIN_DECL */
 #include "xbt/function_types.h"
 
index cf7398d..661d404 100644 (file)
@@ -138,7 +138,9 @@ void Client::handleMessages()
         if (s != sizeof(message))
           xbt_die("Unexpected size for SIMCALL_HANDLE");
         memcpy(&message, message_buffer, sizeof(message));
+#if HAVE_SMPI
         smpi_really_switch_data_segment(message.index);
+#endif
       }
       break;
 
index df068fa..7c350f7 100644 (file)
@@ -162,10 +162,10 @@ bool request_is_enabled(smx_simcall_t req)
   case SIMCALL_MUTEX_LOCK: {
     smx_mutex_t mutex = simcall_mutex_lock__get__mutex(req);
 #if HAVE_MC
-    s_smx_mutex_t temp_mutex;
+    simgrid::mc::Remote<simgrid::simix::Mutex> temp_mutex;
     if (mc_model_checker != nullptr) {
-      mc_model_checker->process().read(&temp_mutex, remote(mutex));
-      mutex = &temp_mutex;
+      mc_model_checker->process().read(temp_mutex.getBuffer(), remote(mutex));
+      mutex = temp_mutex.getBuffer();
     }
 #endif
 
index d89c89d..cf8a8bf 100644 (file)
@@ -387,8 +387,8 @@ std::string simgrid::mc::request_to_string(smx_simcall_t req, int value, simgrid
     else
       type = "Mutex TRYLOCK";
 
-    s_smx_mutex_t mutex;
-    mc_model_checker->process().read_bytes(&mutex, sizeof(mutex),
+    simgrid::mc::Remote<simgrid::simix::Mutex> mutex;
+    mc_model_checker->process().read_bytes(mutex.getBuffer(), sizeof(mutex),
       remote(
         req->call == SIMCALL_MUTEX_LOCK
         ? simcall_mutex_lock__get__mutex(req)
@@ -396,12 +396,12 @@ std::string simgrid::mc::request_to_string(smx_simcall_t req, int value, simgrid
       ));
     s_xbt_swag_t mutex_sleeping;
     mc_model_checker->process().read_bytes(&mutex_sleeping, sizeof(mutex_sleeping),
-      remote(mutex.sleeping));
+      remote(mutex.getBuffer()->sleeping));
 
     args = bprintf("locked = %d, owner = %d, sleeping = %d",
-      mutex.locked,
-      mutex.owner != nullptr ? (int) mc_model_checker->process().resolveProcess(
-        simgrid::mc::remote(mutex.owner))->pid : -1,
+      mutex.getBuffer()->locked,
+      mutex.getBuffer()->owner != nullptr ? (int) mc_model_checker->process().resolveProcess(
+        simgrid::mc::remote(mutex.getBuffer()->owner))->pid : -1,
       mutex_sleeping.count);
     break;
   }
index 2170f74..d5d5e99 100644 (file)
@@ -16,19 +16,15 @@ XBT_LOG_NEW_DEFAULT_CATEGORY(s4u_actor,"S4U actors");
 
 using namespace simgrid;
 
-s4u::Actor::Actor(smx_process_t smx_proc) : pimpl_(smx_proc) {}
-
 s4u::Actor::Actor(const char* name, s4u::Host *host, double killTime, std::function<void()> code)
 {
   // TODO, when autorestart is used, the std::function is copied so the new
   // instance will get a fresh (reinitialized) state. Is this what we want?
-  this->pimpl_ = simcall_process_create(
+  this->pimpl_ = SIMIX_process_ref(simcall_process_create(
     name, std::move(code), nullptr, host->name().c_str(),
-    killTime, nullptr, 0);
+    killTime, nullptr, 0));
 }
 
-s4u::Actor::~Actor() {}
-
 void s4u::Actor::join() {
   simcall_process_join(pimpl_, -1);
 }
diff --git a/src/s4u/s4u_mutex.cpp b/src/s4u/s4u_mutex.cpp
new file mode 100644 (file)
index 0000000..e64bfd4
--- /dev/null
@@ -0,0 +1,29 @@
+/* Copyright (c) 2006-2015. The SimGrid Team.
+ * All rights reserved.                                                     */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include "xbt/log.h"
+#include "src/msg/msg_private.h"
+#include "src/simix/smx_network_private.h"
+
+#include "simgrid/s4u/mutex.hpp"
+
+namespace simgrid {
+namespace s4u {
+
+void Mutex::lock() {
+  simcall_mutex_lock(mutex_);
+}
+
+void Mutex::unlock() {
+  simcall_mutex_unlock(mutex_);
+}
+
+bool Mutex::try_lock() {
+  return simcall_mutex_trylock(mutex_);
+}
+
+}
+}
index d397833..5817bc7 100644 (file)
@@ -23,11 +23,9 @@ void SIMIX_process_set_cleanup_function(
 }
 
 /**
- * \brief creates a new context for a user level process
- * \param code a main function
- * \param argc the number of arguments of the main function
- * \param argv the vector of arguments of the main function
- * \param cleanup_func the function to call when the context stops
+ * @brief creates a new context for a user level process
+ * @param code a main function
+ * @param cleanup_func the function to call when the context stops
  */
 smx_context_t SIMIX_context_new(
   std::function<void()> code,
index 266b0cd..7da114e 100644 (file)
@@ -455,6 +455,8 @@ void simcall_HANDLER_comm_testany(smx_simcall_t simcall, xbt_dynar_t synchros)
 {
   unsigned int cursor;
   smx_synchro_t synchro;
+  // The default result is -1 -- this means, "nothing is ready".
+  // It can be changed below, but only if something matches.
   simcall_comm_testany__set__result(simcall, -1);
 
   if (MC_is_active() || MC_record_replay_is_active()){
index 1eb504d..bcd0600 100644 (file)
@@ -28,6 +28,21 @@ XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_process, simix, "Logging specific to SIMIX
 
 unsigned long simix_process_maxpid = 0;
 
+/** Increase the refcount for this process */
+smx_process_t SIMIX_process_ref(smx_process_t process)
+{
+  if (process != nullptr)
+    intrusive_ptr_add_ref(process);
+  return process;
+}
+
+/** Decrease the refcount for this process */
+void SIMIX_process_unref(smx_process_t process)
+{
+  if (process != nullptr)
+    intrusive_ptr_release(process);
+}
+
 /**
  * \brief Returns the current agent.
  *
@@ -126,17 +141,24 @@ void SIMIX_process_empty_trash(void)
 
   while ((process = (smx_process_t) xbt_swag_extract(simix_global->process_to_destroy))) {
     XBT_DEBUG("Getting rid of %p",process);
-    delete process->context;
-    xbt_dict_free(&process->properties);
-    xbt_fifo_free(process->comms);
-    xbt_dynar_free(&process->on_exit);
-    delete process;
+    intrusive_ptr_release(process);
   }
 }
 
 namespace simgrid {
 namespace simix {
 
+Process::~Process()
+{
+  delete this->context;
+  if (this->properties)
+    xbt_dict_free(&this->properties);
+  if (this->comms != nullptr)
+    xbt_fifo_free(this->comms);
+  if (this->on_exit)
+    xbt_dynar_free(&this->on_exit);
+}
+
 void create_maestro(std::function<void()> code)
 {
   smx_process_t maestro = nullptr;
index 87c9b10..837cc22 100644 (file)
@@ -7,6 +7,7 @@
 #ifndef _SIMIX_PROCESS_PRIVATE_H
 #define _SIMIX_PROCESS_PRIVATE_H
 
+#include <atomic>
 #include <functional>
 #include <string>
 
@@ -29,45 +30,63 @@ class ProcessArg {
 public:
   std::string name;
   std::function<void()> code;
-  void *data = nullptr;
-  const char *hostname = nullptr;
-  double kill_time = 0.0;
-  xbt_dict_t properties  = nullptr;
-  bool auto_restart = false;
+  void *data            = nullptr;
+  const char *hostname  = nullptr;
+  double kill_time      = 0.0;
+  xbt_dict_t properties = nullptr;
+  bool auto_restart     = false;
 };
 
 class Process {
 public:
 
   // TODO, replace with boost intrusive container hooks
-  s_xbt_swag_hookup_t process_hookup = { nullptr, nullptr };   /* simix_global->process_list */
-  s_xbt_swag_hookup_t synchro_hookup = { nullptr, nullptr };   /* {mutex,cond,sem}->sleeping */
+  s_xbt_swag_hookup_t process_hookup   = { nullptr, nullptr };   /* simix_global->process_list */
+  s_xbt_swag_hookup_t synchro_hookup   = { nullptr, nullptr };   /* {mutex,cond,sem}->sleeping */
   s_xbt_swag_hookup_t host_proc_hookup = { nullptr, nullptr }; /* smx_host->process_lis */
-  s_xbt_swag_hookup_t destroy_hookup = { nullptr, nullptr };   /* simix_global->process_to_destroy */
+  s_xbt_swag_hookup_t destroy_hookup   = { nullptr, nullptr };   /* simix_global->process_to_destroy */
 
-  unsigned long pid = 0;
+  unsigned long pid  = 0;
   unsigned long ppid = 0;
   simgrid::xbt::string name;
-  sg_host_t host = nullptr;     /* the host on which the process is running */
+  sg_host_t host        = nullptr;     /* the host on which the process is running */
   smx_context_t context = nullptr; /* the context (uctx/raw/thread) that executes the user function */
 
   // TODO, pack them
   std::exception_ptr exception;
-  bool blocked = false;
-  bool suspended = false;
+  bool blocked      = false;
+  bool suspended    = false;
   bool auto_restart = false;
 
-  sg_host_t new_host = nullptr;     /* if not null, the host on which the process must migrate to */
+  sg_host_t new_host            = nullptr;     /* if not null, the host on which the process must migrate to */
   smx_synchro_t waiting_synchro = nullptr;  /* the current blocking synchro if any */
-  xbt_fifo_t comms = nullptr;       /* the current non-blocking communication synchros */
-  xbt_dict_t properties = nullptr;
+  xbt_fifo_t comms              = nullptr;       /* the current non-blocking communication synchros */
+  xbt_dict_t properties         = nullptr;
   s_smx_simcall_t simcall;
-  void *data = nullptr;    /* kept for compatibility, it should be replaced with moddata */
+  void *data          = nullptr;    /* kept for compatibility, it should be replaced with moddata */
   xbt_dynar_t on_exit = nullptr; /* list of functions executed when the process dies */
 
   std::function<void()> code;
   smx_timer_t kill_timer = nullptr;
-  int segment_index = 0;    /*Reference to an SMPI process' data segment. Default value is -1 if not in SMPI context*/
+  int segment_index      = 0;    /*Reference to an SMPI process' data segment. Default value is -1 if not in SMPI context*/
+
+  friend void intrusive_ptr_add_ref(Process* process)
+  {
+    auto previous = (process->refcount_)++;
+    xbt_assert(previous != 0);
+    (void) previous;
+  }
+  friend void intrusive_ptr_release(Process* process)
+  {
+    auto count = --(process->refcount_);
+    if (count == 0)
+      delete process;
+  }
+
+  ~Process();
+
+private:
+  std::atomic_int_fast32_t refcount_ { 1 };
 };
 
 }
index 2797cb5..0d53762 100644 (file)
@@ -1,3 +1,4 @@
+
 /* Copyright (c) 2007-2015. The SimGrid Team.
  * All rights reserved.                                                     */
 
@@ -93,130 +94,134 @@ void SIMIX_synchro_finish(smx_synchro_t synchro)
 }
 /*********************************** Mutex ************************************/
 
-smx_mutex_t simcall_HANDLER_mutex_init(smx_simcall_t simcall){
-  return SIMIX_mutex_init();
-}
-/**
- * \brief Initialize a mutex.
- *
- * Allocs and creates the data for the mutex.
- * \return A mutex
- */
-smx_mutex_t SIMIX_mutex_init(void)
+namespace simgrid {
+namespace simix {
+
+Mutex::Mutex()
 {
-  XBT_IN("()");
-  simgrid::simix::Process p;            /* useful to initialize sleeping swag */
+  XBT_IN("(%p)", this);
+  // Useful to initialize sleeping swag:
+  simgrid::simix::Process p;
+  this->sleeping = xbt_swag_new(xbt_swag_offset(p, synchro_hookup));
+  XBT_OUT();
+}
 
-  smx_mutex_t mutex = xbt_new0(s_smx_mutex_t, 1);
-  mutex->locked = 0;
-  mutex->sleeping = xbt_swag_new(xbt_swag_offset(p, synchro_hookup));
+Mutex::~Mutex()
+{
+  XBT_IN("(%p)", this);
+  xbt_swag_free(this->sleeping);
   XBT_OUT();
-  return mutex;
 }
 
-/**
- * \brief Handles a mutex lock simcall.
- * \param simcall the simcall
- */
-void simcall_HANDLER_mutex_lock(smx_simcall_t simcall, smx_mutex_t mutex)
+void Mutex::lock(smx_process_t issuer)
 {
-  XBT_IN("(%p)",simcall);
+  XBT_IN("(%p; %p)", this, issuer);
   /* FIXME: check where to validate the arguments */
   smx_synchro_t synchro = nullptr;
-  smx_process_t process = simcall->issuer;
 
-  if (mutex->locked) {
+  if (this->locked) {
     /* FIXME: check if the host is active ? */
     /* Somebody using the mutex, use a synchronization to get host failures */
-    synchro = SIMIX_synchro_wait(process->host, -1);
-    synchro->simcalls.push_back(simcall);
-    simcall->issuer->waiting_synchro = synchro;
-    xbt_swag_insert(simcall->issuer, mutex->sleeping);   
+    synchro = SIMIX_synchro_wait(issuer->host, -1);
+    synchro->simcalls.push_back(&issuer->simcall);
+    issuer->waiting_synchro = synchro;
+    xbt_swag_insert(issuer, this->sleeping);
   } else {
     /* mutex free */
-    mutex->locked = 1;
-    mutex->owner = simcall->issuer;
-    SIMIX_simcall_answer(simcall);
+    this->locked = true;
+    this->owner = issuer;
+    SIMIX_simcall_answer(&issuer->simcall);
   }
   XBT_OUT();
 }
 
-int simcall_HANDLER_mutex_trylock(smx_simcall_t simcall, smx_mutex_t mutex){
-  return SIMIX_mutex_trylock(mutex, simcall->issuer);
-}
-/**
- * \brief Tries to lock a mutex.
+/** Tries to lock the mutex for a process
  *
- * Tries to lock a mutex, return 1 if the mutex is unlocked, else 0.
- * This function does not block and wait for the mutex to be unlocked.
- * \param mutex The mutex
- * \param issuer The process that tries to acquire the mutex
- * \return 1 - mutex free, 0 - mutex used
+ * \param  issuer  the process that tries to acquire the mutex
+ * \return whether we managed to lock the mutex
  */
-int SIMIX_mutex_trylock(smx_mutex_t mutex, smx_process_t issuer)
+bool Mutex::try_lock(smx_process_t issuer)
 {
-  XBT_IN("(%p, %p)",mutex,issuer);
-  if (mutex->locked){
+  XBT_IN("(%p, %p)", this, issuer);
+  if (this->locked) {
     XBT_OUT();
-    return 0;
+    return false;
   }
 
-  mutex->locked = 1;
-  mutex->owner = issuer;
+  this->locked = true;
+  this->owner = issuer;
   XBT_OUT();
-  return 1;
+  return true;
 }
 
-void simcall_HANDLER_mutex_unlock(smx_simcall_t simcall, smx_mutex_t mutex){
-   SIMIX_mutex_unlock(mutex, simcall->issuer);
-}
-/**
- * \brief Unlocks a mutex.
+/** Unlock a mutex for a process
  *
  * Unlocks the mutex and gives it to a process waiting for it. 
  * If the unlocker is not the owner of the mutex nothing happens.
  * If there are no process waiting, it sets the mutex as free.
- * \param mutex The mutex
- * \param issuer The process trying to unlock the mutex
  */
-void SIMIX_mutex_unlock(smx_mutex_t mutex, smx_process_t issuer)
+void Mutex::unlock(smx_process_t issuer)
 {
-  XBT_IN("(%p, %p)",mutex,issuer);
+  XBT_IN("(%p, %p)", this, issuer);
 
   /* If the mutex is not owned by the issuer, that's not good */
-  if (issuer != mutex->owner)
+  if (issuer != this->owner)
     THROWF(mismatch_error, 0, "Cannot release that mutex: it was locked by %s (pid:%d), not by you.",
-        SIMIX_process_get_name(mutex->owner),SIMIX_process_get_PID(mutex->owner));
+        SIMIX_process_get_name(this->owner),SIMIX_process_get_PID(this->owner));
 
-  if (xbt_swag_size(mutex->sleeping) > 0) {
+  if (xbt_swag_size(this->sleeping) > 0) {
     /*process to wake up */
-    smx_process_t p = (smx_process_t) xbt_swag_extract(mutex->sleeping);
+    smx_process_t p = (smx_process_t) xbt_swag_extract(this->sleeping);
     delete p->waiting_synchro;
     p->waiting_synchro = nullptr;
-    mutex->owner = p;
+    this->owner = p;
     SIMIX_simcall_answer(&p->simcall);
   } else {
     /* nobody to wake up */
-    mutex->locked = 0;
-    mutex->owner = nullptr;
+    this->locked = false;
+    this->owner = nullptr;
   }
   XBT_OUT();
 }
 
-/**
- * \brief Destroys a mutex.
- *
- * Destroys and frees the mutex's memory. 
- * \param mutex A mutex
- */
-void SIMIX_mutex_destroy(smx_mutex_t mutex)
+}
+}
+
+/** Increase the refcount for this mutex */
+smx_mutex_t SIMIX_mutex_ref(smx_mutex_t mutex)
 {
-  XBT_IN("(%p)",mutex);
-  if (mutex){
-    xbt_swag_free(mutex->sleeping);
-    xbt_free(mutex);
-  }
-  XBT_OUT();
+  if (mutex != nullptr)
+    intrusive_ptr_add_ref(mutex);
+  return mutex;
+}
+
+/** Decrease the refcount for this mutex */
+void SIMIX_mutex_unref(smx_mutex_t mutex)
+{
+  if (mutex != nullptr)
+    intrusive_ptr_release(mutex);
+}
+
+smx_mutex_t simcall_HANDLER_mutex_init(smx_simcall_t simcall)
+{
+  return new simgrid::simix::Mutex();
+}
+
+// Simcall handlers:
+
+void simcall_HANDLER_mutex_lock(smx_simcall_t simcall, smx_mutex_t mutex)
+{
+  mutex->lock(simcall->issuer);
+}
+
+int simcall_HANDLER_mutex_trylock(smx_simcall_t simcall, smx_mutex_t mutex)
+{
+  return mutex->try_lock(simcall->issuer);
+}
+
+void simcall_HANDLER_mutex_unlock(smx_simcall_t simcall, smx_mutex_t mutex)
+{
+  mutex->unlock(simcall->issuer);
 }
 
 /********************************* Condition **********************************/
@@ -279,7 +284,7 @@ static void _SIMIX_cond_wait(smx_cond_t cond, smx_mutex_t mutex, double timeout,
   /* FIXME: what happens if the issuer is not the owner of the mutex? */
   if (mutex != nullptr) {
     cond->mutex = mutex;
-    SIMIX_mutex_unlock(mutex, issuer);
+    mutex->unlock(issuer);
   }
 
   synchro = SIMIX_synchro_wait(issuer->host, timeout);
index c8ea1f6..21e76b4 100644 (file)
@@ -7,16 +7,51 @@
 #ifndef _SIMIX_SYNCHRO_PRIVATE_H
 #define _SIMIX_SYNCHRO_PRIVATE_H
 
+#include <atomic>
+
 #include "xbt/base.h"
 #include "xbt/swag.h"
 #include "xbt/xbt_os_thread.h"
 #include "src/simix/popping_private.h"
 
-typedef struct s_smx_mutex {
-  unsigned int locked;
-  smx_process_t owner;
-  xbt_swag_t sleeping;          /* list of sleeping process */
-} s_smx_mutex_t;
+namespace simgrid {
+namespace simix {
+
+class XBT_PUBLIC() Mutex {
+public:
+  Mutex();
+  ~Mutex();
+  Mutex(Mutex const&) = delete;
+  Mutex& operator=(Mutex const&) = delete;
+
+  void lock(smx_process_t issuer);
+  bool try_lock(smx_process_t issuer);
+  void unlock(smx_process_t issuer);
+
+  bool locked = false;
+  smx_process_t owner = nullptr;
+  // List of sleeping processes:
+  xbt_swag_t sleeping = nullptr;
+
+  // boost::intrusive_ptr<Mutex> support:
+  friend void intrusive_ptr_add_ref(Mutex* mutex)
+  {
+    auto previous = (mutex->refcount_)++;
+    xbt_assert(previous != 0);
+    (void) previous;
+  }
+  friend void intrusive_ptr_release(Mutex* mutex)
+  {
+    auto count = --(mutex->refcount_);
+    if (count == 0)
+      delete mutex;
+  }
+private:
+  std::atomic_int_fast32_t refcount_ { 1 };
+};
+
+}
+}
 
 typedef struct s_smx_cond {
   smx_mutex_t mutex;
@@ -33,10 +68,6 @@ XBT_PRIVATE void SIMIX_synchro_stop_waiting(smx_process_t process, smx_simcall_t
 XBT_PRIVATE void SIMIX_synchro_destroy(smx_synchro_t synchro);
 XBT_PRIVATE void SIMIX_synchro_finish(smx_synchro_t synchro);
 
-XBT_PRIVATE smx_mutex_t SIMIX_mutex_init(void);
-XBT_PRIVATE int SIMIX_mutex_trylock(smx_mutex_t mutex, smx_process_t issuer);
-XBT_PRIVATE void SIMIX_mutex_unlock(smx_mutex_t mutex, smx_process_t issuer);
-
 XBT_PRIVATE smx_cond_t SIMIX_cond_init(void);
 XBT_PRIVATE void SIMIX_cond_broadcast(smx_cond_t cond);
 XBT_PRIVATE void SIMIX_cond_signal(smx_cond_t cond);
index 89ae538..011c539 100644 (file)
@@ -74,7 +74,7 @@ static int match_send(void* a, void* b,smx_synchro_t ignored) {
 typedef struct s_smpi_factor_multival *smpi_os_factor_multival_t;
 typedef struct s_smpi_factor_multival { // FIXME: this should be merged (deduplicated) with s_smpi_factor defined in network_smpi.c
   long factor=0;
-  std::vector<double> values; /** We allocate arbitrarily 4 elements **/
+  std::vector<double> values;
 } s_smpi_factor_multival_t;
 
 std::vector<s_smpi_factor_multival_t> smpi_os_values;
@@ -775,44 +775,40 @@ int smpi_mpi_testany(int count, MPI_Request requests[], int *index, MPI_Status *
 {
   xbt_dynar_t comms;
   int i;
-  int* map;
   int flag = 0;
-  int size = 0;
 
   *index = MPI_UNDEFINED;
   comms = xbt_dynar_new(sizeof(smx_synchro_t), nullptr);
-  map = xbt_new(int, count);
+  std::vector<int> map; /** Maps all matching comms back to their location in requests **/
   for(i = 0; i < count; i++) {
     if ((requests[i] != MPI_REQUEST_NULL) && requests[i]->action && !(requests[i]->flags & PREPARED)) {
        xbt_dynar_push(comms, &requests[i]->action);
-       map[size] = i;
-       size++;
+       map.push_back(i);
     }
   }
-  if(size > 0) {
+  if(!map.empty()) {
     //multiplier to the sleeptime, to increase speed of execution, each failed testany will increase it
     static int nsleeps = 1;
     if(smpi_test_sleep > 0) 
       simcall_process_sleep(nsleeps*smpi_test_sleep);
 
-    i = simcall_comm_testany(comms);
-    // not MPI_UNDEFINED, as this is a simix return code
-    if(i != -1) {
-      *index = map[i];
+    i = simcall_comm_testany(comms); // The i-th element in comms matches!
+    if (i != -1) { // -1 is not MPI_UNDEFINED but a SIMIX return code. (nothing matches)
+      *index = map[i]; 
       finish_wait(&requests[*index], status);
-      if (requests[*index] != MPI_REQUEST_NULL && (requests[*index]->flags & NON_PERSISTENT))
-      requests[*index] = MPI_REQUEST_NULL;
-      flag = 1;
-      nsleeps=1;
-    }else{
+      flag             = 1;
+      nsleeps          = 1;
+      if (requests[*index] != MPI_REQUEST_NULL && (requests[*index]->flags & NON_PERSISTENT)) {
+        requests[*index] = MPI_REQUEST_NULL;
+      }
+    } else {
       nsleeps++;
     }
-  }else{
+  } else {
       //all requests are null or inactive, return true
-      flag=1;
+      flag = 1;
       smpi_empty_status(status);
   }
-  xbt_free(map);
   xbt_dynar_free(&comms);
 
   return flag;
index 8e07eaf..97fad0b 100755 (executable)
@@ -279,7 +279,7 @@ if [ -z "${HOSTFILE}" ] ; then
                  }
                }
              } elsif (/<cluster/) {
-               die ("Unparsable cluster tag. Either provide an hostfile yourself or give the attributes prefix, radical and suffix in that order on the <cluster line");
+            die ("Unparsable cluster tag. smpirun uses a primitive regular expression to parse cluster tags. Either provide a hostfile yourself or give the attributes prefix, radical and suffix IN THAT ORDER and ON THE SAME LINE as the opening tag (<cluster)");
              }' ${PLATFORM} >> ${HOSTFILE}
 fi
 UNROLLEDHOSTFILETMP=0
index 52b1762..6c982bc 100644 (file)
@@ -39,7 +39,7 @@ void xbt_mutex_release(xbt_mutex_t mutex)
 
 void xbt_mutex_destroy(xbt_mutex_t mutex)
 {
-  SIMIX_mutex_destroy((smx_mutex_t) mutex);
+  SIMIX_mutex_unref((smx_mutex_t) mutex);
 }
 
 /***** condition related functions *****/
index eb8ef77..2bd4041 100644 (file)
@@ -381,6 +381,7 @@ set(S4U_SRC
   src/s4u/s4u_file.cpp  
   src/s4u/s4u_host.cpp  
   src/s4u/s4u_mailbox.cpp
+  src/s4u/s4u_mutex.cpp
   src/s4u/s4u_storage.cpp
 )
 
@@ -644,6 +645,7 @@ set(headers_to_install
   include/simgrid/s4u/file.hpp  
   include/simgrid/s4u/host.hpp  
   include/simgrid/s4u/mailbox.hpp  
+  include/simgrid/s4u/mutex.hpp
   include/simgrid/s4u/storage.hpp  
   include/simgrid/s4u.h
   include/simgrid/plugins/energy.h
@@ -817,6 +819,7 @@ set(DOC_SOURCES
   doc/doxygen/tutorial.doc
   doc/doxygen/models.doc
   doc/doxygen/module-msg.doc
+  doc/doxygen/module-s4u.doc
   doc/doxygen/module-sd.doc
   doc/doxygen/module-simix.doc
   doc/doxygen/module-smpi.doc
index c9659d3..961254f 100755 (executable)
@@ -31,7 +31,7 @@ die "Call this script from its location or from the SimGrid root directory\n" un
 
 die "Usage: ". ($DICTFILE eq "./spell_dict.txt"? "./":"tools/internal/")."spell_comments.pl "
            ."`find ". ($DICTFILE eq "./spell_dict.txt"? "../../":".")." -name '*.[ch]' -o -name '*.hpp' -o -name '*.cpp' |grep -v umpire|grep -v smpi/mpich3-test|grep -v NAS`\n"
-  unless scalar(@ARGV)>1;
+  unless scalar(@ARGV)>0;
 
 my $total = 0;
 foreach my $file (@ARGV) {
index fd23149..d05ad88 100644 (file)
@@ -18,6 +18,7 @@ defgroup
 dict
 dicts
 dontinclude
+doxygen
 DPOR
 dst
 dynar
diff --git a/tools/jenkins/Flags.sh b/tools/jenkins/Flags.sh
new file mode 100755 (executable)
index 0000000..931a135
--- /dev/null
@@ -0,0 +1,56 @@
+#!/bin/sh
+
+set -e
+
+die() {
+    echo "$@"
+    exit 1
+}
+
+do_cleanup() {
+  for d in "$WORKSPACE/build"
+  do
+    if [ -d "$d" ]
+    then
+      rm -rf "$d" || die "Could not remote $d"
+    fi
+  done
+}
+
+### Cleanup previous runs
+
+! [ -z "$WORKSPACE" ] || die "No WORKSPACE"
+[ -d "$WORKSPACE" ] || die "WORKSPACE ($WORKSPACE) does not exist"
+
+do_cleanup
+
+for d in "$WORKSPACE/build"
+do
+  mkdir "$d" || die "Could not create $d"
+done
+
+NUMPROC="$(nproc)" || NUMPROC=1
+
+cd $WORKSPACE/build
+
+for buildjava in ON OFF
+do
+  for buildmalloc in ON OFF
+  do
+    for buildsmpi in ON OFF
+    do
+      for buildmc in ON OFF
+      do
+        echo "build with java=${buildjava}, mallocators=${buildmalloc}, SMPI=${buildsmpi}, MC=${buildmc}"
+        cmake -Denable_documentation=OFF -Denable_lua=ON -Denable_java=${buildjava} \
+              -Denable_compile_optimizations=OFF -Denable_compile_warnings=ON \
+              -Denable_jedule=ON -Denable_mallocators=${buildmalloc} \
+              -Denable_smpi=${buildsmpi} -Denable_smpi_MPICH3_testsuite=${buildsmpi} -Denable_model-checking=${buildmc} \
+              -Denable_memcheck=OFF -Denable_memcheck_xml=OFF -Denable_smpi_ISP_testsuite=OFF -Denable_coverage=OFF $WORKSPACE
+        make -j$NUMPROC
+        make clean
+      done
+    done
+  done
+done 
+