aboutsummaryrefslogtreecommitdiffstats
path: root/common/rwlock.c
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2014-06-10 05:30:02 +0200
committerSven Gothel <[email protected]>2014-06-10 05:30:02 +0200
commitf95bf4457fbc31112fa82dacbc1b7e094b9fd1cf (patch)
tree965ba5b8e6fc8e6bfe7a981c1dfb1179bb9adcde /common/rwlock.c
parent7297c3214a4c648aaee81a9877da15b88f798197 (diff)
parentc07fb7b45c1e345dbaa439882250de5b2213026f (diff)
Merge branch 'UPSTREAM' into UPSTREAM_MERGE
Diffstat (limited to 'common/rwlock.c')
-rw-r--r--common/rwlock.c62
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);
+}