From a115759128a9c4cef65fe6fee3d54c0d352d3f7d Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Sun, 25 Jan 2009 14:39:18 +0100 Subject: [PATCH 01/15] new mutex and recmutex implementation (breaks sync.hpp for now) prepares that chained sections if different kinds can be mixed makes recmutexes typesafe improves nobug tracking --- src/common/interfaceregistry.c | 4 +- src/common/interfaceregistry.h | 4 +- src/lib/Makefile.am | 1 + src/lib/mutex.c | 39 ++---- src/lib/mutex.h | 244 +++++++++++++++------------------ src/lib/recmutex.c | 74 ++++++++++ src/lib/sectionlock.h | 83 +++++++++++ src/lib/sync.hpp | 42 +++--- tests/15locking.tests | 8 +- tests/library/test-locking.c | 34 ++++- 10 files changed, 343 insertions(+), 190 deletions(-) create mode 100644 src/lib/recmutex.c create mode 100644 src/lib/sectionlock.h diff --git a/src/common/interfaceregistry.c b/src/common/interfaceregistry.c index ad8bd8224..5b0db98e7 100644 --- a/src/common/interfaceregistry.c +++ b/src/common/interfaceregistry.c @@ -47,7 +47,7 @@ PSplay lumiera_interfaceregistry; PSplay lumiera_pluginregistry; -lumiera_mutex lumiera_interface_mutex; +lumiera_recmutex lumiera_interface_mutex; static int lumiera_interface_cmp_fn (const void* keya, const void* keyb); @@ -126,7 +126,7 @@ lumiera_interfaceregistry_destroy (void) psplay_delete (lumiera_pluginregistry); lumiera_pluginregistry = NULL; - lumiera_mutex_destroy (&lumiera_interface_mutex, &NOBUG_FLAG(mutex_dbg)); + lumiera_recmutex_destroy (&lumiera_interface_mutex, &NOBUG_FLAG(mutex_dbg)); REQUIRE (!psplay_nelements (lumiera_interfaceregistry), "some interfaces still registered at shutdown"); diff --git a/src/common/interfaceregistry.h b/src/common/interfaceregistry.h index 8adc46313..0ec20f29c 100644 --- a/src/common/interfaceregistry.h +++ b/src/common/interfaceregistry.h @@ -42,7 +42,7 @@ //NOBUG_DECLARE_FLAG (interface); extern PSplay lumiera_interfaceregistry; -extern lumiera_mutex lumiera_interface_mutex; +extern lumiera_recmutex lumiera_interface_mutex; /** @@ -75,8 +75,6 @@ struct lumiera_interfacenode_struct LumieraInterfacenode* deps; }; -extern lumiera_mutex lumiera_interface_mutex; - /** * Initialize the interface registry diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index cb1451c4f..0163d0c4c 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -25,6 +25,7 @@ liblumiera_la_SOURCES = \ $(liblumiera_la_srcdir)/error.c \ $(liblumiera_la_srcdir)/exception.cpp \ $(liblumiera_la_srcdir)/mutex.c \ + $(liblumiera_la_srcdir)/recmutex.c \ $(liblumiera_la_srcdir)/rwlock.c \ $(liblumiera_la_srcdir)/condition.c \ $(liblumiera_la_srcdir)/reccondition.c \ diff --git a/src/lib/mutex.c b/src/lib/mutex.c index 60078671d..d6961982d 100644 --- a/src/lib/mutex.c +++ b/src/lib/mutex.c @@ -26,9 +26,9 @@ * Mutual exclusion locking. */ -LUMIERA_ERROR_DEFINE (MUTEX_LOCK, "Mutex locking failed"); -LUMIERA_ERROR_DEFINE (MUTEX_UNLOCK, "Mutex unlocking failed"); -LUMIERA_ERROR_DEFINE (MUTEX_DESTROY, "Mutex destroy failed"); +LUMIERA_ERROR_DEFINE (LOCK_ACQUIRE, "locking failed"); +LUMIERA_ERROR_DEFINE (LOCK_RELEASE, "unlocking failed"); +LUMIERA_ERROR_DEFINE (LOCK_DESTROY, "lock destroy failed"); LumieraMutex @@ -44,32 +44,6 @@ lumiera_mutex_init (LumieraMutex self, const char* purpose, struct nobug_flag* f } -static pthread_once_t recursive_mutexattr_once = PTHREAD_ONCE_INIT; -static pthread_mutexattr_t recursive_mutexattr; - -static void recursive_mutexattr_init() -{ - pthread_mutexattr_init (&recursive_mutexattr); - pthread_mutexattr_settype (&recursive_mutexattr, PTHREAD_MUTEX_RECURSIVE); -} - - -LumieraMutex -lumiera_recmutex_init (LumieraMutex self, const char* purpose, struct nobug_flag* flag) -{ - if (self) - { - if (recursive_mutexattr_once == PTHREAD_ONCE_INIT) - pthread_once (&recursive_mutexattr_once, recursive_mutexattr_init); - - pthread_mutex_init (&self->mutex, &recursive_mutexattr); - NOBUG_RESOURCE_HANDLE_INIT (self->rh); - NOBUG_RESOURCE_ANNOUNCE_RAW (flag, "recmutex", purpose, self, self->rh); - } - return self; -} - - LumieraMutex lumiera_mutex_destroy (LumieraMutex self, struct nobug_flag* flag) { @@ -77,11 +51,16 @@ lumiera_mutex_destroy (LumieraMutex self, struct nobug_flag* flag) { NOBUG_RESOURCE_FORGET_RAW (flag, self->rh); if (pthread_mutex_destroy (&self->mutex)) - LUMIERA_DIE (MUTEX_DESTROY); + LUMIERA_DIE (LOCK_DESTROY); } return self; } +int lumiera_mutex_unlock_cb (void* mutex) +{ + return pthread_mutex_unlock ((pthread_mutex_t*) mutex); +} + /* // Local Variables: // mode: C diff --git a/src/lib/mutex.h b/src/lib/mutex.h index 0ab5b43c2..378fe00f1 100644 --- a/src/lib/mutex.h +++ b/src/lib/mutex.h @@ -23,6 +23,7 @@ #define LUMIERA_MUTEX_H #include "lib/error.h" +#include "lib/sectionlock.h" #include #include @@ -32,35 +33,30 @@ * Mutual exclusion locking, header. */ -LUMIERA_ERROR_DECLARE (MUTEX_LOCK); -LUMIERA_ERROR_DECLARE (MUTEX_UNLOCK); -LUMIERA_ERROR_DECLARE (MUTEX_DESTROY); /** * Mutual exclusive section. */ -#define LUMIERA_MUTEX_SECTION(nobugflag, mtx) \ - for (lumiera_mutexacquirer NOBUG_CLEANUP(lumiera_mutexacquirer_ensureunlocked) lumiera_mutex_section_ \ - = {(LumieraMutex)1 NOBUG_ALPHA_COMMA_NULL}; \ - lumiera_mutex_section_.mutex;) \ - for ( \ - ({ \ - lumiera_mutex_section_.mutex = (mtx); \ - NOBUG_RESOURCE_HANDLE_INIT (lumiera_mutex_section_.rh); \ - RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire mutex", &lumiera_mutex_section_, \ - NOBUG_RESOURCE_EXCLUSIVE, lumiera_mutex_section_.rh); \ - if (pthread_mutex_lock (&(mtx)->mutex)) LUMIERA_DIE (MUTEX_LOCK); \ - }); \ - lumiera_mutex_section_.mutex; \ - ({ \ - if (lumiera_mutex_section_.mutex) \ - { \ - pthread_mutex_unlock (&lumiera_mutex_section_.mutex->mutex); \ - lumiera_mutex_section_.mutex = NULL; \ - RESOURCE_LEAVE(nobugflag, lumiera_mutex_section_.rh); \ - } \ +#define LUMIERA_MUTEX_SECTION(nobugflag, mtx) \ + for (lumiera_sectionlock NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) \ + lumiera_lock_section_ = { \ + (void*)1, lumiera_mutex_unlock_cb NOBUG_ALPHA_COMMA_NULL NOBUG_ALPHA_COMMA_NULL}; \ + lumiera_lock_section_.lock;) \ + for ( \ + ({ \ + lumiera_lock_section_.lock = &(mtx)->mutex; \ + NOBUG_IF_ALPHA(lumiera_lock_section_.flag = &NOBUG_FLAG(nobugflag);) \ + RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire mutex", &lumiera_lock_section_, \ + NOBUG_RESOURCE_WAITING, lumiera_lock_section_.rh); \ + if (pthread_mutex_lock (lumiera_lock_section_.lock)) LUMIERA_DIE (LOCK_ACQUIRE); \ + RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_EXCLUSIVE, lumiera_lock_section_.rh); \ + }); \ + lumiera_lock_section_.lock; \ + ({ \ + LUMIERA_MUTEX_SECTION_UNLOCK; \ })) + /** * Mutual exclusion chainbuilder section. * Usage: LUMIERA_MUTEX_SECTION(a){LUMIERA_MUTEX_SECTION_CHAIN(b){run();}} @@ -68,99 +64,81 @@ LUMIERA_ERROR_DECLARE (MUTEX_DESTROY); * This macro should only be used inside LUMIERA_MUTEX_SECTION and should be * called on the correct mutexes, period. */ -#define LUMIERA_MUTEX_SECTION_CHAIN(nobugflag, mtx) \ - for (lumiera_mutexacquirer *lumiera_mutex_section_old_ = &lumiera_mutex_section_, \ - NOBUG_CLEANUP(lumiera_mutexacquirer_ensureunlocked) lumiera_mutex_section_ = {(LumieraMutex)1 \ - NOBUG_ALPHA_COMMA_NULL}; \ - lumiera_mutex_section_.mutex;) \ - for ( \ - ({ \ - lumiera_mutex_section_.mutex = (mtx); \ - NOBUG_RESOURCE_HANDLE_INIT (lumiera_mutex_section_.rh); \ - RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire mutex", &lumiera_mutex_section_, \ - NOBUG_RESOURCE_EXCLUSIVE, lumiera_mutex_section_.rh); \ - if (pthread_mutex_lock (&(mtx)->mutex)) LUMIERA_DIE (MUTEX_LOCK); \ - if (lumiera_mutex_section_old_->mutex) \ - { \ - pthread_mutex_unlock (&lumiera_mutex_section_old_->mutex->mutex); \ - lumiera_mutex_section_old_->mutex = NULL; \ - RESOURCE_LEAVE(nobugflag, lumiera_mutex_section_old_->rh); \ - } \ - }); \ - lumiera_mutex_section_.mutex; \ - ({ \ - if (lumiera_mutex_section_.mutex) \ - { \ - pthread_mutex_unlock (&lumiera_mutex_section_.mutex->mutex); \ - lumiera_mutex_section_.mutex = NULL; \ - RESOURCE_LEAVE(nobugflag, lumiera_mutex_section_.rh); \ - } \ + +#define LUMIERA_MUTEX_SECTION_CHAIN(nobugflag, mtx) \ + for (lumiera_sectionlock *lumiera_lock_section_old_ = &lumiera_lock_section_, \ + NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) lumiera_lock_section_ = { \ + (void*)1, lumiera_mutex_unlock_cb NOBUG_ALPHA_COMMA_NULL NOBUG_ALPHA_COMMA_NULL}; \ + lumiera_lock_section_.lock;) \ + for ( \ + ({ \ + lumiera_lock_section_.lock = &(mtx)->mutex; \ + NOBUG_IF_ALPHA(lumiera_lock_section_.flag = &NOBUG_FLAG(nobugflag);) \ + RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire mutex", &lumiera_lock_section_, \ + NOBUG_RESOURCE_WAITING, lumiera_lock_section_.rh); \ + if (pthread_mutex_lock (lumiera_lock_section_.lock)) LUMIERA_DIE (LOCK_ACQUIRE); \ + RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_EXCLUSIVE, lumiera_lock_section_.rh); \ + LUMIERA_SECTION_UNLOCK_(lumiera_lock_section_old_); \ + }); \ + lumiera_lock_section_.lock; \ + ({ \ + LUMIERA_MUTEX_SECTION_UNLOCK; \ })) +#define LUMIERA_MUTEX_SECTION_UNLOCK \ + LUMIERA_SECTION_UNLOCK_(&lumiera_lock_section_) + + /** * Recursive Mutual exclusive section. */ -#define LUMIERA_RECMUTEX_SECTION(nobugflag, mtx) \ - for (lumiera_mutexacquirer NOBUG_CLEANUP(lumiera_mutexacquirer_ensureunlocked) lumiera_mutex_section_ \ - = {(LumieraMutex)1 NOBUG_ALPHA_COMMA_NULL}; \ - lumiera_mutex_section_.mutex;) \ - for ( \ - ({ \ - lumiera_mutex_section_.mutex = (mtx); \ - NOBUG_RESOURCE_HANDLE_INIT (lumiera_mutex_section_.rh); \ - RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire recmutex", &lumiera_mutex_section_, \ - NOBUG_RESOURCE_RECURSIVE, lumiera_mutex_section_.rh); \ - if (pthread_mutex_lock (&(mtx)->mutex)) LUMIERA_DIE (MUTEX_LOCK); \ - }); \ - lumiera_mutex_section_.mutex; \ - ({ \ - if (lumiera_mutex_section_.mutex) \ - { \ - pthread_mutex_unlock (&lumiera_mutex_section_.mutex->mutex); \ - lumiera_mutex_section_.mutex = NULL; \ - RESOURCE_LEAVE(nobugflag, lumiera_mutex_section_.rh); \ - } \ +#define LUMIERA_RECMUTEX_SECTION(nobugflag, mtx) \ + for (lumiera_sectionlock NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) \ + lumiera_lock_section_ = { \ + (void*)1, lumiera_mutex_unlock_cb NOBUG_ALPHA_COMMA_NULL NOBUG_ALPHA_COMMA_NULL}; \ + lumiera_lock_section_.lock;) \ + for ( \ + ({ \ + lumiera_lock_section_.lock = &(mtx)->recmutex; \ + NOBUG_IF_ALPHA(lumiera_lock_section_.flag = &NOBUG_FLAG(nobugflag);) \ + RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire recmutex", &lumiera_lock_section_, \ + NOBUG_RESOURCE_WAITING, lumiera_lock_section_.rh); \ + if (pthread_mutex_lock (lumiera_lock_section_.lock)) LUMIERA_DIE (LOCK_ACQUIRE); \ + RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_RECURSIVE, lumiera_lock_section_.rh); \ + }); \ + lumiera_lock_section_.lock; \ + ({ \ + LUMIERA_MUTEX_SECTION_UNLOCK; \ })) -/** - * Mutual exclusion chainbuilder section. - * Usage: LUMIERA_MUTEX_SECTION(a){LUMIERA_RECMUTEX_SECTION_CHAIN(b){run();}} - * calls lock(a); lock(b); unlock(a); run(); unlock(b); - * This macro should only be used inside LUMIERA_MUTEX_SECTION and should be - * called on the correct mutexes, period. - */ -#define LUMIERA_RECMUTEX_SECTION_CHAIN(nobugflag, mtx) \ - for (lumiera_mutexacquirer *lumiera_mutex_section_old_ = &lumiera_mutex_section_, \ - NOBUG_CLEANUP(lumiera_mutexacquirer_ensureunlocked) lumiera_mutex_section_ = {(LumieraMutex)1 \ - NOBUG_ALPHA_COMMA_NULL}; \ - lumiera_mutex_section_.mutex;) \ - for ( \ - ({ \ - lumiera_mutex_section_.mutex = (mtx); \ - NOBUG_RESOURCE_HANDLE_INIT (lumiera_mutex_section_.rh); \ - RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire recmutex", &lumiera_mutex_section_, \ - NOBUG_RESOURCE_RECURSIVE, lumiera_mutex_section_.rh); \ - if (pthread_mutex_lock (&(mtx)->mutex)) LUMIERA_DIE (MUTEX_LOCK); \ - if (lumiera_mutex_section_old_->mutex) \ - { \ - pthread_mutex_unlock (&lumiera_mutex_section_old_->mutex->mutex); \ - lumiera_mutex_section_old_->mutex = NULL; \ - RESOURCE_LEAVE(nobugflag, lumiera_mutex_section_old_->rh); \ - } \ - }); \ - lumiera_mutex_section_.mutex; \ - ({ \ - if (lumiera_mutex_section_.mutex) \ - { \ - pthread_mutex_unlock (&lumiera_mutex_section_.mutex->mutex); \ - lumiera_mutex_section_.mutex = NULL; \ - RESOURCE_LEAVE(nobugflag, lumiera_mutex_section_.rh); \ - } \ +#define LUMIERA_RECMUTEX_SECTION_CHAIN(nobugflag, mtx) \ + for (lumiera_sectionlock *lumiera_lock_section_old_ = &lumiera_lock_section_, \ + NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) lumiera_lock_section_ = { \ + (void*)1, lumiera_mutex_unlock_cb NOBUG_ALPHA_COMMA_NULL NOBUG_ALPHA_COMMA_NULL}; \ + lumiera_lock_section_.lock;) \ + for ( \ + ({ \ + lumiera_lock_section_.lock = &(mtx)->recmutex; \ + NOBUG_IF_ALPHA(lumiera_lock_section_.flag = &NOBUG_FLAG(nobugflag);) \ + RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire recmutex", &lumiera_lock_section_, \ + NOBUG_RESOURCE_WAITING, lumiera_lock_section_.rh); \ + if (pthread_mutex_lock (lumiera_lock_section_.lock)) LUMIERA_DIE (LOCK_ACQUIRE); \ + RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_recursive, lumiera_lock_section_.rh); \ + LUMIERA_SECTION_UNLOCK_(lumiera_lock_section_old_) \ + }); \ + lumiera_lock_section_.lock; \ + ({ \ + LUMIERA_MUTEX_SECTION_UNLOCK; \ })) +#define LUMIERA_RECMUTEX_SECTION_UNLOCK \ + LUMIERA_SECTION_UNLOCK_(&lumiera_lock_section_) + + + /** * Mutex. * @@ -173,6 +151,14 @@ struct lumiera_mutex_struct typedef struct lumiera_mutex_struct lumiera_mutex; typedef lumiera_mutex* LumieraMutex; +struct lumiera_recmutex_struct +{ + pthread_mutex_t recmutex; + RESOURCE_HANDLE (rh); +}; +typedef struct lumiera_recmutex_struct lumiera_recmutex; +typedef lumiera_recmutex* LumieraRecMutex; + /** * Initialize a mutex variable @@ -183,16 +169,6 @@ typedef lumiera_mutex* LumieraMutex; LumieraMutex lumiera_mutex_init (LumieraMutex self, const char* purpose, struct nobug_flag* flag); -/** - * Initialize a mutex variable - * Initializes a 'recursive' mutex which might be locked by the same thread multiple times. - * @param self is a pointer to the mutex to be initialized - * @return self as given - */ -LumieraMutex -lumiera_recmutex_init (LumieraMutex self, const char* purpose, struct nobug_flag* flag); - - /** * Destroy a mutex variable * @param self is a pointer to the mutex to be destroyed @@ -202,23 +178,31 @@ LumieraMutex lumiera_mutex_destroy (LumieraMutex self, struct nobug_flag* flag); -/** - * mutexacquirer used to manage the state of a mutex. - */ -struct lumiera_mutexacquirer_struct -{ - LumieraMutex mutex; - RESOURCE_HANDLE (rh); -}; -typedef struct lumiera_mutexacquirer_struct lumiera_mutexacquirer; -typedef struct lumiera_mutexacquirer_struct* LumieraMutexacquirer; -/* helper function for nobug */ -static inline void -lumiera_mutexacquirer_ensureunlocked (LumieraMutexacquirer self) -{ - ENSURE (!self->mutex, "forgot to unlock mutex"); -} +/** + * Initialize a recursive mutex variable + * Initializes a 'recursive' mutex which might be locked by the same thread multiple times. + * @param self is a pointer to the mutex to be initialized + * @return self as given + */ +LumieraRecMutex +lumiera_recmutex_init (LumieraRecMutex self, const char* purpose, struct nobug_flag* flag); + +/** + * Destroy a recursive mutex variable + * @param self is a pointer to the mutex to be destroyed + * @return self as given + */ +LumieraRecMutex +lumiera_recmutex_destroy (LumieraRecMutex self, struct nobug_flag* flag); + +/** + * Callback for unlocking mutexes. + * @internal + */ +int +lumiera_mutex_unlock_cb (void* mutex); + #endif /* diff --git a/src/lib/recmutex.c b/src/lib/recmutex.c new file mode 100644 index 000000000..b8a381e6f --- /dev/null +++ b/src/lib/recmutex.c @@ -0,0 +1,74 @@ +/* + recmutex.c - recursive mutex + + Copyright (C) Lumiera.org + 2008, 2009, Christian Thaeter + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "lib/mutex.h" + +/** + * @file + * Recursive Mutexes. + */ + + +static pthread_once_t recmutexattr_once = PTHREAD_ONCE_INIT; +static pthread_mutexattr_t recmutexattr; + +static void recmutexattr_init() +{ + pthread_mutexattr_init (&recmutexattr); + pthread_mutexattr_settype (&recmutexattr, PTHREAD_MUTEX_RECURSIVE); +} + + +LumieraRecMutex +lumiera_recmutex_init (LumieraRecMutex self, const char* purpose, struct nobug_flag* flag) +{ + if (self) + { + if (recmutexattr_once == PTHREAD_ONCE_INIT) + pthread_once (&recmutexattr_once, recmutexattr_init); + + pthread_mutex_init (&self->recmutex, &recmutexattr); + NOBUG_RESOURCE_HANDLE_INIT (self->rh); + NOBUG_RESOURCE_ANNOUNCE_RAW (flag, "recmutex", purpose, self, self->rh); + } + return self; +} + +LumieraRecMutex +lumiera_recmutex_destroy (LumieraRecMutex self, struct nobug_flag* flag) +{ + if (self) + { + NOBUG_RESOURCE_FORGET_RAW (flag, self->rh); + if (pthread_mutex_destroy (&self->recmutex)) + LUMIERA_DIE (LOCK_DESTROY); + } + return self; +} + + +/* +// Local Variables: +// mode: C +// c-file-style: "gnu" +// indent-tabs-mode: nil +// End: +*/ diff --git a/src/lib/sectionlock.h b/src/lib/sectionlock.h new file mode 100644 index 000000000..0bc4d80fb --- /dev/null +++ b/src/lib/sectionlock.h @@ -0,0 +1,83 @@ +/* + sectionlock.h - mutex state handle + + Copyright (C) Lumiera.org + 2008, Christian Thaeter + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef LUMIERA_SECTIONLOCK_H +#define LUMIERA_SECTIONLOCK_H + +#include "lib/error.h" + +#include +#include + +LUMIERA_ERROR_DECLARE (LOCK_ACQUIRE); +LUMIERA_ERROR_DECLARE (LOCK_RELEASE); +LUMIERA_ERROR_DECLARE (LOCK_DESTROY); + + +typedef int (*lumiera_sectionlock_unlock_fn)(void*); + +/** + * sectionlock used to manage the state of mutexes. + */ +struct lumiera_sectionlock_struct +{ + void* lock; + lumiera_sectionlock_unlock_fn unlock; + NOBUG_IF_ALPHA(struct nobug_flag* flag); + RESOURCE_HANDLE (rh); +}; +typedef struct lumiera_sectionlock_struct lumiera_sectionlock; +typedef struct lumiera_sectionlock_struct* LumieraSectionlock; + +/* helper function for nobug */ +static inline void +lumiera_sectionlock_ensureunlocked (LumieraSectionlock self) +{ + ENSURE (!self->lock, "forgot to unlock"); +} + + + +/** + * Unlock the lock hold in a SECTION + * @internal + * @param sectionname name used for the sectionlock instance + * @param ... some extra code to execute + */ +#define LUMIERA_SECTION_UNLOCK_(section, ...) \ + do if ((section)->lock) \ + { \ + if ((section)->unlock((section)->lock)) \ + LUMIERA_DIE (LOCK_RELEASE); \ + (section)->lock = NULL; \ + __VA_ARGS__; \ + NOBUG_RESOURCE_LEAVE_RAW((section)->flag, (section)->rh); \ + } while (0) + + +#endif +/* +// Local Variables: +// mode: C +// c-file-style: "gnu" +// indent-tabs-mode: nil +// End: +*/ diff --git a/src/lib/sync.hpp b/src/lib/sync.hpp index 6515f35b9..e4fcb850a 100644 --- a/src/lib/sync.hpp +++ b/src/lib/sync.hpp @@ -102,21 +102,21 @@ namespace lib { //------------------Resource-Tracking------ void __may_block() { TODO ("Record we may block on mutex"); } void __enter() { TODO ("Record we successfully acquired the mutex"); } - void __leave() { TODO ("Record we are releasing the mutex"); } + void __left() { TODO ("Record we are released the mutex"); } }; struct Wrapped_LumieraRecMutex - : public lumiera_mutex + : public lumiera_recmutex { protected: Wrapped_LumieraRecMutex() { lumiera_recmutex_init (this, "Obj.Monitor RecMutex", &NOBUG_FLAG(sync)); } - ~Wrapped_LumieraRecMutex() { lumiera_mutex_destroy (this, &NOBUG_FLAG(sync)); } + ~Wrapped_LumieraRecMutex() { lumiera_recmutex_destroy (this, &NOBUG_FLAG(sync)); } //------------------Resource-Tracking------ void __may_block() { TODO ("Record we may block on mutex"); } void __enter() { TODO ("Record we successfully acquired the mutex"); } - void __leave() { TODO ("Record we are releasing the mutex"); } + void __left() { TODO ("Record we are released the mutex"); } }; @@ -130,7 +130,7 @@ namespace lib { //------------------Resource-Tracking------ void __may_block() { TODO ("Record we may block on mutex"); } void __enter() { TODO ("Record we successfully acquired the mutex"); } - void __leave() { TODO ("Record we are releasing the mutex"); } + void __left() { TODO ("Record we are released the mutex"); } }; @@ -144,7 +144,7 @@ namespace lib { //------------------Resource-Tracking------ void __may_block() { TODO ("Record we may block on mutex"); } void __enter() { TODO ("Record we successfully acquired the mutex"); } - void __leave() { TODO ("Record we are releasing the mutex"); } + void __left() { TODO ("Record we are released the mutex"); } }; @@ -156,10 +156,10 @@ namespace lib { : protected MTX { protected: - using MTX::mutex; + //using MTX::mutex; using MTX::__may_block; using MTX::__enter; - using MTX::__leave; + using MTX::__left; ~Mutex () { } Mutex () { } @@ -171,19 +171,22 @@ namespace lib { acquire() { __may_block(); - - if (pthread_mutex_lock (&mutex)) - throw lumiera::error::State("Mutex acquire failed."); ///////TODO capture the error-code - + + FIXME ("For to make C typesafe we have now mutex and recmutex member gnah :P -- cehteh"); + // well .. specialization on the mutex type shall solve it ... + //if (pthread_mutex_lock (&mutex)) + // throw lumiera::error::State("Mutex acquire failed."); ///////TODO capture the error-code + __enter(); } void release() - { - __leave(); - - pthread_mutex_unlock (&mutex); + { + FIXME ("For to make C typesafe we have now mutex and recmutex member gnah :P -- cehteh"); + //pthread_mutex_unlock (&mutex); + + __left(); } }; @@ -436,3 +439,10 @@ namespace lib { } // namespace lumiera #endif +/* +// Local Variables: +// mode: C +// c-file-style: "gnu" +// indent-tabs-mode: nil +// End: +*/ diff --git a/tests/15locking.tests b/tests/15locking.tests index 061a2da56..81387ac8e 100644 --- a/tests/15locking.tests +++ b/tests/15locking.tests @@ -11,6 +11,10 @@ TEST "mutex not unlocked asserts" mutexforgotunlock < Date: Mon, 26 Jan 2009 04:21:58 +0100 Subject: [PATCH 02/15] fix: forgotten backcasts in mutex.h --- src/lib/mutex.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/lib/mutex.h b/src/lib/mutex.h index 378fe00f1..901a885ba 100644 --- a/src/lib/mutex.h +++ b/src/lib/mutex.h @@ -48,7 +48,8 @@ NOBUG_IF_ALPHA(lumiera_lock_section_.flag = &NOBUG_FLAG(nobugflag);) \ RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire mutex", &lumiera_lock_section_, \ NOBUG_RESOURCE_WAITING, lumiera_lock_section_.rh); \ - if (pthread_mutex_lock (lumiera_lock_section_.lock)) LUMIERA_DIE (LOCK_ACQUIRE); \ + if (pthread_mutex_lock ((pthread_mutex_t*)lumiera_lock_section_.lock)) \ + LUMIERA_DIE (LOCK_ACQUIRE); \ RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_EXCLUSIVE, lumiera_lock_section_.rh); \ }); \ lumiera_lock_section_.lock; \ @@ -76,7 +77,8 @@ NOBUG_IF_ALPHA(lumiera_lock_section_.flag = &NOBUG_FLAG(nobugflag);) \ RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire mutex", &lumiera_lock_section_, \ NOBUG_RESOURCE_WAITING, lumiera_lock_section_.rh); \ - if (pthread_mutex_lock (lumiera_lock_section_.lock)) LUMIERA_DIE (LOCK_ACQUIRE); \ + if (pthread_mutex_lock ((pthread_mutex_t*)lumiera_lock_section_.lock)) \ + LUMIERA_DIE (LOCK_ACQUIRE); \ RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_EXCLUSIVE, lumiera_lock_section_.rh); \ LUMIERA_SECTION_UNLOCK_(lumiera_lock_section_old_); \ }); \ @@ -104,7 +106,8 @@ NOBUG_IF_ALPHA(lumiera_lock_section_.flag = &NOBUG_FLAG(nobugflag);) \ RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire recmutex", &lumiera_lock_section_, \ NOBUG_RESOURCE_WAITING, lumiera_lock_section_.rh); \ - if (pthread_mutex_lock (lumiera_lock_section_.lock)) LUMIERA_DIE (LOCK_ACQUIRE); \ + if (pthread_mutex_lock ((pthread_mutex_t*)lumiera_lock_section_.lock)) \ + LUMIERA_DIE (LOCK_ACQUIRE); \ RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_RECURSIVE, lumiera_lock_section_.rh); \ }); \ lumiera_lock_section_.lock; \ @@ -124,7 +127,8 @@ NOBUG_IF_ALPHA(lumiera_lock_section_.flag = &NOBUG_FLAG(nobugflag);) \ RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire recmutex", &lumiera_lock_section_, \ NOBUG_RESOURCE_WAITING, lumiera_lock_section_.rh); \ - if (pthread_mutex_lock (lumiera_lock_section_.lock)) LUMIERA_DIE (LOCK_ACQUIRE); \ + if (pthread_mutex_lock ((pthread_mutex_t*)lumiera_lock_section_.lock)) \ + LUMIERA_DIE (LOCK_ACQUIRE); \ RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_recursive, lumiera_lock_section_.rh); \ LUMIERA_SECTION_UNLOCK_(lumiera_lock_section_old_) \ }); \ From ca0250c0184c62d26f9fd9290897e1f70c97514d Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Mon, 26 Jan 2009 07:28:07 +0100 Subject: [PATCH 03/15] error code changed to LOCK_DESTROY --- src/lib/reccondition.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/reccondition.c b/src/lib/reccondition.c index 66000e7e1..b70f8d179 100644 --- a/src/lib/reccondition.c +++ b/src/lib/reccondition.c @@ -64,7 +64,7 @@ lumiera_reccondition_destroy (LumieraReccondition self, struct nobug_flag* flag) NOBUG_RESOURCE_FORGET_RAW (flag, self->rh); if (pthread_mutex_destroy (&self->mutex)) - LUMIERA_DIE (MUTEX_DESTROY); + LUMIERA_DIE (LOCK_DESTROY); if (pthread_cond_destroy (&self->cond)) LUMIERA_DIE (CONDITION_DESTROY); From 5c2ac96f354c2aa6c0f5d75d3b5c3795f6a239ca Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Mon, 26 Jan 2009 07:30:20 +0100 Subject: [PATCH 04/15] rwlock makeover, locksections etc... The CHAINED variant is not tested, what could go wrong anyways :) --- src/lib/rwlock.c | 6 ++ src/lib/rwlock.h | 149 +++++++++++++++++++++-------------- tests/15locking.tests | 9 +++ tests/library/test-locking.c | 39 +++++++++ 4 files changed, 145 insertions(+), 58 deletions(-) diff --git a/src/lib/rwlock.c b/src/lib/rwlock.c index c5287d535..3242591c5 100644 --- a/src/lib/rwlock.c +++ b/src/lib/rwlock.c @@ -60,6 +60,12 @@ lumiera_rwlock_destroy (LumieraRWLock self, struct nobug_flag* flag) return self; } + +int lumiera_rwlock_unlock_cb (void* rwlock) +{ + return pthread_rwlock_unlock ((pthread_rwlock_t*) rwlock); +} + /* // Local Variables: // mode: C diff --git a/src/lib/rwlock.h b/src/lib/rwlock.h index 23376979b..a6b32d264 100644 --- a/src/lib/rwlock.h +++ b/src/lib/rwlock.h @@ -45,53 +45,104 @@ LUMIERA_ERROR_DECLARE(RWLOCK_WRLOCK); /** * Read locked section. */ -#define LUMIERA_RDLOCK_SECTION(nobugflag, rwlck) \ - for (lumiera_rwlockacquirer NOBUG_CLEANUP(lumiera_rwlockacquirer_ensureunlocked) lumiera_rwlock_section_ = {(LumieraRWLock)1}; \ - lumiera_rwlock_section_.rwlock;) \ - for ( \ - ({ \ - lumiera_rwlock_section_.rwlock = (rwlck); \ - NOBUG_RESOURCE_HANDLE_INIT (lumiera_rwlock_section_.rh); \ - RESOURCE_ENTER (nobugflag, (rwlck)->rh, "acquire rwlock for reading", &lumiera_rwlock_section_, \ - NOBUG_RESOURCE_EXCLUSIVE, lumiera_rwlock_section_.rh); \ - if (pthread_rwlock_rdlock (&(rwlck)->rwlock)) LUMIERA_DIE (RWLOCK_RDLOCK); \ - }); \ - lumiera_rwlock_section_.rwlock; \ - ({ \ - if (lumiera_rwlock_section_.rwlock) \ - { \ - pthread_rwlock_unlock (&lumiera_rwlock_section_.rwlock->rwlock); \ - lumiera_rwlock_section_.rwlock = NULL; \ - RESOURCE_LEAVE(nobugflag, lumiera_rwlock_section_.rh); \ - } \ +#define LUMIERA_RDLOCK_SECTION(nobugflag, rwlck) \ + for (lumiera_sectionlock NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) \ + lumiera_lock_section_ = { \ + (void*)1, lumiera_rwlock_unlock_cb NOBUG_ALPHA_COMMA_NULL NOBUG_ALPHA_COMMA_NULL}; \ + lumiera_lock_section_.lock;) \ + for ( \ + ({ \ + lumiera_lock_section_.lock = &(rwlck)->rwlock; \ + NOBUG_IF_ALPHA(lumiera_lock_section_.flag = &NOBUG_FLAG(nobugflag);) \ + RESOURCE_ENTER (nobugflag, (rwlck)->rh, "acquire readlock", \ + &lumiera_lock_section_, NOBUG_RESOURCE_WAITING, \ + lumiera_lock_section_.rh); \ + if (pthread_rwlock_rdlock ((pthread_rwlock_t*)lumiera_lock_section_.lock)) \ + LUMIERA_DIE (LOCK_ACQUIRE); \ + TODO ("implement NOBUG_RESOURCE_SHARED"); \ + /*RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_SHARED, lumiera_lock_section_.rh); */ \ + }); \ + lumiera_lock_section_.lock; \ + ({ \ + LUMIERA_RWLOCK_SECTION_UNLOCK; \ })) +#define LUMIERA_RDLOCK_SECTION_CHAIN(nobugflag, rwlck) \ + for (lumiera_sectionlock *lumiera_lock_section_old_ = &lumiera_lock_section_, \ + NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) lumiera_lock_section_ = { \ + (void*)1, lumiera_rwlock_unlock_cb NOBUG_ALPHA_COMMA_NULL NOBUG_ALPHA_COMMA_NULL}; \ + lumiera_lock_section_.lock;) \ + for ( \ + ({ \ + lumiera_lock_section_.lock = &(rwlck)->rwlock; \ + NOBUG_IF_ALPHA(lumiera_lock_section_.flag = &NOBUG_FLAG(nobugflag);) \ + RESOURCE_ENTER (nobugflag, (rwlck)->rh, "acquire readlock", &lumiera_lock_section_, \ + NOBUG_RESOURCE_WAITING, lumiera_lock_section_.rh); \ + if (pthread_rwlock_rdlock ((pthread_rwlock_t*)lumiera_lock_section_.lock)) \ + LUMIERA_DIE (LOCK_ACQUIRE); \ + /*RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_SHARED, lumiera_lock_section_.rh); */ \ + LUMIERA_SECTION_UNLOCK_(lumiera_lock_section_old_); \ + }); \ + lumiera_lock_section_.lock; \ + ({ \ + LUMIERA_MUTEX_SECTION_UNLOCK; \ + })) + + + + /** * Write locked section. */ -#define LUMIERA_WRLOCK_SECTION(nobugflag, rwlck) \ - for (lumiera_rwlockacquirer NOBUG_CLEANUP(lumiera_rwlockacquirer_ensureunlocked) lumiera_rwlock_section_ = {(LumieraRWLock)1}; \ - lumiera_rwlock_section_.rwlock;) \ - for ( \ - ({ \ - lumiera_rwlock_section_.rwlock = (rwlck); \ - NOBUG_RESOURCE_HANDLE_INIT (lumiera_rwlock_section_.rh); \ - RESOURCE_ENTER (nobugflag, (rwlck)->rh, "acquire rwlock for reading", &lumiera_rwlock_section_, \ - NOBUG_RESOURCE_EXCLUSIVE, lumiera_rwlock_section_.rh); \ - if (pthread_rwlock_wrlock (&(rwlck)->rwlock)) LUMIERA_DIE (RWLOCK_WRLOCK); \ - }); \ - lumiera_rwlock_section_.rwlock; \ - ({ \ - if (lumiera_rwlock_section_.rwlock) \ - { \ - pthread_rwlock_unlock (&lumiera_rwlock_section_.rwlock->rwlock); \ - lumiera_rwlock_section_.rwlock = NULL; \ - RESOURCE_LEAVE(nobugflag, lumiera_rwlock_section_.rh); \ - } \ +#define LUMIERA_WRLOCK_SECTION(nobugflag, rwlck) \ + for (lumiera_sectionlock NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) \ + lumiera_lock_section_ = { \ + (void*)1, lumiera_rwlock_unlock_cb NOBUG_ALPHA_COMMA_NULL NOBUG_ALPHA_COMMA_NULL}; \ + lumiera_lock_section_.lock;) \ + for ( \ + ({ \ + lumiera_lock_section_.lock = &(rwlck)->rwlock; \ + NOBUG_IF_ALPHA(lumiera_lock_section_.flag = &NOBUG_FLAG(nobugflag);) \ + RESOURCE_ENTER (nobugflag, (rwlck)->rh, "acquire writelock", \ + &lumiera_lock_section_, NOBUG_RESOURCE_WAITING, \ + lumiera_lock_section_.rh); \ + if (pthread_rwlock_wrlock ((pthread_rwlock_t*)lumiera_lock_section_.lock)) \ + LUMIERA_DIE (LOCK_ACQUIRE); \ + RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_EXCLUSIVE, lumiera_lock_section_.rh); \ + }); \ + lumiera_lock_section_.lock; \ + ({ \ + LUMIERA_RWLOCK_SECTION_UNLOCK; \ })) +#define LUMIERA_WRLOCK_SECTION_CHAIN(nobugflag, rwlck) \ + for (lumiera_sectionlock *lumiera_lock_section_old_ = &lumiera_lock_section_, \ + NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) lumiera_lock_section_ = { \ + (void*)1, lumiera_rwlock_unlock_cb NOBUG_ALPHA_COMMA_NULL NOBUG_ALPHA_COMMA_NULL}; \ + lumiera_lock_section_.lock;) \ + for ( \ + ({ \ + lumiera_lock_section_.lock = &(rwlck)->rwlock; \ + NOBUG_IF_ALPHA(lumiera_lock_section_.flag = &NOBUG_FLAG(nobugflag);) \ + RESOURCE_ENTER (nobugflag, (rwlck)->rh, "acquire writelock", &lumiera_lock_section_, \ + NOBUG_RESOURCE_WAITING, lumiera_lock_section_.rh); \ + if (pthread_rwlock_wrlock ((pthread_rwlock_t*)lumiera_lock_section_.lock)) \ + LUMIERA_DIE (LOCK_ACQUIRE); \ + RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_EXCLUSIVE, lumiera_lock_section_.rh); \ + LUMIERA_SECTION_UNLOCK_(lumiera_lock_section_old_); \ + }); \ + lumiera_lock_section_.lock; \ + ({ \ + LUMIERA_MUTEX_SECTION_UNLOCK; \ + })) + + +#define LUMIERA_RWLOCK_SECTION_UNLOCK \ + LUMIERA_SECTION_UNLOCK_(&lumiera_lock_section_) + + /** * RWLock. * @@ -121,26 +172,8 @@ LumieraRWLock lumiera_rwlock_destroy (LumieraRWLock self, struct nobug_flag* flag); - - - -/** - * rwlockacquirer used to manage the state of a rwlock variable. - */ -struct lumiera_rwlockacquirer_struct -{ - LumieraRWLock rwlock; - RESOURCE_HANDLE (rh); -}; -typedef struct lumiera_rwlockacquirer_struct lumiera_rwlockacquirer; -typedef struct lumiera_rwlockacquirer_struct* LumieraRWLockacquirer; - -/* helper function for nobug */ -static inline void -lumiera_rwlockacquirer_ensureunlocked (LumieraRWLockacquirer self) -{ - ENSURE (!self->rwlock, "forgot to unlock rwlock"); -} +int +lumiera_rwlock_unlock_cb (void* rwlock); #endif diff --git a/tests/15locking.tests b/tests/15locking.tests index 81387ac8e..0fc57c233 100644 --- a/tests/15locking.tests +++ b/tests/15locking.tests @@ -45,6 +45,15 @@ return: 134 END +PLANNED "rwlock readlock in writelock asserts" rwlockdeadlockwr < Date: Mon, 26 Jan 2009 08:39:37 +0100 Subject: [PATCH 05/15] add check to chained locking validating that the parent lock is held --- src/lib/mutex.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib/mutex.h b/src/lib/mutex.h index 901a885ba..a6943d5a5 100644 --- a/src/lib/mutex.h +++ b/src/lib/mutex.h @@ -73,6 +73,7 @@ lumiera_lock_section_.lock;) \ for ( \ ({ \ + REQUIRE (lumiera_lock_section_old_->lock, "section prematurely unlocked"); \ lumiera_lock_section_.lock = &(mtx)->mutex; \ NOBUG_IF_ALPHA(lumiera_lock_section_.flag = &NOBUG_FLAG(nobugflag);) \ RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire mutex", &lumiera_lock_section_, \ @@ -123,6 +124,7 @@ lumiera_lock_section_.lock;) \ for ( \ ({ \ + REQUIRE (lumiera_lock_section_old_->lock, "section prematurely unlocked"); \ lumiera_lock_section_.lock = &(mtx)->recmutex; \ NOBUG_IF_ALPHA(lumiera_lock_section_.flag = &NOBUG_FLAG(nobugflag);) \ RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire recmutex", &lumiera_lock_section_, \ From 5b82f3355b8b98351992b50f84697c64af8e9501 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Mon, 26 Jan 2009 09:21:03 +0100 Subject: [PATCH 06/15] store a lumiera_mutex in a sectionlock, looks cleaner --- src/lib/mutex.c | 2 +- src/lib/mutex.h | 18 +++++++++--------- src/lib/sectionlock.h | 3 +-- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/lib/mutex.c b/src/lib/mutex.c index d6961982d..c7d6df040 100644 --- a/src/lib/mutex.c +++ b/src/lib/mutex.c @@ -58,7 +58,7 @@ lumiera_mutex_destroy (LumieraMutex self, struct nobug_flag* flag) int lumiera_mutex_unlock_cb (void* mutex) { - return pthread_mutex_unlock ((pthread_mutex_t*) mutex); + return pthread_mutex_unlock (&((LumieraMutex)mutex)->mutex); } /* diff --git a/src/lib/mutex.h b/src/lib/mutex.h index a6943d5a5..5708e19be 100644 --- a/src/lib/mutex.h +++ b/src/lib/mutex.h @@ -44,11 +44,11 @@ lumiera_lock_section_.lock;) \ for ( \ ({ \ - lumiera_lock_section_.lock = &(mtx)->mutex; \ + lumiera_lock_section_.lock = (mtx); \ NOBUG_IF_ALPHA(lumiera_lock_section_.flag = &NOBUG_FLAG(nobugflag);) \ RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire mutex", &lumiera_lock_section_, \ NOBUG_RESOURCE_WAITING, lumiera_lock_section_.rh); \ - if (pthread_mutex_lock ((pthread_mutex_t*)lumiera_lock_section_.lock)) \ + if (pthread_mutex_lock (&(mtx)->mutex)) \ LUMIERA_DIE (LOCK_ACQUIRE); \ RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_EXCLUSIVE, lumiera_lock_section_.rh); \ }); \ @@ -73,12 +73,12 @@ lumiera_lock_section_.lock;) \ for ( \ ({ \ - REQUIRE (lumiera_lock_section_old_->lock, "section prematurely unlocked"); \ - lumiera_lock_section_.lock = &(mtx)->mutex; \ + REQUIRE (lumiera_lock_section_old_->lock, "section prematurely unlocked"); \ + lumiera_lock_section_.lock = mtx; \ NOBUG_IF_ALPHA(lumiera_lock_section_.flag = &NOBUG_FLAG(nobugflag);) \ RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire mutex", &lumiera_lock_section_, \ NOBUG_RESOURCE_WAITING, lumiera_lock_section_.rh); \ - if (pthread_mutex_lock ((pthread_mutex_t*)lumiera_lock_section_.lock)) \ + if (pthread_mutex_lock (&(mtx)->mutex)) \ LUMIERA_DIE (LOCK_ACQUIRE); \ RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_EXCLUSIVE, lumiera_lock_section_.rh); \ LUMIERA_SECTION_UNLOCK_(lumiera_lock_section_old_); \ @@ -103,11 +103,11 @@ lumiera_lock_section_.lock;) \ for ( \ ({ \ - lumiera_lock_section_.lock = &(mtx)->recmutex; \ + lumiera_lock_section_.lock = (mtx); \ NOBUG_IF_ALPHA(lumiera_lock_section_.flag = &NOBUG_FLAG(nobugflag);) \ RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire recmutex", &lumiera_lock_section_, \ NOBUG_RESOURCE_WAITING, lumiera_lock_section_.rh); \ - if (pthread_mutex_lock ((pthread_mutex_t*)lumiera_lock_section_.lock)) \ + if (pthread_mutex_lock (&(mtx)->recmutex)) \ LUMIERA_DIE (LOCK_ACQUIRE); \ RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_RECURSIVE, lumiera_lock_section_.rh); \ }); \ @@ -125,11 +125,11 @@ for ( \ ({ \ REQUIRE (lumiera_lock_section_old_->lock, "section prematurely unlocked"); \ - lumiera_lock_section_.lock = &(mtx)->recmutex; \ + lumiera_lock_section_.lock = (mtx); \ NOBUG_IF_ALPHA(lumiera_lock_section_.flag = &NOBUG_FLAG(nobugflag);) \ RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire recmutex", &lumiera_lock_section_, \ NOBUG_RESOURCE_WAITING, lumiera_lock_section_.rh); \ - if (pthread_mutex_lock ((pthread_mutex_t*)lumiera_lock_section_.lock)) \ + if (pthread_mutex_lock (&(mtx)->recmutex)) \ LUMIERA_DIE (LOCK_ACQUIRE); \ RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_recursive, lumiera_lock_section_.rh); \ LUMIERA_SECTION_UNLOCK_(lumiera_lock_section_old_) \ diff --git a/src/lib/sectionlock.h b/src/lib/sectionlock.h index 0bc4d80fb..c50ecfc8d 100644 --- a/src/lib/sectionlock.h +++ b/src/lib/sectionlock.h @@ -62,13 +62,12 @@ lumiera_sectionlock_ensureunlocked (LumieraSectionlock self) * @param sectionname name used for the sectionlock instance * @param ... some extra code to execute */ -#define LUMIERA_SECTION_UNLOCK_(section, ...) \ +#define LUMIERA_SECTION_UNLOCK_(section) \ do if ((section)->lock) \ { \ if ((section)->unlock((section)->lock)) \ LUMIERA_DIE (LOCK_RELEASE); \ (section)->lock = NULL; \ - __VA_ARGS__; \ NOBUG_RESOURCE_LEAVE_RAW((section)->flag, (section)->rh); \ } while (0) From 93abe657c8cee09e3c0f17d049ab53e16310d949 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Mon, 26 Jan 2009 09:49:15 +0100 Subject: [PATCH 07/15] store lumiera_rwlock in sectionlock --- src/lib/rwlock.c | 2 +- src/lib/rwlock.h | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/lib/rwlock.c b/src/lib/rwlock.c index 3242591c5..60929a458 100644 --- a/src/lib/rwlock.c +++ b/src/lib/rwlock.c @@ -63,7 +63,7 @@ lumiera_rwlock_destroy (LumieraRWLock self, struct nobug_flag* flag) int lumiera_rwlock_unlock_cb (void* rwlock) { - return pthread_rwlock_unlock ((pthread_rwlock_t*) rwlock); + return pthread_rwlock_unlock (&((LumieraRWLock)rwlock)->rwlock); } /* diff --git a/src/lib/rwlock.h b/src/lib/rwlock.h index a6b32d264..aa0814b37 100644 --- a/src/lib/rwlock.h +++ b/src/lib/rwlock.h @@ -52,12 +52,12 @@ LUMIERA_ERROR_DECLARE(RWLOCK_WRLOCK); lumiera_lock_section_.lock;) \ for ( \ ({ \ - lumiera_lock_section_.lock = &(rwlck)->rwlock; \ + lumiera_lock_section_.lock = (rwlck); \ NOBUG_IF_ALPHA(lumiera_lock_section_.flag = &NOBUG_FLAG(nobugflag);) \ RESOURCE_ENTER (nobugflag, (rwlck)->rh, "acquire readlock", \ &lumiera_lock_section_, NOBUG_RESOURCE_WAITING, \ lumiera_lock_section_.rh); \ - if (pthread_rwlock_rdlock ((pthread_rwlock_t*)lumiera_lock_section_.lock)) \ + if (pthread_rwlock_rdlock (&(rwlck)->rwlock)) \ LUMIERA_DIE (LOCK_ACQUIRE); \ TODO ("implement NOBUG_RESOURCE_SHARED"); \ /*RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_SHARED, lumiera_lock_section_.rh); */ \ @@ -75,11 +75,12 @@ LUMIERA_ERROR_DECLARE(RWLOCK_WRLOCK); lumiera_lock_section_.lock;) \ for ( \ ({ \ - lumiera_lock_section_.lock = &(rwlck)->rwlock; \ + REQUIRE (lumiera_lock_section_old_->lock, "section prematurely unlocked"); \ + lumiera_lock_section_.lock = (rwlck); \ NOBUG_IF_ALPHA(lumiera_lock_section_.flag = &NOBUG_FLAG(nobugflag);) \ RESOURCE_ENTER (nobugflag, (rwlck)->rh, "acquire readlock", &lumiera_lock_section_, \ NOBUG_RESOURCE_WAITING, lumiera_lock_section_.rh); \ - if (pthread_rwlock_rdlock ((pthread_rwlock_t*)lumiera_lock_section_.lock)) \ + if (pthread_rwlock_rdlock (&(rwlck)->rwlock)) \ LUMIERA_DIE (LOCK_ACQUIRE); \ /*RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_SHARED, lumiera_lock_section_.rh); */ \ LUMIERA_SECTION_UNLOCK_(lumiera_lock_section_old_); \ @@ -102,12 +103,12 @@ LUMIERA_ERROR_DECLARE(RWLOCK_WRLOCK); lumiera_lock_section_.lock;) \ for ( \ ({ \ - lumiera_lock_section_.lock = &(rwlck)->rwlock; \ + lumiera_lock_section_.lock = (rwlck); \ NOBUG_IF_ALPHA(lumiera_lock_section_.flag = &NOBUG_FLAG(nobugflag);) \ RESOURCE_ENTER (nobugflag, (rwlck)->rh, "acquire writelock", \ &lumiera_lock_section_, NOBUG_RESOURCE_WAITING, \ lumiera_lock_section_.rh); \ - if (pthread_rwlock_wrlock ((pthread_rwlock_t*)lumiera_lock_section_.lock)) \ + if (pthread_rwlock_wrlock (&(rwlck)->rwlock)) \ LUMIERA_DIE (LOCK_ACQUIRE); \ RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_EXCLUSIVE, lumiera_lock_section_.rh); \ }); \ @@ -124,11 +125,12 @@ LUMIERA_ERROR_DECLARE(RWLOCK_WRLOCK); lumiera_lock_section_.lock;) \ for ( \ ({ \ - lumiera_lock_section_.lock = &(rwlck)->rwlock; \ + REQUIRE (lumiera_lock_section_old_->lock, "section prematurely unlocked"); \ + lumiera_lock_section_.lock = (rwlck); \ NOBUG_IF_ALPHA(lumiera_lock_section_.flag = &NOBUG_FLAG(nobugflag);) \ RESOURCE_ENTER (nobugflag, (rwlck)->rh, "acquire writelock", &lumiera_lock_section_, \ NOBUG_RESOURCE_WAITING, lumiera_lock_section_.rh); \ - if (pthread_rwlock_wrlock ((pthread_rwlock_t*)lumiera_lock_section_.lock)) \ + if (pthread_rwlock_wrlock (&(twlck)->rwlock)) \ LUMIERA_DIE (LOCK_ACQUIRE); \ RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_EXCLUSIVE, lumiera_lock_section_.rh); \ LUMIERA_SECTION_UNLOCK_(lumiera_lock_section_old_); \ From 30a117c1d838d564c44e0bc39b63f46adf5db8b2 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Tue, 27 Jan 2009 08:43:49 +0100 Subject: [PATCH 08/15] rename casing of RecMutex to Recmutex to be consistent --- src/lib/mutex.h | 10 +++++----- src/lib/recmutex.c | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/lib/mutex.h b/src/lib/mutex.h index 5708e19be..a3cd46fd9 100644 --- a/src/lib/mutex.h +++ b/src/lib/mutex.h @@ -163,7 +163,7 @@ struct lumiera_recmutex_struct RESOURCE_HANDLE (rh); }; typedef struct lumiera_recmutex_struct lumiera_recmutex; -typedef lumiera_recmutex* LumieraRecMutex; +typedef lumiera_recmutex* LumieraRecmutex; /** @@ -191,16 +191,16 @@ lumiera_mutex_destroy (LumieraMutex self, struct nobug_flag* flag); * @param self is a pointer to the mutex to be initialized * @return self as given */ -LumieraRecMutex -lumiera_recmutex_init (LumieraRecMutex self, const char* purpose, struct nobug_flag* flag); +LumieraRecmutex +lumiera_recmutex_init (LumieraRecmutex self, const char* purpose, struct nobug_flag* flag); /** * Destroy a recursive mutex variable * @param self is a pointer to the mutex to be destroyed * @return self as given */ -LumieraRecMutex -lumiera_recmutex_destroy (LumieraRecMutex self, struct nobug_flag* flag); +LumieraRecmutex +lumiera_recmutex_destroy (LumieraRecmutex self, struct nobug_flag* flag); /** * Callback for unlocking mutexes. diff --git a/src/lib/recmutex.c b/src/lib/recmutex.c index b8a381e6f..57b9b7d65 100644 --- a/src/lib/recmutex.c +++ b/src/lib/recmutex.c @@ -37,8 +37,8 @@ static void recmutexattr_init() } -LumieraRecMutex -lumiera_recmutex_init (LumieraRecMutex self, const char* purpose, struct nobug_flag* flag) +LumieraRecmutex +lumiera_recmutex_init (LumieraRecmutex self, const char* purpose, struct nobug_flag* flag) { if (self) { @@ -52,8 +52,8 @@ lumiera_recmutex_init (LumieraRecMutex self, const char* purpose, struct nobug_f return self; } -LumieraRecMutex -lumiera_recmutex_destroy (LumieraRecMutex self, struct nobug_flag* flag) +LumieraRecmutex +lumiera_recmutex_destroy (LumieraRecmutex self, struct nobug_flag* flag) { if (self) { From ec62ca073b39affedbfd64de85aa526f158166d3 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Tue, 27 Jan 2009 09:41:22 +0100 Subject: [PATCH 09/15] typo fix in mutex.h --- src/lib/mutex.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/mutex.h b/src/lib/mutex.h index a3cd46fd9..1199dbec5 100644 --- a/src/lib/mutex.h +++ b/src/lib/mutex.h @@ -131,7 +131,7 @@ NOBUG_RESOURCE_WAITING, lumiera_lock_section_.rh); \ if (pthread_mutex_lock (&(mtx)->recmutex)) \ LUMIERA_DIE (LOCK_ACQUIRE); \ - RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_recursive, lumiera_lock_section_.rh); \ + RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_RECURSIVE, lumiera_lock_section_.rh); \ LUMIERA_SECTION_UNLOCK_(lumiera_lock_section_old_) \ }); \ lumiera_lock_section_.lock; \ From 4f29f302b2d8ac43ba4c03f5c5a2f35d28ac66be Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Tue, 27 Jan 2009 10:07:30 +0100 Subject: [PATCH 10/15] split mutex.h again into mutex.h and recmutex.h --- src/lib/Makefile.am | 3 +- src/lib/mutex.c | 2 +- src/lib/mutex.h | 80 +-------------------- src/lib/recmutex.c | 2 +- src/lib/recmutex.h | 132 +++++++++++++++++++++++++++++++++++ src/lib/sync.hpp | 1 + tests/library/test-locking.c | 2 + 7 files changed, 140 insertions(+), 82 deletions(-) create mode 100644 src/lib/recmutex.h diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 0163d0c4c..8991e2e39 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -1,5 +1,5 @@ # Copyright (C) Lumiera.org -# 2007, Christian Thaeter +# 2007, 2008, 2009 Christian Thaeter # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as @@ -52,6 +52,7 @@ noinst_HEADERS += \ $(liblumiera_la_srcdir)/error.h \ $(liblumiera_la_srcdir)/error.hpp \ $(liblumiera_la_srcdir)/mutex.h \ + $(liblumiera_la_srcdir)/recmutex.h \ $(liblumiera_la_srcdir)/rwlock.h \ $(liblumiera_la_srcdir)/condition.h \ $(liblumiera_la_srcdir)/reccondition.h \ diff --git a/src/lib/mutex.c b/src/lib/mutex.c index c7d6df040..25b56679c 100644 --- a/src/lib/mutex.c +++ b/src/lib/mutex.c @@ -2,7 +2,7 @@ mutex.c - mutex Copyright (C) Lumiera.org - 2008, Christian Thaeter + 2008, 2009, Christian Thaeter This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as diff --git a/src/lib/mutex.h b/src/lib/mutex.h index 1199dbec5..a76707933 100644 --- a/src/lib/mutex.h +++ b/src/lib/mutex.h @@ -2,7 +2,7 @@ mutex.h - mutal exclusion locking Copyright (C) Lumiera.org - 2008, Christian Thaeter + 2008, 2009, Christian Thaeter This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -93,58 +93,6 @@ LUMIERA_SECTION_UNLOCK_(&lumiera_lock_section_) -/** - * Recursive Mutual exclusive section. - */ -#define LUMIERA_RECMUTEX_SECTION(nobugflag, mtx) \ - for (lumiera_sectionlock NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) \ - lumiera_lock_section_ = { \ - (void*)1, lumiera_mutex_unlock_cb NOBUG_ALPHA_COMMA_NULL NOBUG_ALPHA_COMMA_NULL}; \ - lumiera_lock_section_.lock;) \ - for ( \ - ({ \ - lumiera_lock_section_.lock = (mtx); \ - NOBUG_IF_ALPHA(lumiera_lock_section_.flag = &NOBUG_FLAG(nobugflag);) \ - RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire recmutex", &lumiera_lock_section_, \ - NOBUG_RESOURCE_WAITING, lumiera_lock_section_.rh); \ - if (pthread_mutex_lock (&(mtx)->recmutex)) \ - LUMIERA_DIE (LOCK_ACQUIRE); \ - RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_RECURSIVE, lumiera_lock_section_.rh); \ - }); \ - lumiera_lock_section_.lock; \ - ({ \ - LUMIERA_MUTEX_SECTION_UNLOCK; \ - })) - - -#define LUMIERA_RECMUTEX_SECTION_CHAIN(nobugflag, mtx) \ - for (lumiera_sectionlock *lumiera_lock_section_old_ = &lumiera_lock_section_, \ - NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) lumiera_lock_section_ = { \ - (void*)1, lumiera_mutex_unlock_cb NOBUG_ALPHA_COMMA_NULL NOBUG_ALPHA_COMMA_NULL}; \ - lumiera_lock_section_.lock;) \ - for ( \ - ({ \ - REQUIRE (lumiera_lock_section_old_->lock, "section prematurely unlocked"); \ - lumiera_lock_section_.lock = (mtx); \ - NOBUG_IF_ALPHA(lumiera_lock_section_.flag = &NOBUG_FLAG(nobugflag);) \ - RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire recmutex", &lumiera_lock_section_, \ - NOBUG_RESOURCE_WAITING, lumiera_lock_section_.rh); \ - if (pthread_mutex_lock (&(mtx)->recmutex)) \ - LUMIERA_DIE (LOCK_ACQUIRE); \ - RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_RECURSIVE, lumiera_lock_section_.rh); \ - LUMIERA_SECTION_UNLOCK_(lumiera_lock_section_old_) \ - }); \ - lumiera_lock_section_.lock; \ - ({ \ - LUMIERA_MUTEX_SECTION_UNLOCK; \ - })) - - -#define LUMIERA_RECMUTEX_SECTION_UNLOCK \ - LUMIERA_SECTION_UNLOCK_(&lumiera_lock_section_) - - - /** * Mutex. * @@ -157,14 +105,6 @@ struct lumiera_mutex_struct typedef struct lumiera_mutex_struct lumiera_mutex; typedef lumiera_mutex* LumieraMutex; -struct lumiera_recmutex_struct -{ - pthread_mutex_t recmutex; - RESOURCE_HANDLE (rh); -}; -typedef struct lumiera_recmutex_struct lumiera_recmutex; -typedef lumiera_recmutex* LumieraRecmutex; - /** * Initialize a mutex variable @@ -184,24 +124,6 @@ LumieraMutex lumiera_mutex_destroy (LumieraMutex self, struct nobug_flag* flag); - -/** - * Initialize a recursive mutex variable - * Initializes a 'recursive' mutex which might be locked by the same thread multiple times. - * @param self is a pointer to the mutex to be initialized - * @return self as given - */ -LumieraRecmutex -lumiera_recmutex_init (LumieraRecmutex self, const char* purpose, struct nobug_flag* flag); - -/** - * Destroy a recursive mutex variable - * @param self is a pointer to the mutex to be destroyed - * @return self as given - */ -LumieraRecmutex -lumiera_recmutex_destroy (LumieraRecmutex self, struct nobug_flag* flag); - /** * Callback for unlocking mutexes. * @internal diff --git a/src/lib/recmutex.c b/src/lib/recmutex.c index 57b9b7d65..447a12350 100644 --- a/src/lib/recmutex.c +++ b/src/lib/recmutex.c @@ -19,7 +19,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "lib/mutex.h" +#include "lib/recmutex.h" /** * @file diff --git a/src/lib/recmutex.h b/src/lib/recmutex.h new file mode 100644 index 000000000..a893d3bed --- /dev/null +++ b/src/lib/recmutex.h @@ -0,0 +1,132 @@ +/* + recmutex.h - recursive mutal exclusion locking + + Copyright (C) Lumiera.org + 2008, 2009, Christian Thaeter + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef LUMIERA_RECMUTEX_H +#define LUMIERA_RECMUTEX_H + +#include "lib/error.h" +#include "lib/sectionlock.h" + +#include +#include + +/** + * @file + * Mutual exclusion locking, header. + */ + +/** + * Recursive Mutual exclusive section. + */ +#define LUMIERA_RECMUTEX_SECTION(nobugflag, mtx) \ + for (lumiera_sectionlock NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) \ + lumiera_lock_section_ = { \ + (void*)1, lumiera_mutex_unlock_cb NOBUG_ALPHA_COMMA_NULL NOBUG_ALPHA_COMMA_NULL}; \ + lumiera_lock_section_.lock;) \ + for ( \ + ({ \ + lumiera_lock_section_.lock = (mtx); \ + NOBUG_IF_ALPHA(lumiera_lock_section_.flag = &NOBUG_FLAG(nobugflag);) \ + RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire recmutex", &lumiera_lock_section_, \ + NOBUG_RESOURCE_WAITING, lumiera_lock_section_.rh); \ + if (pthread_mutex_lock (&(mtx)->recmutex)) \ + LUMIERA_DIE (LOCK_ACQUIRE); \ + RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_RECURSIVE, lumiera_lock_section_.rh); \ + }); \ + lumiera_lock_section_.lock; \ + ({ \ + LUMIERA_MUTEX_SECTION_UNLOCK; \ + })) + + +#define LUMIERA_RECMUTEX_SECTION_CHAIN(nobugflag, mtx) \ + for (lumiera_sectionlock *lumiera_lock_section_old_ = &lumiera_lock_section_, \ + NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) lumiera_lock_section_ = { \ + (void*)1, lumiera_mutex_unlock_cb NOBUG_ALPHA_COMMA_NULL NOBUG_ALPHA_COMMA_NULL}; \ + lumiera_lock_section_.lock;) \ + for ( \ + ({ \ + REQUIRE (lumiera_lock_section_old_->lock, "section prematurely unlocked"); \ + lumiera_lock_section_.lock = (mtx); \ + NOBUG_IF_ALPHA(lumiera_lock_section_.flag = &NOBUG_FLAG(nobugflag);) \ + RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire recmutex", &lumiera_lock_section_, \ + NOBUG_RESOURCE_WAITING, lumiera_lock_section_.rh); \ + if (pthread_mutex_lock (&(mtx)->recmutex)) \ + LUMIERA_DIE (LOCK_ACQUIRE); \ + RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_RECURSIVE, lumiera_lock_section_.rh); \ + LUMIERA_SECTION_UNLOCK_(lumiera_lock_section_old_) \ + }); \ + lumiera_lock_section_.lock; \ + ({ \ + LUMIERA_MUTEX_SECTION_UNLOCK; \ + })) + + +#define LUMIERA_RECMUTEX_SECTION_UNLOCK \ + LUMIERA_SECTION_UNLOCK_(&lumiera_lock_section_) + + + +/** + * Mutex. + * + */ +struct lumiera_recmutex_struct +{ + pthread_mutex_t recmutex; + RESOURCE_HANDLE (rh); +}; +typedef struct lumiera_recmutex_struct lumiera_recmutex; +typedef lumiera_recmutex* LumieraRecmutex; + +/** + * Initialize a recursive mutex variable + * Initializes a 'recursive' mutex which might be locked by the same thread multiple times. + * @param self is a pointer to the mutex to be initialized + * @return self as given + */ +LumieraRecmutex +lumiera_recmutex_init (LumieraRecmutex self, const char* purpose, struct nobug_flag* flag); + +/** + * Destroy a recursive mutex variable + * @param self is a pointer to the mutex to be destroyed + * @return self as given + */ +LumieraRecmutex +lumiera_recmutex_destroy (LumieraRecmutex self, struct nobug_flag* flag); + +/** + * Callback for unlocking mutexes. + * @internal + */ +int +lumiera_mutex_unlock_cb (void* mutex); + + +#endif +/* +// Local Variables: +// mode: C +// c-file-style: "gnu" +// indent-tabs-mode: nil +// End: +*/ diff --git a/src/lib/sync.hpp b/src/lib/sync.hpp index e4fcb850a..4a20852b6 100644 --- a/src/lib/sync.hpp +++ b/src/lib/sync.hpp @@ -73,6 +73,7 @@ extern "C" { #include "lib/mutex.h" +#include "lib/recmutex.h" #include "lib/condition.h" #include "lib/reccondition.h" } diff --git a/tests/library/test-locking.c b/tests/library/test-locking.c index 33ac2fccf..7ea7db794 100644 --- a/tests/library/test-locking.c +++ b/tests/library/test-locking.c @@ -21,7 +21,9 @@ #include "tests/test.h" #include "lib/mutex.h" +#include "lib/recmutex.h" #include "lib/condition.h" +#include "lib/reccondition.h" #include "lib/rwlock.h" #include From d91620a60f24920a7f5942a4adb0990e6df72497 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Tue, 27 Jan 2009 10:10:03 +0100 Subject: [PATCH 11/15] New condition and reccondition implementation Should be working but not thoroughly tested still, docs not complete --- src/lib/condition.c | 18 ++-- src/lib/condition.h | 145 ++++++++++++++--------------- src/lib/reccondition.c | 13 ++- src/lib/reccondition.h | 174 +++++++++++++++++------------------ tests/15locking.tests | 16 ++++ tests/library/test-locking.c | 67 ++++++++++++++ 6 files changed, 259 insertions(+), 174 deletions(-) diff --git a/src/lib/condition.c b/src/lib/condition.c index a7f17e57b..9db79c54f 100644 --- a/src/lib/condition.c +++ b/src/lib/condition.c @@ -2,7 +2,7 @@ condition.c - condition variable Copyright (C) Lumiera.org - 2008, Christian Thaeter + 2008, 2009 Christian Thaeter This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -26,8 +26,6 @@ * Condition variables */ -LUMIERA_ERROR_DEFINE (CONDITION_DESTROY, "condition destroy failed"); - LumieraCondition lumiera_condition_init (LumieraCondition self, const char* purpose, struct nobug_flag* flag) @@ -35,7 +33,7 @@ lumiera_condition_init (LumieraCondition self, const char* purpose, struct nobug if (self) { pthread_cond_init (&self->cond, NULL); - pthread_mutex_init (&self->mutex, NULL); + pthread_mutex_init (&self->cndmutex, NULL); NOBUG_RESOURCE_HANDLE_INIT (self->rh); NOBUG_RESOURCE_ANNOUNCE_RAW (flag, "cond_var", purpose, self, self->rh); } @@ -50,15 +48,21 @@ lumiera_condition_destroy (LumieraCondition self, struct nobug_flag* flag) { NOBUG_RESOURCE_FORGET_RAW (flag, self->rh); - if (pthread_mutex_destroy (&self->mutex)) - LUMIERA_DIE (MUTEX_DESTROY); + if (pthread_mutex_destroy (&self->cndmutex)) + LUMIERA_DIE (LOCK_DESTROY); if (pthread_cond_destroy (&self->cond)) - LUMIERA_DIE (CONDITION_DESTROY); + LUMIERA_DIE (LOCK_DESTROY); } return self; } +int lumiera_condition_unlock_cb (void* cond) +{ + return pthread_mutex_unlock (&((LumieraCondition)cond)->cndmutex); +} + + diff --git a/src/lib/condition.h b/src/lib/condition.h index 328d07c49..a2e02cebd 100644 --- a/src/lib/condition.h +++ b/src/lib/condition.h @@ -23,58 +23,73 @@ #define LUMIERA_CONDITION_H #include "lib/error.h" -#include "lib/mutex.h" +#include "lib/sectionlock.h" +#include +#include /** * @file * Condition variables, header */ -LUMIERA_ERROR_DECLARE (CONDITION_DESTROY); - - /** * Condition section. * Locks the condition mutex, one can use LUMIERA_CONDITION_WAIT to wait for signals or * LUMIERA_CONDITION_SIGNAL or LUMIERA_CONDITION_BROADCAST to wake waiting threads + * Condition variables must be at the end of locking chains, they can not be used at + * intermediate position. * @param nobugflag NoBug flag used to log actions on the condition * @param cnd Condition variable to be locked */ -#define LUMIERA_CONDITION_SECTION(nobugflag, cnd) \ - for (lumiera_conditionacquirer NOBUG_CLEANUP(lumiera_conditionacquirer_ensureunlocked) \ - lumiera_condition_section_ = {(LumieraCondition)1}; \ - lumiera_condition_section_.condition;) \ - for ( \ - ({ \ - lumiera_condition_section_.condition = (cnd); \ - NOBUG_IF(NOBUG_MODE_ALPHA, lumiera_condition_section_.flag = &NOBUG_FLAG(nobugflag)); \ - NOBUG_RESOURCE_HANDLE_INIT (lumiera_condition_section_.rh); \ - RESOURCE_ENTER (nobugflag, (cnd)->rh, "acquire condition", &lumiera_condition_section_, \ - NOBUG_RESOURCE_EXCLUSIVE, lumiera_condition_section_.rh); \ - if (pthread_mutex_lock (&(cnd)->mutex)) LUMIERA_DIE (MUTEX_LOCK); \ - }); \ - lumiera_condition_section_.condition; \ - ({ \ - LUMIERA_CONDITION_UNLOCK \ +#define LUMIERA_CONDITION_SECTION(nobugflag, cnd) \ + for (lumiera_sectionlock NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) \ + lumiera_cond_section_ = { \ + (void*)1, lumiera_condition_unlock_cb NOBUG_ALPHA_COMMA_NULL NOBUG_ALPHA_COMMA_NULL}; \ + lumiera_cond_section_.lock;) \ + for ( \ + ({ \ + lumiera_cond_section_.lock = (cnd); \ + NOBUG_IF_ALPHA(lumiera_cond_section_.flag = &NOBUG_FLAG(nobugflag);) \ + RESOURCE_ENTER (nobugflag, (cnd)->rh, "acquire condmutex", &lumiera_cond_section_, \ + NOBUG_RESOURCE_WAITING, lumiera_cond_section_.rh); \ + if (pthread_mutex_lock (&(cnd)->cndmutex)) \ + LUMIERA_DIE (LOCK_ACQUIRE); \ + RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_EXCLUSIVE, lumiera_cond_section_.rh); \ + }); \ + lumiera_cond_section_.lock; \ + ({ \ + LUMIERA_CONDITION_SECTION_UNLOCK; \ })) -/** - * Explicit mutex unlock for a condition variable - * One can early unlock the mutex of a condition variable prior leaving a CONDITION_SECTION. - * The CONDITION_WAIT, CONDITION_SIGNAL and CONDITION_BROADCAST macros must not be used after the mutex - * got unlocked. - * @param nobugflag NoBug flag used to log actions on the condition - */ -#define LUMIERA_CONDITION_UNLOCK \ - if (lumiera_condition_section_.condition) \ - { \ - pthread_mutex_unlock (&lumiera_condition_section_.condition->mutex); \ - lumiera_condition_section_.condition = NULL; \ - NOBUG_RESOURCE_LEAVE_RAW(lumiera_condition_section_.flag, lumiera_condition_section_.rh); \ - } +#define LUMIERA_CONDITION_SECTION_CHAIN(nobugflag, cnd) \ + for (lumiera_sectionlock *lumiera_lock_section_old_ = &lumiera_lock_section_, \ + NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) lumiera_cond_section_ = { \ + (void*)1, lumiera_condition_unlock_cb NOBUG_ALPHA_COMMA_NULL NOBUG_ALPHA_COMMA_NULL}; \ + lumiera_cond_section_.lock;) \ + for ( \ + ({ \ + REQUIRE (lumiera_lock_section_old_->lock, "section prematurely unlocked"); \ + lumiera_cond_section_.lock = cnd; \ + NOBUG_IF_ALPHA(lumiera_cond_section_.flag = &NOBUG_FLAG(nobugflag);) \ + RESOURCE_ENTER (nobugflag, (cnd)->rh, "acquire condmutex", &lumiera_cond_section_, \ + NOBUG_RESOURCE_WAITING, lumiera_cond_section_.rh); \ + if (pthread_mutex_lock (&(cnd)->cndmutex)) \ + LUMIERA_DIE (LOCK_ACQUIRE); \ + RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_EXCLUSIVE, lumiera_cond_section_.rh); \ + LUMIERA_SECTION_UNLOCK_(lumiera_lock_section_old_); \ + }); \ + lumiera_cond_section_.lock; \ + ({ \ + LUMIERA_CONDITION_SECTION_UNLOCK; \ + })) + + + +#define LUMIERA_CONDITION_SECTION_UNLOCK \ + LUMIERA_SECTION_UNLOCK_(&lumiera_cond_section_) /** @@ -82,12 +97,13 @@ LUMIERA_ERROR_DECLARE (CONDITION_DESTROY); * Must be used inside a CONDITION_SECTION. * @param expr Conditon which must become true, else the condition variable goes back into sleep */ -#define LUMIERA_CONDITION_WAIT(expr) \ - do { \ - ENSURE (lumiera_condition_section_.condition, "Condition mutex not locked"); \ - NOBUG_RESOURCE_STATE_RAW (lumiera_condition_section_.flag, lumiera_condition_section_.rh, NOBUG_RESOURCE_WAITING); \ - pthread_cond_wait (&lumiera_condition_section_.condition->cond, &lumiera_condition_section_.condition->mutex); \ - NOBUG_RESOURCE_STATE_RAW (lumiera_condition_section_.flag, lumiera_condition_section_.rh, NOBUG_RESOURCE_EXCLUSIVE);\ +#define LUMIERA_CONDITION_WAIT(expr) \ + do { \ + REQUIRE (lumiera_cond_section_.lock, "Condition mutex not locked"); \ + NOBUG_RESOURCE_STATE_RAW (lumiera_cond_section_.flag, NOBUG_RESOURCE_WAITING, lumiera_cond_section_.rh); \ + pthread_cond_wait (&((LumieraCondition)lumiera_cond_section_.lock)->cond, \ + &((LumieraCondition)lumiera_cond_section_.lock)->cndmutex); \ + NOBUG_RESOURCE_STATE_RAW (lumiera_cond_section_.flag, NOBUG_RESOURCE_EXCLUSIVE, lumiera_cond_section_.rh); \ } while (!(expr)) @@ -96,12 +112,12 @@ LUMIERA_ERROR_DECLARE (CONDITION_DESTROY); * Must be used inside a CONDITION_SECTION. * Wakes one thread waiting on the condition variable */ -#define LUMIERA_CONDITION_SIGNAL \ -do { \ - ENSURE (lumiera_condition_section_.condition, "Condition mutex not locked"); \ - NOBUG_IF(NOBUG_MODE_ALPHA, TRACE(lumiera_condition_section_.flag, "Signaling")); \ - pthread_cond_signal (&lumiera_condition_section_.condition->cond); \ -} while (0) +#define LUMIERA_CONDITION_SIGNAL \ + do { \ + REQUIRE (lumiera_cond_section_.lock, "Condition mutex not locked"); \ + TRACE(NOBUG_FLAG_RAW(lumiera_cond_section_.flag), "Signal %p", &lumiera_cond_section_); \ + pthread_cond_signal (&((LumieraCondition)lumiera_cond_section_.lock)->cond); \ + } while (0) /** @@ -109,13 +125,12 @@ do { * Must be used inside a CONDITION_SECTION. * Wakes all threads waiting on the condition variable */ -#define LUMIERA_CONDITION_BROADCAST \ -do { \ - ENSURE (lumiera_condition_section_.condition, "Condition mutex not locked"); \ - NOBUG_IF(NOBUG_MODE_ALPHA, TRACE(lumiera_condition_section_.flag, "Broadcasting")); \ - pthread_cond_broadcast (&lumiera_condition_section_.condition->cond); \ -} while (0) - +#define LUMIERA_CONDITION_BROADCAST \ + do { \ + REQUIRE (lumiera_cond_section_.lock, "Condition mutex not locked"); \ + TRACE(NOBUG_FLAG_RAW(lumiera_cond_section_.flag), "Broadcast %p", &lumiera_cond_section_); \ + pthread_cond_broadcast (&((LumieraCondition)lumiera_cond_section_.lock)->cond); \ + } while (0) /** @@ -125,7 +140,7 @@ do { struct lumiera_condition_struct { pthread_cond_t cond; - pthread_mutex_t mutex; + pthread_mutex_t cndmutex; RESOURCE_HANDLE (rh); }; typedef struct lumiera_condition_struct lumiera_condition; @@ -149,26 +164,8 @@ lumiera_condition_init (LumieraCondition self, const char* purpose, struct nobug LumieraCondition lumiera_condition_destroy (LumieraCondition self, struct nobug_flag* flag); - -/** - * conditionacquirer used to manage the state of a condition variable. - */ -struct lumiera_conditionacquirer_struct -{ - LumieraCondition condition; - NOBUG_IF(NOBUG_MODE_ALPHA, struct nobug_flag* flag); - RESOURCE_HANDLE (rh); -}; -typedef struct lumiera_conditionacquirer_struct lumiera_conditionacquirer; -typedef struct lumiera_conditionacquirer_struct* LumieraConditionacquirer; - - -/* helper function for nobug */ -static inline void -lumiera_conditionacquirer_ensureunlocked (LumieraConditionacquirer self) -{ - ENSURE (!self->condition, "forgot to unlock condition variable"); -} +int +lumiera_condition_unlock_cb (void* cond); #endif diff --git a/src/lib/reccondition.c b/src/lib/reccondition.c index b70f8d179..59bc956aa 100644 --- a/src/lib/reccondition.c +++ b/src/lib/reccondition.c @@ -2,7 +2,7 @@ reccondition.c - condition variable, w/ recursive mutex Copyright (C) Lumiera.org - 2008, Christian Thaeter + 2008, 2009, Christian Thaeter This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -19,7 +19,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "lib/condition.h" #include "lib/reccondition.h" /** @@ -48,7 +47,7 @@ lumiera_reccondition_init (LumieraReccondition self, const char* purpose, struct pthread_once (&recursive_mutexattr_once, recursive_mutexattr_init); pthread_cond_init (&self->cond, NULL); - pthread_mutex_init (&self->mutex, &recursive_mutexattr); + pthread_mutex_init (&self->reccndmutex, &recursive_mutexattr); NOBUG_RESOURCE_HANDLE_INIT (self->rh); NOBUG_RESOURCE_ANNOUNCE_RAW (flag, "reccond_var", purpose, self, self->rh); } @@ -63,15 +62,19 @@ lumiera_reccondition_destroy (LumieraReccondition self, struct nobug_flag* flag) { NOBUG_RESOURCE_FORGET_RAW (flag, self->rh); - if (pthread_mutex_destroy (&self->mutex)) + if (pthread_mutex_destroy (&self->reccndmutex)) LUMIERA_DIE (LOCK_DESTROY); if (pthread_cond_destroy (&self->cond)) - LUMIERA_DIE (CONDITION_DESTROY); + LUMIERA_DIE (LOCK_DESTROY); } return self; } +int lumiera_reccondition_unlock_cb (void* cond) +{ + return pthread_mutex_unlock (&((LumieraReccondition)cond)->reccndmutex); +} diff --git a/src/lib/reccondition.h b/src/lib/reccondition.h index f3246c516..aa88567d9 100644 --- a/src/lib/reccondition.h +++ b/src/lib/reccondition.h @@ -1,8 +1,8 @@ /* - reccondition.h - condition variables, w/ recursive mutex + reccondition.h - recursive locked condition variables Copyright (C) Lumiera.org - 2008, Christian Thaeter + 2008, 2009, Christian Thaeter This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -23,106 +23,122 @@ #define LUMIERA_RECCONDITION_H #include "lib/error.h" -#include "lib/mutex.h" +#include "lib/sectionlock.h" +#include +#include /** * @file - * Reccondition variables. Same as Conditon variables but using a recursive mutex for locking. + * Condition variables, header */ /** - * Reccondition section. - * Locks the reccondition mutex, one can then use LUMIERA_RECCONDITION_WAIT to wait for signals or + * Recursive Condition section. + * Locks the condition mutex, one can use LUMIERA_RECCONDITION_WAIT to wait for signals or * LUMIERA_RECCONDITION_SIGNAL or LUMIERA_RECCONDITION_BROADCAST to wake waiting threads - * @param nobugflag NoBug flag used to log actions on the reccondition - * @param rcnd Reccondition variable to be locked + * @param nobugflag NoBug flag used to log actions on the condition + * @param cnd Condition variable to be locked */ -#define LUMIERA_RECCONDITION_SECTION(nobugflag, rcnd) \ - for (lumiera_recconditionacquirer NOBUG_CLEANUP(lumiera_recconditionacquirer_ensureunlocked) \ - lumiera_reccondition_section_ = {(LumieraReccondition)1}; \ - lumiera_reccondition_section_.reccondition;) \ - for ( \ - ({ \ - lumiera_reccondition_section_.reccondition = (rcnd); \ - NOBUG_IF(NOBUG_MODE_ALPHA, lumiera_reccondition_section_.flag = &NOBUG_FLAG(nobugflag)); \ - NOBUG_RESOURCE_HANDLE_INIT (lumiera_reccondition_section_.rh); \ - RESOURCE_ENTER (nobugflag, (rcnd)->rh, "acquire reccondition", &lumiera_reccondition_section_, \ - NOBUG_RESOURCE_RECURSIVE, lumiera_reccondition_section_.rh); \ - if (pthread_mutex_lock (&(rcnd)->mutex)) LUMIERA_DIE (MUTEX_LOCK); \ - }); \ - lumiera_reccondition_section_.reccondition; \ - ({ \ - LUMIERA_RECCONDITION_UNLOCK(nobugflag) \ +#define LUMIERA_RECCONDITION_SECTION(nobugflag, cnd) \ + for (lumiera_sectionlock NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) \ + lumiera_reccond_section_ = { \ + (void*)1, lumiera_condition_unlock_cb NOBUG_ALPHA_COMMA_NULL NOBUG_ALPHA_COMMA_NULL}; \ + lumiera_reccond_section_.lock;) \ + for ( \ + ({ \ + lumiera_reccond_section_.lock = (cnd); \ + NOBUG_IF_ALPHA(lumiera_reccond_section_.flag = &NOBUG_FLAG(nobugflag);) \ + RESOURCE_ENTER (nobugflag, (cnd)->rh, "acquire reccondmutex", &lumiera_reccond_section_, \ + NOBUG_RESOURCE_WAITING, lumiera_reccond_section_.rh); \ + if (pthread_mutex_lock (&(cnd)->reccndmutex)) \ + LUMIERA_DIE (LOCK_ACQUIRE); \ + RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_RECURSIVE, lumiera_reccond_section_.rh); \ + }); \ + lumiera_reccond_section_.lock; \ + ({ \ + LUMIERA_RECCONDITION_SECTION_UNLOCK; \ })) -/** - * Explicit mutex unlock for a reccondition variable - * One can early unlock the mutex of a condition variable prior leaving a RECCONDITION_SECTION. - * The RECCONDITION_WAIT, RECCONDITION_SIGNAL and RECCONDITION_BROADCAST macros must not be used after the mutex - * got unlocked. - * @param nobugflag NoBug flag used to log actions on the reccondition - */ -#define LUMIERA_RECCONDITION_UNLOCK \ - if (lumiera_reccondition_section_.reccondition) \ - { \ - pthread_mutex_unlock (&lumiera_reccondition_section_.reccondition->mutex); \ - lumiera_reccondition_section_.reccondition = NULL; \ - RESOURCE_LEAVE(nobugflag, lumiera_reccondition_section_.rh); \ - } + +#define LUMIERA_RECCONDITION_SECTION_CHAIN(nobugflag, cnd) \ + for (lumiera_sectionlock *lumiera_lock_section_old_ = &lumiera_lock_section_, \ + NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) lumiera_reccond_section_ = { \ + (void*)1, lumiera_reccondition_unlock_cb NOBUG_ALPHA_COMMA_NULL NOBUG_ALPHA_COMMA_NULL}; \ + lumiera_reccond_section_.lock;) \ + for ( \ + ({ \ + REQUIRE (lumiera_lock_section_old_->lock, "section prematurely unlocked"); \ + lumiera_reccond_section_.lock = (cnd); \ + NOBUG_IF_ALPHA(lumiera_reccond_section_.flag = &NOBUG_FLAG(nobugflag);) \ + RESOURCE_ENTER (nobugflag, (cnd)->rh, "acquire reccondmutex", &lumiera_reccond_section_, \ + NOBUG_RESOURCE_WAITING, lumiera_reccond_section_.rh); \ + if (pthread_mutex_lock (&(cnd)->reccndmutex)) \ + LUMIERA_DIE (LOCK_ACQUIRE); \ + RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_RECURSIVE, lumiera_reccond_section_.rh); \ + LUMIERA_SECTION_UNLOCK_(lumiera_lock_section_old_) \ + }); \ + lumiera_reccond_section_.lock; \ + ({ \ + LUMIERA_RECCONDITION_SECTION_UNLOCK; \ + })) + + +#define LUMIERA_RECCONDITION_SECTION_UNLOCK \ + LUMIERA_SECTION_UNLOCK_(&lumiera_reccond_section_) /** - * Wait for a reccondition. + * Wait for a condition. * Must be used inside a RECCONDITION_SECTION. - * @param expr Recconditon which must become true, else the reccondition variable goes back into sleep + * @param expr Conditon which must become true, else the condition variable goes back into sleep */ -#define LUMIERA_RECCONDITION_WAIT(expr) \ - do { \ - ENSURE (lumiera_reccondition_section_.reccondition, "Reccondition mutex not locked"); \ - NOBUG_RESOURCE_STATE_RAW (lumiera_reccondition_section_.flag, lumiera_reccondition_section_.rh, NOBUG_RESOURCE_WAITING); \ - pthread_cond_wait (&lumiera_reccondition_section_.reccondition->cond, &lumiera_reccondition_section_.reccondition->mutex); \ - NOBUG_RESOURCE_STATE_RAW (lumiera_reccondition_section_.flag, lumiera_reccondition_section_.rh, NOBUG_RESOURCE_RECURSIVE); \ +#define LUMIERA_RECCONDITION_WAIT(expr) \ + do { \ + REQUIRE (lumiera_reccond_section_.lock, "Condition recmutex not locked"); \ + NOBUG_RESOURCE_STATE_RAW (lumiera_reccond_section_.flag, NOBUG_RESOURCE_WAITING, lumiera_reccond_section_.rh); \ + pthread_cond_wait (&((LumieraCondition)lumiera_reccond_section_.lock)->cond, \ + &((LumieraCondition)lumiera_reccond_section_.lock)->cndmutex); \ + NOBUG_RESOURCE_STATE_RAW (lumiera_reccond_section_.flag, NOBUG_RESOURCE_RECURSIVE, lumiera_reccond_section_.rh); \ } while (!(expr)) /** - * Signal a reccondition variable + * Signal a condition variable * Must be used inside a RECCONDITION_SECTION. * Wakes one thread waiting on the condition variable */ -#define LUMIERA_RECCONDITION_SIGNAL \ -do { \ - ENSURE (lumiera_reccondition_section_.reccondition, "Reccondition mutex not locked"); \ - NOBUG_IF(NOBUG_MODE_ALPHA, TRACE(lumiera_reccondition_section_.flag, "Signaling")); \ - pthread_cond_signal (&lumiera_reccondition_section_.reccondition->cond); \ -} while (0) +#define LUMIERA_RECCONDITION_SIGNAL \ + do { \ + REQUIRE (lumiera_reccond_section_.lock, "Condition recmutex not locked"); \ + TRACE(NOBUG_FLAG_RAW(lumiera_reccond_section_.flag), "Signal %p", &lumiera_reccond_section_); \ + pthread_cond_signal (&((LumieraCondition)lumiera_reccond_section_.lock)->cond); \ + } while (0) /** - * Broadcast a reccondition variable + * Broadcast a condition variable * Must be used inside a RECCONDITION_SECTION. - * Wakes all threads waiting on the reccondition variable + * Wakes all threads waiting on the condition variable */ -#define LUMIERA_RECCONDITION_BROADCAST \ -do { \ - ENSURE (lumiera_reccondition_section_.reccondition, "Reccondition mutex not locked"); \ - NOBUG_IF(NOBUG_MODE_ALPHA, TRACE(lumiera_reccondition_section_.flag, "Broadcasting"));\ - pthread_cond_broadcast (&lumiera_reccondition_section_.reccondition->cond); \ -} while (0) - +#define LUMIERA_RECCONDITION_BROADCAST \ + do { \ + REQUIRE (lumiera_reccond_section_.lock, "Condition recmutex not locked"); \ + TRACE(NOBUG_FLAG_RAW(lumiera_reccond_section_.flag), "Broadcast %p", &lumiera_reccond_section_); \ + pthread_cond_broadcast (&((LumieraCondition)lumiera_reccond_section_.lock)->cond); \ + } while (0) /** - * Reccondition variables. + * Condition variables. Recursive mutex variant. * */ struct lumiera_reccondition_struct { pthread_cond_t cond; - pthread_mutex_t mutex; + pthread_mutex_t reccndmutex; RESOURCE_HANDLE (rh); }; typedef struct lumiera_reccondition_struct lumiera_reccondition; @@ -130,8 +146,8 @@ typedef lumiera_reccondition* LumieraReccondition; /** - * Initialize a reccondition variable - * @param self is a pointer to the reccondition variable to be initialized + * Initialize a condition variable + * @param self is a pointer to the condition variable to be initialized * @return self as given */ LumieraReccondition @@ -139,34 +155,16 @@ lumiera_reccondition_init (LumieraReccondition self, const char* purpose, struct /** - * Destroy a reccondition variable - * @param self is a pointer to the reccondition variable to be destroyed + * Destroy a condition variable + * @param self is a pointer to the condition variable to be destroyed * @return self as given */ LumieraReccondition lumiera_reccondition_destroy (LumieraReccondition self, struct nobug_flag* flag); -/** - * recconditionacquirer used to manage the state of a reccondition variable. - */ -struct lumiera_recconditionacquirer_struct -{ - LumieraReccondition reccondition; - NOBUG_IF(NOBUG_MODE_ALPHA, struct nobug_flag* flag); - RESOURCE_HANDLE (rh); -}; -typedef struct lumiera_recconditionacquirer_struct lumiera_recconditionacquirer; -typedef struct lumiera_recconditionacquirer_struct* LumieraRecconditionacquirer; - - -/* helper function for nobug */ -static inline void -lumiera_recconditionacquirer_ensureunlocked (LumieraRecconditionacquirer self) -{ - ENSURE (!self->reccondition, "forgot to unlock reccondition variable"); -} - +int +lumiera_reccondition_unlock_cb (void* cond); #endif /* diff --git a/tests/15locking.tests b/tests/15locking.tests index 0fc57c233..0936499f2 100644 --- a/tests/15locking.tests +++ b/tests/15locking.tests @@ -70,3 +70,19 @@ PLANNED "condition broadcasting" < Date: Wed, 28 Jan 2009 04:17:01 +0100 Subject: [PATCH 12/15] weed out reccondition bugs/typos --- src/lib/reccondition.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/lib/reccondition.h b/src/lib/reccondition.h index aa88567d9..a2dd54f58 100644 --- a/src/lib/reccondition.h +++ b/src/lib/reccondition.h @@ -44,7 +44,7 @@ #define LUMIERA_RECCONDITION_SECTION(nobugflag, cnd) \ for (lumiera_sectionlock NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) \ lumiera_reccond_section_ = { \ - (void*)1, lumiera_condition_unlock_cb NOBUG_ALPHA_COMMA_NULL NOBUG_ALPHA_COMMA_NULL}; \ + (void*)1, lumiera_reccondition_unlock_cb NOBUG_ALPHA_COMMA_NULL NOBUG_ALPHA_COMMA_NULL}; \ lumiera_reccond_section_.lock;) \ for ( \ ({ \ @@ -99,8 +99,8 @@ do { \ REQUIRE (lumiera_reccond_section_.lock, "Condition recmutex not locked"); \ NOBUG_RESOURCE_STATE_RAW (lumiera_reccond_section_.flag, NOBUG_RESOURCE_WAITING, lumiera_reccond_section_.rh); \ - pthread_cond_wait (&((LumieraCondition)lumiera_reccond_section_.lock)->cond, \ - &((LumieraCondition)lumiera_reccond_section_.lock)->cndmutex); \ + pthread_cond_wait (&((LumieraReccondition)lumiera_reccond_section_.lock)->cond, \ + &((LumieraReccondition)lumiera_reccond_section_.lock)->reccndmutex); \ NOBUG_RESOURCE_STATE_RAW (lumiera_reccond_section_.flag, NOBUG_RESOURCE_RECURSIVE, lumiera_reccond_section_.rh); \ } while (!(expr)) @@ -114,7 +114,7 @@ do { \ REQUIRE (lumiera_reccond_section_.lock, "Condition recmutex not locked"); \ TRACE(NOBUG_FLAG_RAW(lumiera_reccond_section_.flag), "Signal %p", &lumiera_reccond_section_); \ - pthread_cond_signal (&((LumieraCondition)lumiera_reccond_section_.lock)->cond); \ + pthread_cond_signal (&((LumieraReccondition)lumiera_reccond_section_.lock)->cond); \ } while (0) @@ -127,7 +127,7 @@ do { \ REQUIRE (lumiera_reccond_section_.lock, "Condition recmutex not locked"); \ TRACE(NOBUG_FLAG_RAW(lumiera_reccond_section_.flag), "Broadcast %p", &lumiera_reccond_section_); \ - pthread_cond_broadcast (&((LumieraCondition)lumiera_reccond_section_.lock)->cond); \ + pthread_cond_broadcast (&((LumieraReccondition)lumiera_reccond_section_.lock)->cond); \ } while (0) From 323724b623ca83bdbb20d94af6cd971402fd841a Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Wed, 28 Jan 2009 04:18:53 +0100 Subject: [PATCH 13/15] fix some includes for new mutex/recmutex headers --- src/common/interface.c | 2 +- src/common/interfaceregistry.c | 1 - src/common/interfaceregistry.h | 1 + src/common/plugin.c | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/common/interface.c b/src/common/interface.c index 1853c7af3..a8d91c40f 100644 --- a/src/common/interface.c +++ b/src/common/interface.c @@ -21,7 +21,7 @@ #include "include/logging.h" -#include "lib/mutex.h" +#include "lib/recmutex.h" #include "lib/safeclib.h" #include "common/plugin.h" diff --git a/src/common/interfaceregistry.c b/src/common/interfaceregistry.c index 5b0db98e7..3b67e77e1 100644 --- a/src/common/interfaceregistry.c +++ b/src/common/interfaceregistry.c @@ -20,7 +20,6 @@ */ #include "include/logging.h" -#include "lib/mutex.h" #include "lib/error.h" #include "lib/psplay.h" #include "lib/safeclib.h" diff --git a/src/common/interfaceregistry.h b/src/common/interfaceregistry.h index 0ec20f29c..bc4f11440 100644 --- a/src/common/interfaceregistry.h +++ b/src/common/interfaceregistry.h @@ -22,6 +22,7 @@ #define LUMIERA_INTERFACEREGISTRY_H #include "lib/mutex.h" +#include "lib/recmutex.h" #include "lib/psplay.h" #include "common/interface.h" diff --git a/src/common/plugin.c b/src/common/plugin.c index 1d24f9c5e..2ddd58998 100644 --- a/src/common/plugin.c +++ b/src/common/plugin.c @@ -22,7 +22,7 @@ #include "include/logging.h" #include "lib/safeclib.h" #include "lib/psplay.h" -#include "lib/mutex.h" +#include "lib/recmutex.h" #include "lib/error.h" #include "common/interfaceregistry.h" From dd9b7a174f1e5f914c3ed499530ace4c7bef2960 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Wed, 28 Jan 2009 04:56:01 +0100 Subject: [PATCH 14/15] Add reccondition to threads, make its functionality complete With this the threads are now usable, despite still a mockup implementation. Some basic tests to show their use included. --- src/backend/Makefile.am | 4 +- src/backend/threads.c | 57 ++++++------- src/backend/threads.h | 4 +- tests/Makefile.am | 6 ++ tests/backend/test-threads.c | 159 +++++++++++++++++++++++++++++++++++ tests/library/test-locking.c | 1 + 6 files changed, 198 insertions(+), 33 deletions(-) create mode 100644 tests/backend/test-threads.c diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am index c2161cc82..5729d910b 100644 --- a/src/backend/Makefile.am +++ b/src/backend/Makefile.am @@ -19,7 +19,7 @@ liblumierabackend_la_srcdir = $(top_srcdir)/src/backend lib_LTLIBRARIES += liblumierabackend.la liblumierabackend_la_CPPFLAGS = $(AM_CPPFLAGS) -liblumierabackend_la_CFLAGS = $(AM_CFLAGS) -std=gnu99 -Wextra -Wall -Werror +liblumierabackend_la_CFLAGS = $(AM_CFLAGS) -std=gnu99 -Wextra -Wall -Werror liblumierabackend_la_LIBADD = liblumiera.la liblumierabackend_la_SOURCES = \ @@ -29,10 +29,10 @@ liblumierabackend_la_SOURCES = \ $(liblumierabackend_la_srcdir)/file.c \ $(liblumierabackend_la_srcdir)/filehandle.c \ $(liblumierabackend_la_srcdir)/filedescriptor.c \ + $(liblumierabackend_la_srcdir)/filehandlecache.c \ $(liblumierabackend_la_srcdir)/mmap.c \ $(liblumierabackend_la_srcdir)/mmapings.c \ $(liblumierabackend_la_srcdir)/mmapcache.c \ - $(liblumierabackend_la_srcdir)/filehandlecache.c \ $(liblumierabackend_la_srcdir)/enginefacade.cpp \ $(liblumierabackend_la_srcdir)/scriptrunnerfacade.cpp \ $(liblumierabackend_la_srcdir)/netnodefacade.cpp diff --git a/src/backend/threads.c b/src/backend/threads.c index 794d13b79..1ff7184f9 100644 --- a/src/backend/threads.c +++ b/src/backend/threads.c @@ -21,6 +21,7 @@ //TODO: Support library includes// +#include "include/logging.h" //TODO: Lumiera header includes// #include "threads.h" @@ -41,8 +42,29 @@ //code goes here// -/* really dumb mutex, to make the mockup little less brittle */ -static pthread_mutex_t threads_mutex = PTHREAD_MUTEX_INITIALIZER; + +struct lumiera_thread_mockup +{ + void (*fn)(void*); + void* arg; + LumieraReccondition finished; +}; + + +static void* pthread_runner (void* thread) +{ + pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL); + + struct lumiera_thread_mockup* starter = (struct lumiera_thread_mockup*) thread; + + starter->fn (starter->arg); + + LUMIERA_RECCONDITION_SECTION(cond_sync, starter->finished) + LUMIERA_RECCONDITION_BROADCAST; + + return NULL; +} + static pthread_once_t attr_once = PTHREAD_ONCE_INIT; static pthread_attr_t attrs; @@ -51,42 +73,22 @@ static void thread_attr_init (void) { pthread_attr_init (&attrs); pthread_attr_setdetachstate (&attrs, PTHREAD_CREATE_DETACHED); - pthread_attr_setdetachstate (&attrs, PTHREAD_CREATE_DETACHED); + //cancel ... } -struct lumiera_thread_mockup -{ - void (*fn)(void*); - void* arg; -}; - - -static void* pthread_runner (void* thread) -{ - struct lumiera_thread_mockup* starter = (struct lumiera_thread_mockup*) thread; - (void) starter; - pthread_mutex_lock (&threads_mutex); - pthread_mutex_unlock (&threads_mutex); - starter->fn (starter->arg); - return NULL; -} - - + LumieraThread lumiera_thread_run (enum lumiera_thread_class kind, void (*start_routine)(void *), void * arg, - LumieraCondition finished, + LumieraReccondition finished, const char* purpose, struct nobug_flag* flag) { (void) kind; - (void) finished; (void) purpose; (void) flag; - REQUIRE (!finished, "Condition variable for finish notification not yet implemented"); - if (attr_once == PTHREAD_ONCE_INIT) pthread_once (&attr_once, thread_attr_init); @@ -94,14 +96,11 @@ lumiera_thread_run (enum lumiera_thread_class kind, thread.fn = start_routine; thread.arg = arg; - - pthread_mutex_lock (&threads_mutex); + thread.finished = finished; pthread_t dummy; int error = pthread_create (&dummy, &attrs, pthread_runner, &thread); - pthread_mutex_unlock (&threads_mutex); - if (error) return 0; /////TODO temporary addition by Ichthyo; probably we'll set lumiera_error? return (LumieraThread) 1; } diff --git a/src/backend/threads.h b/src/backend/threads.h index 50786c729..9d420fa2f 100644 --- a/src/backend/threads.h +++ b/src/backend/threads.h @@ -23,7 +23,7 @@ #define LUMIERA_THREADS_H //TODO: Support library includes// -#include "lib/condition.h" +#include "lib/reccondition.h" //TODO: Forward declarations// @@ -96,7 +96,7 @@ LumieraThread lumiera_thread_run (enum lumiera_thread_class kind, void (*start_routine)(void *), void * arg, - LumieraCondition finished, + LumieraReccondition finished, const char* purpose, struct nobug_flag* flag); diff --git a/tests/Makefile.am b/tests/Makefile.am index acaf205b6..f5404f3f1 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -105,4 +105,10 @@ test_interfaces_LDADD = \ -lboost_program_options-mt \ -lboost_regex-mt +check_PROGRAMS += test-threads +test_threads_SOURCES = $(tests_srcdir)/backend/test-threads.c +test_threads_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -I$(top_srcdir)/src/ +test_threads_CFLAGS = $(AM_CFLAGS) $(PTHREAD_CFLAGS) +test_threads_LDADD = liblumierabackend.la liblumiera.la -lnobugmt -lpthread -ldl -lm liblumieracommon.la liblumieraproc.la -ldl -lboost_program_options-mt -lboost_regex-mt + TESTS = $(tests_srcdir)/test.sh diff --git a/tests/backend/test-threads.c b/tests/backend/test-threads.c new file mode 100644 index 000000000..14237f7a2 --- /dev/null +++ b/tests/backend/test-threads.c @@ -0,0 +1,159 @@ +/* + test-threads.c - test thread management + + Copyright (C) Lumiera.org + 2008, Christian Thaeter + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +//#include +//#include + +#include "common/config.h" + +#include "include/logging.h" +#include "lib/mutex.h" +#include "backend/threads.h" +#include "tests/test.h" + +#include +#include +#include + +void threadfn(void* blah) +{ + (void) blah; + struct timespec wait = {0,300000000}; + + fprintf (stderr, "thread running %s\n", NOBUG_THREAD_ID_GET); + nanosleep (&wait, NULL); + fprintf (stderr, "thread done %s\n", NOBUG_THREAD_ID_GET); +} + + +void threadsyncfn(void* blah) +{ + struct timespec wait = {0,200000000}; + LumieraReccondition sync = (LumieraReccondition) blah; + + ECHO ("thread starting up %s", NOBUG_THREAD_ID_GET); + LUMIERA_RECCONDITION_SECTION(cond_sync, sync) + { + ECHO ("send startup signal %s", NOBUG_THREAD_ID_GET); + LUMIERA_RECCONDITION_SIGNAL; + ECHO ("wait for trigger %s", NOBUG_THREAD_ID_GET); + LUMIERA_RECCONDITION_WAIT(1); + } + + ECHO ("thread running %s", NOBUG_THREAD_ID_GET); + nanosleep (&wait, NULL); + ECHO ("thread done %s", NOBUG_THREAD_ID_GET); +} + + + +lumiera_mutex testmutex; + +void mutexfn(void* blah) +{ + (void) blah; + struct timespec wait = {0,300000000}; + + LUMIERA_MUTEX_SECTION (NOBUG_ON, &testmutex) + { + fprintf (stderr, "mutex thread running %s\n", NOBUG_THREAD_ID_GET); + nanosleep (&wait, NULL); + fprintf (stderr, "thread done %s\n", NOBUG_THREAD_ID_GET); + } +} + + + +TESTS_BEGIN + +TEST ("simple_thread") +{ + fprintf (stderr, "main before thread %s\n", NOBUG_THREAD_ID_GET); + + lumiera_thread_run (LUMIERA_THREAD_WORKER, + threadfn, + NULL, + NULL, + argv[1], + NULL); + + struct timespec wait = {0,600000000}; + nanosleep (&wait, NULL); + fprintf (stderr, "main after thread %s\n", NOBUG_THREAD_ID_GET); +} + +TEST ("thread_synced") +{ + lumiera_reccondition cnd; + lumiera_reccondition_init (&cnd, "threadsync", &NOBUG_FLAG(NOBUG_ON)); + + LUMIERA_RECCONDITION_SECTION(cond_sync, &cnd) + { + ECHO ("main before thread %s", NOBUG_THREAD_ID_GET); + + lumiera_thread_run (LUMIERA_THREAD_WORKER, + threadsyncfn, + &cnd, + &cnd, + argv[1], + NULL); + + ECHO ("main wait for thread being ready %s", NOBUG_THREAD_ID_GET); + LUMIERA_RECCONDITION_WAIT(1); + + ECHO ("main trigger thread %s", NOBUG_THREAD_ID_GET); + LUMIERA_RECCONDITION_SIGNAL; + + ECHO ("wait for thread end %s", NOBUG_THREAD_ID_GET); + LUMIERA_RECCONDITION_WAIT(1); + ECHO ("thread ended %s", NOBUG_THREAD_ID_GET); + } + + lumiera_reccondition_destroy (&cnd, &NOBUG_FLAG(NOBUG_ON)); +} + + + +TEST ("mutex_thread") +{ + lumiera_mutex_init (&testmutex, "test", &NOBUG_FLAG(NOBUG_ON)); + + LUMIERA_MUTEX_SECTION (NOBUG_ON, &testmutex) + { + fprintf (stderr, "main before thread %s\n", NOBUG_THREAD_ID_GET); + + lumiera_thread_run (LUMIERA_THREAD_WORKER, + mutexfn, + NULL, + NULL, + argv[1], + NULL); + + struct timespec wait = {0,600000000}; + nanosleep (&wait, NULL); + fprintf (stderr, "main after thread %s\n", NOBUG_THREAD_ID_GET); + } + + lumiera_mutex_destroy (&testmutex, &NOBUG_FLAG(NOBUG_ON)); +} + + +TESTS_END diff --git a/tests/library/test-locking.c b/tests/library/test-locking.c index 5728783ec..14ec0c458 100644 --- a/tests/library/test-locking.c +++ b/tests/library/test-locking.c @@ -254,6 +254,7 @@ TEST ("conditionsection") } + TEST ("conditionforgotunlock") { lumiera_condition cond; From 99b5f8d44d7aae9f3d1443c95311428910ddd90d Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Thu, 29 Jan 2009 20:05:52 +0100 Subject: [PATCH 15/15] adapt the Sync template --- src/lib/sync.hpp | 57 +++++++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/src/lib/sync.hpp b/src/lib/sync.hpp index 4a20852b6..c4cef10ed 100644 --- a/src/lib/sync.hpp +++ b/src/lib/sync.hpp @@ -99,11 +99,13 @@ namespace lib { protected: Wrapped_LumieraExcMutex() { lumiera_mutex_init (this, "Obj.Monitor ExclMutex", &NOBUG_FLAG(sync)); } ~Wrapped_LumieraExcMutex() { lumiera_mutex_destroy (this, &NOBUG_FLAG(sync)); } - + + pthread_mutex_t* mutex() { return &(lumiera_mutex::mutex); } + //------------------Resource-Tracking------ void __may_block() { TODO ("Record we may block on mutex"); } void __enter() { TODO ("Record we successfully acquired the mutex"); } - void __left() { TODO ("Record we are released the mutex"); } + void __left() { TODO ("Record we released the mutex"); } }; @@ -113,11 +115,13 @@ namespace lib { protected: Wrapped_LumieraRecMutex() { lumiera_recmutex_init (this, "Obj.Monitor RecMutex", &NOBUG_FLAG(sync)); } ~Wrapped_LumieraRecMutex() { lumiera_recmutex_destroy (this, &NOBUG_FLAG(sync)); } - + + pthread_mutex_t* mutex() { return &recmutex; } + //------------------Resource-Tracking------ void __may_block() { TODO ("Record we may block on mutex"); } void __enter() { TODO ("Record we successfully acquired the mutex"); } - void __left() { TODO ("Record we are released the mutex"); } + void __left() { TODO ("Record we are released the mutex"); } }; @@ -127,11 +131,14 @@ namespace lib { protected: Wrapped_LumieraExcCond() { lumiera_condition_init (this, "Obj.Monitor ExclCondition", &NOBUG_FLAG(sync) ); } ~Wrapped_LumieraExcCond() { lumiera_condition_destroy (this, &NOBUG_FLAG(sync) ); } - + + pthread_mutex_t* mutex() { return &cndmutex; } + pthread_cond_t* condv() { return &cond; } + //------------------Resource-Tracking------ void __may_block() { TODO ("Record we may block on mutex"); } void __enter() { TODO ("Record we successfully acquired the mutex"); } - void __left() { TODO ("Record we are released the mutex"); } + void __left() { TODO ("Record we released the mutex"); } }; @@ -141,11 +148,14 @@ namespace lib { protected: Wrapped_LumieraRecCond() { lumiera_reccondition_init (this, "Obj.Monitor RecCondition", &NOBUG_FLAG(sync) ); } ////////TODO ~Wrapped_LumieraRecCond() { lumiera_reccondition_destroy (this, &NOBUG_FLAG(sync) ); } - + + pthread_mutex_t* mutex() { return &reccndmutex; } + pthread_cond_t* condv() { return &cond; } + //------------------Resource-Tracking------ void __may_block() { TODO ("Record we may block on mutex"); } void __enter() { TODO ("Record we successfully acquired the mutex"); } - void __left() { TODO ("Record we are released the mutex"); } + void __left() { TODO ("Record we released the mutex"); } }; @@ -157,7 +167,7 @@ namespace lib { : protected MTX { protected: - //using MTX::mutex; + using MTX::mutex; using MTX::__may_block; using MTX::__enter; using MTX::__left; @@ -172,21 +182,18 @@ namespace lib { acquire() { __may_block(); - - FIXME ("For to make C typesafe we have now mutex and recmutex member gnah :P -- cehteh"); - // well .. specialization on the mutex type shall solve it ... - //if (pthread_mutex_lock (&mutex)) - // throw lumiera::error::State("Mutex acquire failed."); ///////TODO capture the error-code - + + if (pthread_mutex_lock (mutex())) + throw lumiera::error::State("Mutex acquire failed."); ///////TODO capture the error-code + __enter(); } void release() - { - FIXME ("For to make C typesafe we have now mutex and recmutex member gnah :P -- cehteh"); - //pthread_mutex_unlock (&mutex); - + { + pthread_mutex_unlock (mutex()); + __left(); } @@ -201,7 +208,7 @@ namespace lib { : public Mutex { protected: - using CDX::cond; + using CDX::condv; using CDX::mutex; public: @@ -209,9 +216,9 @@ namespace lib { signal (bool wakeAll=false) { if (wakeAll) - pthread_cond_broadcast (&cond); + pthread_cond_broadcast (condv()); else - pthread_cond_signal (&cond); + pthread_cond_signal (condv()); } @@ -222,9 +229,9 @@ namespace lib { int err=0; while (!predicate() && !err) if (waitEndTime) - err = pthread_cond_timedwait (&cond, &mutex, &waitEndTime); + err = pthread_cond_timedwait (condv(), mutex(), &waitEndTime); else - err = pthread_cond_wait (&cond, &mutex); + err = pthread_cond_wait (condv(), mutex()); if (!err) return true; if (ETIMEDOUT==err) return false; @@ -442,7 +449,7 @@ namespace lib { #endif /* // Local Variables: -// mode: C +// mode: C++ // c-file-style: "gnu" // indent-tabs-mode: nil // End: