Implement read-write lock methods in CriticalSectionRawRwLock and update tests

This commit is contained in:
Alix ANNERAUD 2025-02-28 23:26:59 +01:00
parent 5568478225
commit 9cbdc9f11d
2 changed files with 52 additions and 7 deletions

View File

@ -1,7 +1,7 @@
//! Read-Write Lock primitives. //! Read-Write Lock primitives.
//! //!
//! This module provides a trait for read-write locks that can be used in different contexts. //! This module provides a trait for read-write locks that can be used in different contexts.
use core::marker::PhantomData; use core::{cell::RefCell, marker::PhantomData};
/// Raw read-write lock trait. /// Raw read-write lock trait.
/// ///
@ -41,15 +41,50 @@ pub unsafe trait RawRwLock {
/// ///
/// This read-write lock is safe to share between different executors and interrupts. /// This read-write lock is safe to share between different executors and interrupts.
pub struct CriticalSectionRawRwLock { pub struct CriticalSectionRawRwLock {
_phantom: PhantomData<()>, state: RefCell<isize>,
} }
unsafe impl Send for CriticalSectionRawRwLock {} unsafe impl Send for CriticalSectionRawRwLock {}
unsafe impl Sync for CriticalSectionRawRwLock {} unsafe impl Sync for CriticalSectionRawRwLock {}
impl CriticalSectionRawRwLock { impl CriticalSectionRawRwLock {
/// Create a new `CriticalSectionRawRwLock`. /// Creates a new [`CriticalSectionRawRwLock`].
pub const fn new() -> Self { pub const fn new() -> Self {
Self { _phantom: PhantomData } Self { state: RefCell::new(0) }
}
fn lock_read(&self) {
critical_section::with(|_| {
let mut state = self.state.borrow_mut();
while *state & WRITER != 0 {
// Spin until the writer releases the lock
}
*state += 1;
});
}
fn unlock_read(&self) {
critical_section::with(|_| {
*self.state.borrow_mut() -= 1;
});
}
fn lock_write(&self) {
critical_section::with(|_| {
let mut state = self.state.borrow_mut();
while *state != 0 {
// Spin until all readers and writers release the lock
}
*state = WRITER;
});
}
fn unlock_write(&self) {
critical_section::with(|_| {
*self.state.borrow_mut() = 0;
});
} }
} }
@ -57,14 +92,24 @@ unsafe impl RawRwLock for CriticalSectionRawRwLock {
const INIT: Self = Self::new(); const INIT: Self = Self::new();
fn read_lock<R>(&self, f: impl FnOnce() -> R) -> R { fn read_lock<R>(&self, f: impl FnOnce() -> R) -> R {
critical_section::with(|_| f()) self.lock_read();
let result = f();
self.unlock_read();
result
} }
fn write_lock<R>(&self, f: impl FnOnce() -> R) -> R { fn write_lock<R>(&self, f: impl FnOnce() -> R) -> R {
critical_section::with(|_| f()) self.lock_write();
let result = f();
self.unlock_write();
result
} }
} }
const WRITER: isize = -1;
// The rest of the file remains unchanged
// ================ // ================
/// A read-write lock that allows borrowing data in the context of a single executor. /// A read-write lock that allows borrowing data in the context of a single executor.

View File

@ -350,7 +350,7 @@ where
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::blocking_rwlock::raw::NoopRawRwLock; use crate::blocking_rwlock::raw::NoopRawRwLock;
use crate::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard}; use crate::rwlock::RwLock;
#[futures_test::test] #[futures_test::test]
async fn read_guard_releases_lock_when_dropped() { async fn read_guard_releases_lock_when_dropped() {