diff options
author | Sven Gothel <[email protected]> | 2014-06-10 05:30:02 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2014-06-10 05:30:02 +0200 |
commit | f95bf4457fbc31112fa82dacbc1b7e094b9fd1cf (patch) | |
tree | 965ba5b8e6fc8e6bfe7a981c1dfb1179bb9adcde /common/rwlock.c | |
parent | 7297c3214a4c648aaee81a9877da15b88f798197 (diff) | |
parent | c07fb7b45c1e345dbaa439882250de5b2213026f (diff) |
Merge branch 'UPSTREAM' into UPSTREAM_MERGE
Diffstat (limited to 'common/rwlock.c')
-rw-r--r-- | common/rwlock.c | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/common/rwlock.c b/common/rwlock.c new file mode 100644 index 00000000..ff7aa418 --- /dev/null +++ b/common/rwlock.c @@ -0,0 +1,62 @@ + +#include "config.h" + +#include "rwlock.h" + +#include "bool.h" +#include "atomic.h" +#include "threads.h" + + +/* A simple spinlock. Yield the thread while the given integer is set by + * another. Could probably be improved... */ +static void Lock(volatile int *l) +{ + while(ExchangeInt(l, true) == true) + althrd_yield(); +} + +static void Unlock(volatile int *l) +{ + ExchangeInt(l, false); +} + + +void RWLockInit(RWLock *lock) +{ + InitRef(&lock->read_count, 0); + InitRef(&lock->write_count, 0); + lock->read_lock = false; + lock->read_entry_lock = false; + lock->write_lock = false; +} + +void ReadLock(RWLock *lock) +{ + Lock(&lock->read_entry_lock); + Lock(&lock->read_lock); + if(IncrementRef(&lock->read_count) == 1) + Lock(&lock->write_lock); + Unlock(&lock->read_lock); + Unlock(&lock->read_entry_lock); +} + +void ReadUnlock(RWLock *lock) +{ + if(DecrementRef(&lock->read_count) == 0) + Unlock(&lock->write_lock); +} + +void WriteLock(RWLock *lock) +{ + if(IncrementRef(&lock->write_count) == 1) + Lock(&lock->read_lock); + Lock(&lock->write_lock); +} + +void WriteUnlock(RWLock *lock) +{ + Unlock(&lock->write_lock); + if(DecrementRef(&lock->write_count) == 0) + Unlock(&lock->read_lock); +} |