diff options
author | Chris Robinson <[email protected]> | 2014-05-07 19:16:49 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2014-05-07 19:16:49 -0700 |
commit | a2bddb7b40960b3a8680afa0ab31e99d204dece1 (patch) | |
tree | 999977561aff4cec16ee966c494666371a60fde7 /common/rwlock.c | |
parent | 3e274c3a5784daa313fb5f7663f1b1fc55f5cefc (diff) |
Move RWLock and UIntMap implementations to common
This should make the code in common completely self-reliant.
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..b967db0a --- /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) +{ + lock->read_count = 0; + 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); +} |