#include "src/mc/mc_replay.hpp"
#include "src/simix/smx_private.hpp"
+#include "src/simix/MutexImpl.hpp"
+
#if SIMGRID_HAVE_MC
#include "src/mc/ModelChecker.hpp"
/* This program is free software; you can redistribute it and/or modify it
* under the terms of the license (GNU LGPL) which comes with this package. */
-#include "src/msg/msg_private.hpp"
-#include "src/simix/smx_synchro_private.hpp"
-#include "xbt/log.h"
-
#include "simgrid/s4u/Mutex.hpp"
+#include "src/simix/MutexImpl.hpp"
namespace simgrid {
namespace s4u {
void* getUserData() { return userdata; }
};
+/* Used to keep the list of actors blocked on a synchro */
+typedef boost::intrusive::list<ActorImpl, boost::intrusive::member_hook<ActorImpl, boost::intrusive::list_member_hook<>,
+ &ActorImpl::smx_synchro_hook>>
+ SynchroList;
}
}
--- /dev/null
+/* Copyright (c) 2007-2017. 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 "smx_private.hpp"
+#include "src/surf/cpu_interface.hpp"
+#include "src/surf/surf_interface.hpp"
+#include <xbt/ex.hpp>
+#include <xbt/log.h>
+#include <xbt/utility.hpp>
+
+#include "src/kernel/activity/SynchroRaw.hpp"
+#include "src/simix/MutexImpl.hpp"
+
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_mutex, simix_synchro, "Mutex kernel-space implementation");
+
+namespace simgrid {
+namespace simix {
+
+MutexImpl::MutexImpl() : mutex_(this)
+{
+ XBT_IN("(%p)", this);
+ XBT_OUT();
+}
+
+MutexImpl::~MutexImpl()
+{
+ XBT_IN("(%p)", this);
+ XBT_OUT();
+}
+
+void MutexImpl::lock(smx_actor_t issuer)
+{
+ XBT_IN("(%p; %p)", this, issuer);
+ /* FIXME: check where to validate the arguments */
+ smx_activity_t synchro = nullptr;
+
+ 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(issuer->host, -1);
+ synchro->simcalls.push_back(&issuer->simcall);
+ issuer->waiting_synchro = synchro;
+ this->sleeping.push_back(*issuer);
+ } else {
+ /* mutex free */
+ this->locked = true;
+ this->owner = issuer;
+ SIMIX_simcall_answer(&issuer->simcall);
+ }
+ XBT_OUT();
+}
+
+/** Tries to lock the mutex for a process
+ *
+ * \param issuer the process that tries to acquire the mutex
+ * \return whether we managed to lock the mutex
+ */
+bool MutexImpl::try_lock(smx_actor_t issuer)
+{
+ XBT_IN("(%p, %p)", this, issuer);
+ if (this->locked) {
+ XBT_OUT();
+ return false;
+ }
+
+ this->locked = true;
+ this->owner = issuer;
+ XBT_OUT();
+ return true;
+}
+
+/** 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.
+ */
+void MutexImpl::unlock(smx_actor_t issuer)
+{
+ XBT_IN("(%p, %p)", this, issuer);
+ if (not this->locked)
+ THROWF(mismatch_error, 0, "Cannot release that mutex: it was not locked.");
+
+ /* If the mutex is not owned by the issuer, that's not good */
+ if (issuer != this->owner)
+ THROWF(mismatch_error, 0, "Cannot release that mutex: it was locked by %s (pid:%lu), not by you.",
+ this->owner->getCname(), this->owner->pid);
+
+ if (not this->sleeping.empty()) {
+ /*process to wake up */
+ smx_actor_t p = &this->sleeping.front();
+ this->sleeping.pop_front();
+ p->waiting_synchro = nullptr;
+ this->owner = p;
+ SIMIX_simcall_answer(&p->simcall);
+ } else {
+ /* nobody to wake up */
+ this->locked = false;
+ this->owner = nullptr;
+ }
+ XBT_OUT();
+}
+}
+}
+
+/** Increase the refcount for this mutex */
+smx_mutex_t SIMIX_mutex_ref(smx_mutex_t mutex)
+{
+ 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);
+}
+
+// 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);
+}
--- /dev/null
+/* Copyright (c) 2012-2017. 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 SIMIX_MUTEXIMPL_HPP
+#define SIMIX_MUTEXIMPL_HPP
+
+#include "simgrid/s4u/ConditionVariable.hpp"
+#include "src/simix/ActorImpl.hpp"
+#include <boost/intrusive/list.hpp>
+
+namespace simgrid {
+namespace simix {
+
+class XBT_PUBLIC() MutexImpl {
+public:
+ MutexImpl();
+ ~MutexImpl();
+ MutexImpl(MutexImpl const&) = delete;
+ MutexImpl& operator=(MutexImpl const&) = delete;
+
+ void lock(smx_actor_t issuer);
+ bool try_lock(smx_actor_t issuer);
+ void unlock(smx_actor_t issuer);
+
+ bool locked = false;
+ smx_actor_t owner = nullptr;
+ // List of sleeping processes:
+ simgrid::simix::SynchroList sleeping;
+
+ // boost::intrusive_ptr<Mutex> support:
+ friend void intrusive_ptr_add_ref(MutexImpl* mutex)
+ {
+ XBT_ATTRIB_UNUSED auto previous = mutex->refcount_.fetch_add(1);
+ xbt_assert(previous != 0);
+ }
+ friend void intrusive_ptr_release(MutexImpl* mutex)
+ {
+ if (mutex->refcount_.fetch_sub(1) == 1)
+ delete mutex;
+ }
+
+ simgrid::s4u::Mutex& mutex() { return mutex_; }
+
+private:
+ std::atomic_int_fast32_t refcount_{1};
+ simgrid::s4u::Mutex mutex_;
+};
+}
+}
+#endif /* SIMIX_MUTEXIMPL_HPP */
#include "src/mc/mc_forward.hpp"
#include "src/mc/mc_replay.hpp"
#include "src/plugins/vm/VirtualMachineImpl.hpp"
+#include "src/simix/MutexImpl.hpp"
#include "src/simix/smx_host_private.hpp"
#include "xbt/ex.h"
#include "xbt/functional.hpp"
#include <xbt/utility.hpp>
#include "src/kernel/activity/SynchroRaw.hpp"
+#include "src/simix/MutexImpl.hpp"
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_synchro, simix, "SIMIX Synchronization (mutex, semaphores and conditions)");
-static smx_activity_t SIMIX_synchro_wait(sg_host_t smx_host, double timeout);
static void _SIMIX_cond_wait(smx_cond_t cond, smx_mutex_t mutex, double timeout,
smx_actor_t issuer, smx_simcall_t simcall);
static void _SIMIX_sem_wait(smx_sem_t sem, double timeout, smx_actor_t issuer,
/***************************** Raw synchronization *********************************/
-static smx_activity_t SIMIX_synchro_wait(sg_host_t smx_host, double timeout)
+smx_activity_t SIMIX_synchro_wait(sg_host_t smx_host, double timeout)
{
XBT_IN("(%p, %f)",smx_host,timeout);
SIMIX_simcall_answer(simcall);
XBT_OUT();
}
-/*********************************** Mutex ************************************/
-
-namespace simgrid {
-namespace simix {
-
-MutexImpl::MutexImpl() : mutex_(this)
-{
- XBT_IN("(%p)", this);
- XBT_OUT();
-}
-
-MutexImpl::~MutexImpl()
-{
- XBT_IN("(%p)", this);
- XBT_OUT();
-}
-
-void MutexImpl::lock(smx_actor_t issuer)
-{
- XBT_IN("(%p; %p)", this, issuer);
- /* FIXME: check where to validate the arguments */
- smx_activity_t synchro = nullptr;
-
- 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(issuer->host, -1);
- synchro->simcalls.push_back(&issuer->simcall);
- issuer->waiting_synchro = synchro;
- this->sleeping.push_back(*issuer);
- } else {
- /* mutex free */
- this->locked = true;
- this->owner = issuer;
- SIMIX_simcall_answer(&issuer->simcall);
- }
- XBT_OUT();
-}
-
-/** Tries to lock the mutex for a process
- *
- * \param issuer the process that tries to acquire the mutex
- * \return whether we managed to lock the mutex
- */
-bool MutexImpl::try_lock(smx_actor_t issuer)
-{
- XBT_IN("(%p, %p)", this, issuer);
- if (this->locked) {
- XBT_OUT();
- return false;
- }
-
- this->locked = true;
- this->owner = issuer;
- XBT_OUT();
- return true;
-}
-
-/** 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.
- */
-void MutexImpl::unlock(smx_actor_t issuer)
-{
- XBT_IN("(%p, %p)", this, issuer);
- if (not this->locked)
- THROWF(mismatch_error, 0, "Cannot release that mutex: it was not locked.");
-
- /* If the mutex is not owned by the issuer, that's not good */
- if (issuer != this->owner)
- THROWF(mismatch_error, 0, "Cannot release that mutex: it was locked by %s (pid:%lu), not by you.",
- this->owner->getCname(), this->owner->pid);
-
- if (not this->sleeping.empty()) {
- /*process to wake up */
- smx_actor_t p = &this->sleeping.front();
- this->sleeping.pop_front();
- p->waiting_synchro = nullptr;
- this->owner = p;
- SIMIX_simcall_answer(&p->simcall);
- } else {
- /* nobody to wake up */
- this->locked = false;
- this->owner = nullptr;
- }
- XBT_OUT();
-}
-
-}
-}
-
-/** Increase the refcount for this mutex */
-smx_mutex_t SIMIX_mutex_ref(smx_mutex_t mutex)
-{
- 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);
-}
-
-// 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 **********************************/
#include "src/simix/ActorImpl.hpp"
#include <boost/intrusive/list.hpp>
-namespace simgrid {
-namespace simix {
-
-typedef boost::intrusive::list<ActorImpl, boost::intrusive::member_hook<ActorImpl, boost::intrusive::list_member_hook<>,
- &ActorImpl::smx_synchro_hook>>
- SynchroList;
-
-class XBT_PUBLIC() MutexImpl {
-public:
- MutexImpl();
- ~MutexImpl();
- MutexImpl(MutexImpl const&) = delete;
- MutexImpl& operator=(MutexImpl const&) = delete;
-
- void lock(smx_actor_t issuer);
- bool try_lock(smx_actor_t issuer);
- void unlock(smx_actor_t issuer);
-
- bool locked = false;
- smx_actor_t owner = nullptr;
- // List of sleeping processes:
- simgrid::simix::SynchroList sleeping;
-
- // boost::intrusive_ptr<Mutex> support:
- friend void intrusive_ptr_add_ref(MutexImpl* mutex)
- {
- XBT_ATTRIB_UNUSED auto previous = mutex->refcount_.fetch_add(1);
- xbt_assert(previous != 0);
- }
- friend void intrusive_ptr_release(MutexImpl* mutex)
- {
- if (mutex->refcount_.fetch_sub(1) == 1)
- delete mutex;
- }
-
- simgrid::s4u::Mutex& mutex() { return mutex_; }
-
-private:
- std::atomic_int_fast32_t refcount_{1};
- simgrid::s4u::Mutex mutex_;
-};
-}
-}
+smx_activity_t SIMIX_synchro_wait(sg_host_t smx_host, double timeout);
struct s_smx_cond_t {
s_smx_cond_t() : cond_(this) {}
src/simix/smx_network.cpp
src/simix/ActorImpl.cpp
src/simix/ActorImpl.hpp
+ src/simix/MutexImpl.cpp
+ src/simix/MutexImpl.hpp
src/simix/smx_synchro.cpp
src/simix/popping.cpp
src/kernel/activity/ActivityImpl.cpp