aboutsummaryrefslogtreecommitdiff
path: root/embassy-sync/src
diff options
context:
space:
mode:
authorAlix ANNERAUD <[email protected]>2025-02-28 23:26:59 +0100
committerAlix ANNERAUD <[email protected]>2025-02-28 23:26:59 +0100
commit9cbdc9f11d8e0b857ed9bf483120da03ed3a878c (patch)
tree975b2d7cfd7258d15063d40489ff608407df6ab7 /embassy-sync/src
parent55684782258b0241ede93ac6e43a07a3075ad028 (diff)
Implement read-write lock methods in CriticalSectionRawRwLock and update tests
Diffstat (limited to 'embassy-sync/src')
-rw-r--r--embassy-sync/src/blocking_rwlock/raw.rs57
-rw-r--r--embassy-sync/src/rwlock.rs2
2 files changed, 52 insertions, 7 deletions
diff --git a/embassy-sync/src/blocking_rwlock/raw.rs b/embassy-sync/src/blocking_rwlock/raw.rs
index 7725edfa5..dc25e6305 100644
--- a/embassy-sync/src/blocking_rwlock/raw.rs
+++ b/embassy-sync/src/blocking_rwlock/raw.rs
@@ -1,7 +1,7 @@
1//! Read-Write Lock primitives. 1//! Read-Write Lock primitives.
2//! 2//!
3//! This module provides a trait for read-write locks that can be used in different contexts. 3//! This module provides a trait for read-write locks that can be used in different contexts.
4use core::marker::PhantomData; 4use core::{cell::RefCell, marker::PhantomData};
5 5
6/// Raw read-write lock trait. 6/// Raw read-write lock trait.
7/// 7///
@@ -41,15 +41,50 @@ pub unsafe trait RawRwLock {
41/// 41///
42/// This read-write lock is safe to share between different executors and interrupts. 42/// This read-write lock is safe to share between different executors and interrupts.
43pub struct CriticalSectionRawRwLock { 43pub struct CriticalSectionRawRwLock {
44 _phantom: PhantomData<()>, 44 state: RefCell<isize>,
45} 45}
46
46unsafe impl Send for CriticalSectionRawRwLock {} 47unsafe impl Send for CriticalSectionRawRwLock {}
47unsafe impl Sync for CriticalSectionRawRwLock {} 48unsafe impl Sync for CriticalSectionRawRwLock {}
48 49
49impl CriticalSectionRawRwLock { 50impl CriticalSectionRawRwLock {
50 /// Create a new `CriticalSectionRawRwLock`. 51 /// Creates a new [`CriticalSectionRawRwLock`].
51 pub const fn new() -> Self { 52 pub const fn new() -> Self {
52 Self { _phantom: PhantomData } 53 Self { state: RefCell::new(0) }
54 }
55
56 fn lock_read(&self) {
57 critical_section::with(|_| {
58 let mut state = self.state.borrow_mut();
59
60 while *state & WRITER != 0 {
61 // Spin until the writer releases the lock
62 }
63 *state += 1;
64 });
65 }
66
67 fn unlock_read(&self) {
68 critical_section::with(|_| {
69 *self.state.borrow_mut() -= 1;
70 });
71 }
72
73 fn lock_write(&self) {
74 critical_section::with(|_| {
75 let mut state = self.state.borrow_mut();
76
77 while *state != 0 {
78 // Spin until all readers and writers release the lock
79 }
80 *state = WRITER;
81 });
82 }
83
84 fn unlock_write(&self) {
85 critical_section::with(|_| {
86 *self.state.borrow_mut() = 0;
87 });
53 } 88 }
54} 89}
55 90
@@ -57,14 +92,24 @@ unsafe impl RawRwLock for CriticalSectionRawRwLock {
57 const INIT: Self = Self::new(); 92 const INIT: Self = Self::new();
58 93
59 fn read_lock<R>(&self, f: impl FnOnce() -> R) -> R { 94 fn read_lock<R>(&self, f: impl FnOnce() -> R) -> R {
60 critical_section::with(|_| f()) 95 self.lock_read();
96 let result = f();
97 self.unlock_read();
98 result
61 } 99 }
62 100
63 fn write_lock<R>(&self, f: impl FnOnce() -> R) -> R { 101 fn write_lock<R>(&self, f: impl FnOnce() -> R) -> R {
64 critical_section::with(|_| f()) 102 self.lock_write();
103 let result = f();
104 self.unlock_write();
105 result
65 } 106 }
66} 107}
67 108
109const WRITER: isize = -1;
110
111// The rest of the file remains unchanged
112
68// ================ 113// ================
69 114
70/// A read-write lock that allows borrowing data in the context of a single executor. 115/// A read-write lock that allows borrowing data in the context of a single executor.
diff --git a/embassy-sync/src/rwlock.rs b/embassy-sync/src/rwlock.rs
index 9fa61ee56..0ad5d5864 100644
--- a/embassy-sync/src/rwlock.rs
+++ b/embassy-sync/src/rwlock.rs
@@ -350,7 +350,7 @@ where
350#[cfg(test)] 350#[cfg(test)]
351mod tests { 351mod tests {
352 use crate::blocking_rwlock::raw::NoopRawRwLock; 352 use crate::blocking_rwlock::raw::NoopRawRwLock;
353 use crate::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard}; 353 use crate::rwlock::RwLock;
354 354
355 #[futures_test::test] 355 #[futures_test::test]
356 async fn read_guard_releases_lock_when_dropped() { 356 async fn read_guard_releases_lock_when_dropped() {