rwlock makeover, locksections etc...
The CHAINED variant is not tested, what could go wrong anyways :)
This commit is contained in:
parent
ca0250c018
commit
5c2ac96f35
4 changed files with 145 additions and 58 deletions
|
|
@ -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
|
||||
|
|
|
|||
149
src/lib/rwlock.h
149
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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue