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 \
- @subpage install
- @subpage install_yours
- @subpage application
+ - @subpage s4u_api
- @subpage MSG_API
- @subpage SD_API
- @subpage SMPI_API
\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
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.
\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 */
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
@tableofcontents
-blabla bla
+blah blah blah
@section <short_name_of_section> <title>
-bliblublo
+blah blah blah
@subsection <short_name_of_subsection> <title>
-/*!
-\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
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.
};
~~~~
-\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
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:
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
--- /dev/null
+/**
+@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.
+
+ *
processes_arrived_sofar--;
if (processes_arrived_sofar<=0) {
SIMIX_cond_destroy(cond);
- SIMIX_mutex_destroy(mutex);
+ SIMIX_mutex_unref(mutex);
mutex = NULL;
}
}
-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})
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)
-/* 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. */
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;
}
{
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;
}
--- /dev/null
+/* 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;
+}
--- /dev/null
+#! ./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
#include "s4u/engine.hpp"
#include "s4u/host.hpp"
+#include "s4u/mutex.hpp"
#include "s4u/Activity.hpp"
#include "s4u/comm.hpp"
-/* 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
/** 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);
};
-}} // 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 */
--- /dev/null
+/* 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 */
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;
/** @} */
/* ******************************** Synchro ************************************ */
-/**
- * \ingroup simix_synchro_management
- */
-typedef struct s_smx_mutex *smx_mutex_t;
+
/**
* \ingroup simix_synchro_management
*/
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);
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);
/************************** 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);
#ifndef _XBT_THREAD_H
#define _XBT_THREAD_H
+#include <simgrid/simix.h>
+
#include "xbt/misc.h" /* SG_BEGIN_DECL */
#include "xbt/function_types.h"
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;
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
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)
));
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;
}
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);
}
--- /dev/null
+/* 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_);
+}
+
+}
+}
}
/**
- * \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,
{
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()){
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.
*
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;
#ifndef _SIMIX_PROCESS_PRIVATE_H
#define _SIMIX_PROCESS_PRIVATE_H
+#include <atomic>
#include <functional>
#include <string>
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 };
};
}
+
/* Copyright (c) 2007-2015. The SimGrid Team.
* All rights reserved. */
}
/*********************************** 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 **********************************/
/* 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);
#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;
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);
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;
{
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;
}
}
} 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
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 *****/
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
)
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
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
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) {
dict
dicts
dontinclude
+doxygen
DPOR
dst
dynar
--- /dev/null
+#!/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
+