rwlock makeover, locksections etc...

The CHAINED variant is not tested, what could go wrong anyways :)
This commit is contained in:
Christian Thaeter 2009-01-26 07:30:20 +01:00
parent ca0250c018
commit 5c2ac96f35
4 changed files with 145 additions and 58 deletions

View file

@ -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

View file

@ -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

View file

@ -45,6 +45,15 @@ return: 134
END
PLANNED "rwlock readlock in writelock asserts" rwlockdeadlockwr <<END
return: 134
END
PLANNED "rwlock writelock in readlock asserts" rwlockdeadlockrw <<END
return: 134
END
TEST "condition not unlocked asserts" conditionforgotunlock <<END
return: 134
END

View file

@ -164,6 +164,7 @@ TEST ("rwlocksection")
lumiera_rwlock_destroy (&rwlock, &NOBUG_FLAG(NOBUG_ON));
}
TEST ("rwlockforgotunlock")
{
lumiera_rwlock rwlock;
@ -178,6 +179,44 @@ TEST ("rwlockforgotunlock")
}
TEST ("rwdeadlockwr")
{
lumiera_rwlock rwlock;
lumiera_rwlock_init (&rwlock, "rwsection", &NOBUG_FLAG(NOBUG_ON));
LUMIERA_WRLOCK_SECTION (NOBUG_ON, &rwlock)
{
printf ("write locked section 1\n");
LUMIERA_RDLOCK_SECTION (NOBUG_ON, &rwlock)
{
printf ("read locked section 2\n");
}
}
lumiera_rwlock_destroy (&rwlock, &NOBUG_FLAG(NOBUG_ON));
}
TEST ("rwdeadlockrw")
{
lumiera_rwlock rwlock;
lumiera_rwlock_init (&rwlock, "rwsection", &NOBUG_FLAG(NOBUG_ON));
LUMIERA_RDLOCK_SECTION (NOBUG_ON, &rwlock)
{
printf ("read locked section 1\n");
LUMIERA_WRLOCK_SECTION (NOBUG_ON, &rwlock)
{
printf ("write locked section 2\n");
}
}
lumiera_rwlock_destroy (&rwlock, &NOBUG_FLAG(NOBUG_ON));
}
TEST ("conditionsection")
{
lumiera_condition cond;