diff --git a/ctr-std/src/sys/unix/rwlock.rs b/ctr-std/src/sys/unix/rwlock.rs index 76d2271..4a802e9 100644 --- a/ctr-std/src/sys/unix/rwlock.rs +++ b/ctr-std/src/sys/unix/rwlock.rs @@ -16,7 +16,7 @@ use super::condvar::Condvar; pub struct RWLock { mutex: Mutex, cvar: Condvar, - reader_count: UnsafeCell, // Is 255 potential readers enough? I would hope so, but idk + reader_count: UnsafeCell, writer_active: UnsafeCell, } @@ -36,10 +36,14 @@ impl RWLock { #[inline] pub unsafe fn read(&self) { self.mutex.lock(); + while *self.writer_active.get() { self.cvar.wait(&self.mutex); } + + assert!(*self.reader_count.get() != u32::max_value()); *self.reader_count.get() += 1; + self.mutex.unlock(); } @@ -52,19 +56,24 @@ impl RWLock { while *self.writer_active.get() { self.cvar.wait(&self.mutex); } + + assert!(*self.reader_count.get() != u32::max_value()); *self.reader_count.get() += 1; - self.mutex.unlock(); + self.mutex.unlock(); true } #[inline] pub unsafe fn write(&self) { self.mutex.lock(); + while *self.writer_active.get() || *self.reader_count.get() > 0 { self.cvar.wait(&self.mutex); } + *self.writer_active.get() = true; + self.mutex.unlock(); } @@ -77,27 +86,34 @@ impl RWLock { while *self.writer_active.get() || *self.reader_count.get() > 0 { self.cvar.wait(&self.mutex); } + *self.writer_active.get() = true; - self.mutex.unlock(); + self.mutex.unlock(); true } #[inline] pub unsafe fn read_unlock(&self) { self.mutex.lock(); + *self.reader_count.get() -= 1; + if *self.reader_count.get() == 0 { self.cvar.notify_one() } + self.mutex.unlock(); } #[inline] pub unsafe fn write_unlock(&self) { self.mutex.lock(); + *self.writer_active.get() = false; + self.cvar.notify_all(); + self.mutex.unlock(); }