From: Martin Quinson Date: Sun, 15 Apr 2018 19:56:19 +0000 (+0200) Subject: Separate ConditionVariableImpl into its own files X-Git-Tag: v3.20~425 X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/commitdiff_plain/0224a9ae5debdfc901f8f201b9567b8b0825740a Separate ConditionVariableImpl into its own files First step toward modernity in this area. That's a detour while snake_casing s4u::ConditionVariable :( --- diff --git a/include/simgrid/s4u/ConditionVariable.hpp b/include/simgrid/s4u/ConditionVariable.hpp index 77811c0d03..8e89a59fdd 100644 --- a/include/simgrid/s4u/ConditionVariable.hpp +++ b/include/simgrid/s4u/ConditionVariable.hpp @@ -34,7 +34,9 @@ public: friend XBT_PUBLIC void intrusive_ptr_release(ConditionVariable * cond); using Ptr = boost::intrusive_ptr; - static Ptr createConditionVariable(); + static Ptr create(); + + XBT_ATTRIB_DEPRECATED_v323("Please use Comm::get_mailbox()") Ptr createConditionVariable() { return create(); } // Wait functions without time: diff --git a/src/kernel/activity/CommImpl.hpp b/src/kernel/activity/CommImpl.hpp index 849f605785..4f00dc0f28 100644 --- a/src/kernel/activity/CommImpl.hpp +++ b/src/kernel/activity/CommImpl.hpp @@ -3,8 +3,8 @@ /* This program is free software; you can redistribute it and/or modify it * under the terms of the license (GNU LGPL) which comes with this package. */ -#ifndef SIMIX_SYNCHRO_COMM_HPP -#define SIMIX_SYNCHRO_COMM_HPP +#ifndef SIMGRID_KERNEL_ACTIVITY_COMM_HPP +#define SIMGRID_KERNEL_ACTIVITY_COMM_HPP #include "src/kernel/activity/ActivityImpl.hpp" #include "surf/surf.hpp" diff --git a/src/kernel/activity/ConditionVariableImpl.cpp b/src/kernel/activity/ConditionVariableImpl.cpp new file mode 100644 index 0000000000..349a206e96 --- /dev/null +++ b/src/kernel/activity/ConditionVariableImpl.cpp @@ -0,0 +1,165 @@ +/* Copyright (c) 2007-2018. 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 "src/kernel/activity/ConditionVariableImpl.hpp" +#include "src/kernel/activity/MutexImpl.hpp" +#include "src/kernel/activity/SynchroRaw.hpp" +#include "src/simix/smx_synchro_private.hpp" +#include "xbt/ex.hpp" + +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(ConditionVariable, simix_synchro, "Condition variables"); + +static void _SIMIX_cond_wait(smx_cond_t cond, smx_mutex_t mutex, double timeout, smx_actor_t issuer, + smx_simcall_t simcall); + +/********************************* Condition **********************************/ + +/** + * \brief Initialize a condition. + * + * Allocates and creates the data for the condition. + * It have to be called before the use of the condition. + * \return A condition + */ +smx_cond_t SIMIX_cond_init() +{ + XBT_IN("()"); + smx_cond_t cond = new s_smx_cond_t(); + XBT_OUT(); + return cond; +} + +/** + * \brief Handle a condition waiting simcall without timeouts + * \param simcall the simcall + */ +void simcall_HANDLER_cond_wait(smx_simcall_t simcall, smx_cond_t cond, smx_mutex_t mutex) +{ + XBT_IN("(%p)", simcall); + smx_actor_t issuer = simcall->issuer; + + _SIMIX_cond_wait(cond, mutex, -1, issuer, simcall); + XBT_OUT(); +} + +/** + * \brief Handle a condition waiting simcall with timeouts + * \param simcall the simcall + */ +void simcall_HANDLER_cond_wait_timeout(smx_simcall_t simcall, smx_cond_t cond, smx_mutex_t mutex, double timeout) +{ + XBT_IN("(%p)", simcall); + smx_actor_t issuer = simcall->issuer; + + _SIMIX_cond_wait(cond, mutex, timeout, issuer, simcall); + XBT_OUT(); +} + +static void _SIMIX_cond_wait(smx_cond_t cond, smx_mutex_t mutex, double timeout, smx_actor_t issuer, + smx_simcall_t simcall) +{ + XBT_IN("(%p, %p, %f, %p,%p)", cond, mutex, timeout, issuer, simcall); + smx_activity_t synchro = nullptr; + + XBT_DEBUG("Wait condition %p", cond); + + /* If there is a mutex unlock it */ + /* FIXME: what happens if the issuer is not the owner of the mutex? */ + if (mutex != nullptr) { + cond->mutex = mutex; + mutex->unlock(issuer); + } + + synchro = SIMIX_synchro_wait(issuer->host, timeout); + synchro->simcalls.push_front(simcall); + issuer->waiting_synchro = synchro; + cond->sleeping.push_back(*simcall->issuer); + XBT_OUT(); +} + +/** + * \brief Signalizes a condition. + * + * Signalizes a condition and wakes up a sleeping process. + * If there are no process sleeping, no action is done. + * \param cond A condition + */ +void SIMIX_cond_signal(smx_cond_t cond) +{ + XBT_IN("(%p)", cond); + XBT_DEBUG("Signal condition %p", cond); + + /* If there are processes waiting for the condition choose one and try + to make it acquire the mutex */ + if (not cond->sleeping.empty()) { + auto& proc = cond->sleeping.front(); + cond->sleeping.pop_front(); + + /* Destroy waiter's synchronization */ + proc.waiting_synchro = nullptr; + + /* Now transform the cond wait simcall into a mutex lock one */ + smx_simcall_t simcall = &proc.simcall; + smx_mutex_t mutex; + if (simcall->call == SIMCALL_COND_WAIT) + mutex = simcall_cond_wait__get__mutex(simcall); + else + mutex = simcall_cond_wait_timeout__get__mutex(simcall); + simcall->call = SIMCALL_MUTEX_LOCK; + + simcall_HANDLER_mutex_lock(simcall, mutex); + } + XBT_OUT(); +} + +/** + * \brief Broadcasts a condition. + * + * Signal ALL processes waiting on a condition. + * If there are no process waiting, no action is done. + * \param cond A condition + */ +void SIMIX_cond_broadcast(smx_cond_t cond) +{ + XBT_IN("(%p)", cond); + XBT_DEBUG("Broadcast condition %p", cond); + + /* Signal the condition until nobody is waiting on it */ + while (not cond->sleeping.empty()) { + SIMIX_cond_signal(cond); + } + XBT_OUT(); +} + +smx_cond_t SIMIX_cond_ref(smx_cond_t cond) +{ + if (cond != nullptr) + intrusive_ptr_add_ref(cond); + return cond; +} + +void SIMIX_cond_unref(smx_cond_t cond) +{ + XBT_IN("(%p)", cond); + XBT_DEBUG("Destroy condition %p", cond); + if (cond != nullptr) { + intrusive_ptr_release(cond); + } + XBT_OUT(); +} + +void intrusive_ptr_add_ref(s_smx_cond_t* cond) +{ + auto previous = cond->refcount_.fetch_add(1); + xbt_assert(previous != 0); +} + +void intrusive_ptr_release(s_smx_cond_t* cond) +{ + if (cond->refcount_.fetch_sub(1) == 1) { + xbt_assert(cond->sleeping.empty(), "Cannot destroy conditional since someone is still using it"); + delete cond; + } +} diff --git a/src/kernel/activity/ConditionVariableImpl.hpp b/src/kernel/activity/ConditionVariableImpl.hpp new file mode 100644 index 0000000000..e0634e66ae --- /dev/null +++ b/src/kernel/activity/ConditionVariableImpl.hpp @@ -0,0 +1,28 @@ +/* Copyright (c) 2012-2018. 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_KERNEL_ACTIVITY_CONDITIONVARIABLEIMPL_HPP +#define SIMGRID_KERNEL_ACTIVITY_CONDITIONVARIABLEIMPL_HPP + +#include "simgrid/s4u/ConditionVariable.hpp" +#include "src/simix/ActorImpl.hpp" +#include + +struct s_smx_cond_t { + s_smx_cond_t() : cond_(this) {} + + std::atomic_int_fast32_t refcount_{1}; + smx_mutex_t mutex = nullptr; + simgrid::kernel::actor::SynchroList sleeping; /* list of sleeping processes */ + simgrid::s4u::ConditionVariable cond_; +}; + +XBT_PRIVATE smx_cond_t SIMIX_cond_init(); +XBT_PRIVATE void SIMIX_cond_broadcast(smx_cond_t cond); +XBT_PRIVATE void SIMIX_cond_signal(smx_cond_t cond); +XBT_PRIVATE void intrusive_ptr_add_ref(s_smx_cond_t* cond); +XBT_PRIVATE void intrusive_ptr_release(s_smx_cond_t* cond); + +#endif diff --git a/src/kernel/activity/MailboxImpl.cpp b/src/kernel/activity/MailboxImpl.cpp index d859649af9..647c643ff4 100644 --- a/src/kernel/activity/MailboxImpl.cpp +++ b/src/kernel/activity/MailboxImpl.cpp @@ -4,7 +4,6 @@ * under the terms of the license (GNU LGPL) which comes with this package. */ #include "src/kernel/activity/MailboxImpl.hpp" - #include "src/kernel/activity/CommImpl.hpp" XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_mailbox, simix, "Mailbox implementation"); diff --git a/src/s4u/s4u_conditionVariable.cpp b/src/s4u/s4u_conditionVariable.cpp index 9a096b17e3..0def488914 100644 --- a/src/s4u/s4u_conditionVariable.cpp +++ b/src/s4u/s4u_conditionVariable.cpp @@ -11,12 +11,12 @@ #include "simgrid/s4u/ConditionVariable.hpp" #include "simgrid/simix.h" -#include "src/simix/smx_synchro_private.hpp" +#include "src/kernel/activity/ConditionVariableImpl.hpp" namespace simgrid { namespace s4u { -ConditionVariablePtr ConditionVariable::createConditionVariable() +ConditionVariablePtr ConditionVariable::create() { smx_cond_t cond = simcall_cond_init(); return ConditionVariablePtr(&cond->cond_, false); diff --git a/src/simix/libsmx.cpp b/src/simix/libsmx.cpp index 5a87f19a29..943902b52c 100644 --- a/src/simix/libsmx.cpp +++ b/src/simix/libsmx.cpp @@ -20,6 +20,7 @@ #include "simgrid/simix/blocking_simcall.hpp" #include "smx_private.hpp" #include "src/kernel/activity/CommImpl.hpp" +#include "src/kernel/activity/ConditionVariableImpl.hpp" #include "src/kernel/activity/MutexImpl.hpp" #include "src/mc/mc_forward.hpp" #include "src/mc/mc_replay.hpp" diff --git a/src/simix/popping_generated.cpp b/src/simix/popping_generated.cpp index 095603e8ae..bd9f4df373 100644 --- a/src/simix/popping_generated.cpp +++ b/src/simix/popping_generated.cpp @@ -19,6 +19,7 @@ #if SIMGRID_HAVE_MC #include "src/mc/mc_forward.hpp" #endif +#include "src/kernel/activity/ConditionVariableImpl.hpp" #include "src/simix/smx_host_private.hpp" #include "src/simix/smx_synchro_private.hpp" diff --git a/src/simix/simcalls.py b/src/simix/simcalls.py index 1467d6f139..696b6f0615 100755 --- a/src/simix/simcalls.py +++ b/src/simix/simcalls.py @@ -311,6 +311,7 @@ if __name__ == '__main__': fd.write('#if SIMGRID_HAVE_MC\n') fd.write('#include "src/mc/mc_forward.hpp"\n') fd.write('#endif\n') + fd.write('#include "src/kernel/activity/ConditionVariableImpl.hpp"\n') fd.write('#include "src/simix/smx_synchro_private.hpp"\n') fd.write('#include "src/simix/smx_host_private.hpp"\n') diff --git a/src/simix/smx_synchro.cpp b/src/simix/smx_synchro.cpp index 96275c3fea..f961a2cc78 100644 --- a/src/simix/smx_synchro.cpp +++ b/src/simix/smx_synchro.cpp @@ -4,6 +4,7 @@ * under the terms of the license (GNU LGPL) which comes with this package. */ #include "smx_private.hpp" +#include "src/kernel/activity/ConditionVariableImpl.hpp" #include "src/kernel/activity/MutexImpl.hpp" #include "src/kernel/activity/SynchroRaw.hpp" #include "src/simix/smx_synchro_private.hpp" @@ -89,160 +90,6 @@ void SIMIX_synchro_finish(smx_activity_t synchro) XBT_OUT(); } -/********************************* Condition **********************************/ - -/** - * \brief Initialize a condition. - * - * Allocates and creates the data for the condition. - * It have to be called before the use of the condition. - * \return A condition - */ -smx_cond_t SIMIX_cond_init() -{ - XBT_IN("()"); - smx_cond_t cond = new s_smx_cond_t(); - cond->refcount_ = 1; - XBT_OUT(); - return cond; -} - -/** - * \brief Handle a condition waiting simcall without timeouts - * \param simcall the simcall - */ -void simcall_HANDLER_cond_wait(smx_simcall_t simcall, smx_cond_t cond, smx_mutex_t mutex) -{ - XBT_IN("(%p)",simcall); - smx_actor_t issuer = simcall->issuer; - - _SIMIX_cond_wait(cond, mutex, -1, issuer, simcall); - XBT_OUT(); -} - -/** - * \brief Handle a condition waiting simcall with timeouts - * \param simcall the simcall - */ -void simcall_HANDLER_cond_wait_timeout(smx_simcall_t simcall, smx_cond_t cond, - smx_mutex_t mutex, double timeout) -{ - XBT_IN("(%p)",simcall); - smx_actor_t issuer = simcall->issuer; - - _SIMIX_cond_wait(cond, mutex, timeout, issuer, simcall); - XBT_OUT(); -} - - -static void _SIMIX_cond_wait(smx_cond_t cond, smx_mutex_t mutex, double timeout, - smx_actor_t issuer, smx_simcall_t simcall) -{ - XBT_IN("(%p, %p, %f, %p,%p)",cond,mutex,timeout,issuer,simcall); - smx_activity_t synchro = nullptr; - - XBT_DEBUG("Wait condition %p", cond); - - /* If there is a mutex unlock it */ - /* FIXME: what happens if the issuer is not the owner of the mutex? */ - if (mutex != nullptr) { - cond->mutex = mutex; - mutex->unlock(issuer); - } - - synchro = SIMIX_synchro_wait(issuer->host, timeout); - synchro->simcalls.push_front(simcall); - issuer->waiting_synchro = synchro; - cond->sleeping.push_back(*simcall->issuer); - XBT_OUT(); -} - -/** - * \brief Signalizes a condition. - * - * Signalizes a condition and wakes up a sleeping process. - * If there are no process sleeping, no action is done. - * \param cond A condition - */ -void SIMIX_cond_signal(smx_cond_t cond) -{ - XBT_IN("(%p)",cond); - XBT_DEBUG("Signal condition %p", cond); - - /* If there are processes waiting for the condition choose one and try - to make it acquire the mutex */ - if (not cond->sleeping.empty()) { - auto& proc = cond->sleeping.front(); - cond->sleeping.pop_front(); - - /* Destroy waiter's synchronization */ - proc.waiting_synchro = nullptr; - - /* Now transform the cond wait simcall into a mutex lock one */ - smx_simcall_t simcall = &proc.simcall; - smx_mutex_t mutex; - if(simcall->call == SIMCALL_COND_WAIT) - mutex = simcall_cond_wait__get__mutex(simcall); - else - mutex = simcall_cond_wait_timeout__get__mutex(simcall); - simcall->call = SIMCALL_MUTEX_LOCK; - - simcall_HANDLER_mutex_lock(simcall, mutex); - } - XBT_OUT(); -} - -/** - * \brief Broadcasts a condition. - * - * Signal ALL processes waiting on a condition. - * If there are no process waiting, no action is done. - * \param cond A condition - */ -void SIMIX_cond_broadcast(smx_cond_t cond) -{ - XBT_IN("(%p)",cond); - XBT_DEBUG("Broadcast condition %p", cond); - - /* Signal the condition until nobody is waiting on it */ - while (not cond->sleeping.empty()) { - SIMIX_cond_signal(cond); - } - XBT_OUT(); -} - -smx_cond_t SIMIX_cond_ref(smx_cond_t cond) -{ - if (cond != nullptr) - intrusive_ptr_add_ref(cond); - return cond; -} - -void SIMIX_cond_unref(smx_cond_t cond) -{ - XBT_IN("(%p)",cond); - XBT_DEBUG("Destroy condition %p", cond); - if (cond != nullptr) { - intrusive_ptr_release(cond); - } - XBT_OUT(); -} - - -void intrusive_ptr_add_ref(s_smx_cond_t *cond) -{ - auto previous = cond->refcount_.fetch_add(1); - xbt_assert(previous != 0); -} - -void intrusive_ptr_release(s_smx_cond_t *cond) -{ - if (cond->refcount_.fetch_sub(1) == 1) { - xbt_assert(cond->sleeping.empty(), "Cannot destroy conditional since someone is still using it"); - delete cond; - } -} - /******************************** Semaphores **********************************/ /** @brief Initialize a semaphore */ smx_sem_t SIMIX_sem_init(unsigned int value) diff --git a/src/simix/smx_synchro_private.hpp b/src/simix/smx_synchro_private.hpp index 76f8a9cfc3..22a765a38f 100644 --- a/src/simix/smx_synchro_private.hpp +++ b/src/simix/smx_synchro_private.hpp @@ -12,15 +12,6 @@ smx_activity_t SIMIX_synchro_wait(sg_host_t smx_host, double timeout); -struct s_smx_cond_t { - s_smx_cond_t() : cond_(this) {} - - std::atomic_int_fast32_t refcount_{1}; - smx_mutex_t mutex = nullptr; - simgrid::kernel::actor::SynchroList sleeping; /* list of sleeping processes */ - simgrid::s4u::ConditionVariable cond_; -}; - struct s_smx_sem_t { unsigned int value; simgrid::kernel::actor::SynchroList sleeping; /* list of sleeping processes */ @@ -29,12 +20,6 @@ struct s_smx_sem_t { XBT_PRIVATE void SIMIX_synchro_stop_waiting(smx_actor_t process, smx_simcall_t simcall); XBT_PRIVATE void SIMIX_synchro_finish(smx_activity_t synchro); -XBT_PRIVATE smx_cond_t SIMIX_cond_init(); -XBT_PRIVATE void SIMIX_cond_broadcast(smx_cond_t cond); -XBT_PRIVATE void SIMIX_cond_signal(smx_cond_t cond); -XBT_PRIVATE void intrusive_ptr_add_ref(s_smx_cond_t* cond); -XBT_PRIVATE void intrusive_ptr_release(s_smx_cond_t* cond); - XBT_PRIVATE XBT_PRIVATE smx_sem_t SIMIX_sem_init(unsigned int value); XBT_PRIVATE void SIMIX_sem_release(smx_sem_t sem); XBT_PRIVATE int SIMIX_sem_would_block(smx_sem_t sem); diff --git a/tools/cmake/DefinePackages.cmake b/tools/cmake/DefinePackages.cmake index fed584c885..69ba68b1d9 100644 --- a/tools/cmake/DefinePackages.cmake +++ b/tools/cmake/DefinePackages.cmake @@ -387,6 +387,8 @@ set(SIMIX_SRC src/simix/popping.cpp src/kernel/activity/ActivityImpl.cpp src/kernel/activity/ActivityImpl.hpp + src/kernel/activity/ConditionVariableImpl.cpp + src/kernel/activity/ConditionVariableImpl.hpp src/kernel/activity/CommImpl.cpp src/kernel/activity/CommImpl.hpp src/kernel/activity/ExecImpl.cpp