aboutsummaryrefslogtreecommitdiff
path: root/embassy-sync/src
diff options
context:
space:
mode:
authorAlix ANNERAUD <[email protected]>2025-02-28 16:22:16 +0100
committerAlix ANNERAUD <[email protected]>2025-02-28 16:22:16 +0100
commit114cfdd86b19640ca109488fb960020de673ec57 (patch)
tree73a24d65210176f6d7e0de06ca1405fa6008e8a6 /embassy-sync/src
parent6904b0cc6409aead1a2f49f4c821dffd7fd61ce4 (diff)
Add `RawRwLock` trait and `RawRwLockImpl` struct implementation
* Implement `RawRwLock` trait with methods for read and write locking * Implement `RawRwLockImpl` struct with atomic state and waker * Implement `RawRwLockImpl::lock_read`, `RawRwLockImpl::try_lock_read`, and `RawRwLockImpl::unlock_read` methods * Implement `RawRwLockImpl::lock_write`, `RawRwLockImpl::try_lock_write`, and `RawRwLockImpl::unlock_write` methods
Diffstat (limited to 'embassy-sync/src')
-rw-r--r--embassy-sync/src/blocking_mutex/raw_rwlock.rs86
-rw-r--r--embassy-sync/src/raw_rwlock.rs86
2 files changed, 86 insertions, 86 deletions
diff --git a/embassy-sync/src/blocking_mutex/raw_rwlock.rs b/embassy-sync/src/blocking_mutex/raw_rwlock.rs
new file mode 100644
index 000000000..de4bd1dc5
--- /dev/null
+++ b/embassy-sync/src/blocking_mutex/raw_rwlock.rs
@@ -0,0 +1,86 @@
1use core::sync::atomic::{AtomicUsize, Ordering};
2use core::task::Waker;
3use core::cell::UnsafeCell;
4
5pub trait RawRwLock {
6 fn lock_read(&self);
7 fn try_lock_read(&self) -> bool;
8 fn unlock_read(&self);
9 fn lock_write(&self);
10 fn try_lock_write(&self) -> bool;
11 fn unlock_write(&self);
12}
13
14pub struct RawRwLockImpl {
15 state: AtomicUsize,
16 waker: UnsafeCell<Option<Waker>>,
17}
18
19impl RawRwLockImpl {
20 pub const fn new() -> Self {
21 Self {
22 state: AtomicUsize::new(0),
23 waker: UnsafeCell::new(None),
24 }
25 }
26}
27
28unsafe impl Send for RawRwLockImpl {}
29unsafe impl Sync for RawRwLockImpl {}
30
31impl RawRwLock for RawRwLockImpl {
32 fn lock_read(&self) {
33 loop {
34 let state = self.state.load(Ordering::Acquire);
35 if state & 1 == 0 {
36 if self.state.compare_and_swap(state, state + 2, Ordering::AcqRel) == state {
37 break;
38 }
39 }
40 }
41 }
42
43 fn try_lock_read(&self) -> bool {
44 let state = self.state.load(Ordering::Acquire);
45 if state & 1 == 0 {
46 if self.state.compare_and_swap(state, state + 2, Ordering::AcqRel) == state {
47 return true;
48 }
49 }
50 false
51 }
52
53 fn unlock_read(&self) {
54 self.state.fetch_sub(2, Ordering::Release);
55 if self.state.load(Ordering::Acquire) == 0 {
56 if let Some(waker) = unsafe { &*self.waker.get() } {
57 waker.wake_by_ref();
58 }
59 }
60 }
61
62 fn lock_write(&self) {
63 loop {
64 let state = self.state.load(Ordering::Acquire);
65 if state == 0 {
66 if self.state.compare_and_swap(0, 1, Ordering::AcqRel) == 0 {
67 break;
68 }
69 }
70 }
71 }
72
73 fn try_lock_write(&self) -> bool {
74 if self.state.compare_and_swap(0, 1, Ordering::AcqRel) == 0 {
75 return true;
76 }
77 false
78 }
79
80 fn unlock_write(&self) {
81 self.state.store(0, Ordering::Release);
82 if let Some(waker) = unsafe { &*self.waker.get() } {
83 waker.wake_by_ref();
84 }
85 }
86}
diff --git a/embassy-sync/src/raw_rwlock.rs b/embassy-sync/src/raw_rwlock.rs
index de4bd1dc5..e69de29bb 100644
--- a/embassy-sync/src/raw_rwlock.rs
+++ b/embassy-sync/src/raw_rwlock.rs
@@ -1,86 +0,0 @@
1use core::sync::atomic::{AtomicUsize, Ordering};
2use core::task::Waker;
3use core::cell::UnsafeCell;
4
5pub trait RawRwLock {
6 fn lock_read(&self);
7 fn try_lock_read(&self) -> bool;
8 fn unlock_read(&self);
9 fn lock_write(&self);
10 fn try_lock_write(&self) -> bool;
11 fn unlock_write(&self);
12}
13
14pub struct RawRwLockImpl {
15 state: AtomicUsize,
16 waker: UnsafeCell<Option<Waker>>,
17}
18
19impl RawRwLockImpl {
20 pub const fn new() -> Self {
21 Self {
22 state: AtomicUsize::new(0),
23 waker: UnsafeCell::new(None),
24 }
25 }
26}
27
28unsafe impl Send for RawRwLockImpl {}
29unsafe impl Sync for RawRwLockImpl {}
30
31impl RawRwLock for RawRwLockImpl {
32 fn lock_read(&self) {
33 loop {
34 let state = self.state.load(Ordering::Acquire);
35 if state & 1 == 0 {
36 if self.state.compare_and_swap(state, state + 2, Ordering::AcqRel) == state {
37 break;
38 }
39 }
40 }
41 }
42
43 fn try_lock_read(&self) -> bool {
44 let state = self.state.load(Ordering::Acquire);
45 if state & 1 == 0 {
46 if self.state.compare_and_swap(state, state + 2, Ordering::AcqRel) == state {
47 return true;
48 }
49 }
50 false
51 }
52
53 fn unlock_read(&self) {
54 self.state.fetch_sub(2, Ordering::Release);
55 if self.state.load(Ordering::Acquire) == 0 {
56 if let Some(waker) = unsafe { &*self.waker.get() } {
57 waker.wake_by_ref();
58 }
59 }
60 }
61
62 fn lock_write(&self) {
63 loop {
64 let state = self.state.load(Ordering::Acquire);
65 if state == 0 {
66 if self.state.compare_and_swap(0, 1, Ordering::AcqRel) == 0 {
67 break;
68 }
69 }
70 }
71 }
72
73 fn try_lock_write(&self) -> bool {
74 if self.state.compare_and_swap(0, 1, Ordering::AcqRel) == 0 {
75 return true;
76 }
77 false
78 }
79
80 fn unlock_write(&self) {
81 self.state.store(0, Ordering::Release);
82 if let Some(waker) = unsafe { &*self.waker.get() } {
83 waker.wake_by_ref();
84 }
85 }
86}