diff --git a/kernel/libs/xarray/src/cursor.rs b/kernel/libs/xarray/src/cursor.rs index 524ee9e3..1ba25989 100644 --- a/kernel/libs/xarray/src/cursor.rs +++ b/kernel/libs/xarray/src/cursor.rs @@ -4,8 +4,8 @@ use alloc::sync::Arc; use core::ops::{Deref, DerefMut}; use ostd::{ - sync::{non_null::NonNullPtr, SpinGuardian}, - task::{atomic_mode::AsAtomicModeGuard, DisabledPreemptGuard}, + sync::{non_null::NonNullPtr, SpinGuardian, SpinLockGuard}, + task::atomic_mode::{AsAtomicModeGuard, InAtomicMode}, util::Either, }; @@ -98,7 +98,7 @@ impl<'a, P: NonNullPtr + Send + Sync> CursorState<'a, P> { /// point by performing a [`Cursor::reset`] operation. /// /// The typical way to obtain a `Cursor` instance is to call [`XArray::cursor`]. -pub struct Cursor<'a, P, M = NoneMark, G = DisabledPreemptGuard> +pub struct Cursor<'a, P, M = NoneMark> where P: NonNullPtr + Send + Sync, { @@ -107,19 +107,22 @@ where /// The target index of the cursor. index: u64, /// The atomic-mode guard that protects cursor operations. - guard: &'a G, + guard: &'a dyn InAtomicMode, /// The state of the cursor. state: CursorState<'a, P>, } -impl<'a, P: NonNullPtr + Send + Sync, M, G: AsAtomicModeGuard> Cursor<'a, P, M, G> { +impl<'a, P: NonNullPtr + Send + Sync, M> Cursor<'a, P, M> { /// Creates a `Cursor` to perform read-related operations in the `XArray`. - pub(super) fn new(xa: &'a XArray, guard: &'a G, index: u64) -> Self { - let _ = guard.as_atomic_mode_guard(); + pub(super) fn new( + xa: &'a XArray, + guard: &'a G, + index: u64, + ) -> Self { Self { xa, index, - guard, + guard: guard.as_atomic_mode_guard(), state: CursorState::Inactive, } } @@ -229,7 +232,7 @@ impl<'a, P: NonNullPtr + Send + Sync, M, G: AsAtomicModeGuard> Cursor<'a, P, M, } } -impl, G: AsAtomicModeGuard> Cursor<'_, P, M, G> { +impl> Cursor<'_, P, M> { /// Checks whether the target item is marked with the input `mark`. /// /// If the target item does not exist, this method will also return false. @@ -253,16 +256,26 @@ impl, G: AsAtomicModeGuard> Cursor<' /// The typical way to obtain a `CursorMut` instance is to call [`LockedXArray::cursor_mut`]. /// /// [`LockedXArray::cursor_mut`]: super::LockedXArray::cursor_mut -pub struct CursorMut<'a, P, M, G>(Cursor<'a, P, M, XLockGuard<'a, G>>) +pub struct CursorMut<'a, P, M>(Cursor<'a, P, M>) where - P: NonNullPtr + Send + Sync, - G: SpinGuardian; + P: NonNullPtr + Send + Sync; -impl<'a, P: NonNullPtr + Send + Sync, M, G: SpinGuardian> CursorMut<'a, P, M, G> { - pub(super) fn new(xa: &'a XArray, guard: &'a XLockGuard<'a, G>, index: u64) -> Self { +impl<'a, P: NonNullPtr + Send + Sync, M> CursorMut<'a, P, M> { + /// Creates a `CursorMut` to perform read- and write-related operations in the `XArray`. + pub(super) fn new( + xa: &'a XArray, + guard: &'a SpinLockGuard<'a, (), G>, + index: u64, + ) -> Self { Self(Cursor::new(xa, guard, index)) } + /// Returns an `XLockGuard` that marks the `XArray` is locked. + fn lock_guard(&self) -> XLockGuard { + // Having a `CursorMut` means that the `XArray` is locked. + XLockGuard(self.guard) + } + /// Increases the height of the `XArray` so that the `index`-th element can be stored. fn reserve(&self, index: u64) { if self.xa.head.read_with(self.guard).is_none() { @@ -280,7 +293,7 @@ impl<'a, P: NonNullPtr + Send + Sync, M, G: SpinGuardian> CursorMut<'a, P, M, G> } let new_head = Arc::new(XNode::new_root(height.go_root())); - new_head.set_entry(self.guard, 0, Some(Either::Left(head.clone()))); + new_head.set_entry(self.lock_guard(), 0, Some(Either::Left(head.clone()))); self.xa.head.update(Some(new_head)); } @@ -317,7 +330,7 @@ impl<'a, P: NonNullPtr + Send + Sync, M, G: SpinGuardian> CursorMut<'a, P, M, G> { let new_node = XNode::new(current_node.height().go_leaf(), operation_offset); let new_entry = Either::Left(Arc::new(new_node)); - current_node.set_entry(self.guard, operation_offset, Some(new_entry)); + current_node.set_entry(self.lock_guard(), operation_offset, Some(new_entry)); } let next_node = current_node @@ -337,7 +350,11 @@ impl<'a, P: NonNullPtr + Send + Sync, M, G: SpinGuardian> CursorMut<'a, P, M, G> pub fn store(&mut self, item: P) { self.expand_and_traverse_to_target(); let (node, operation_offset) = self.state.as_node().unwrap(); - node.set_entry(self.guard, operation_offset, Some(Either::Right(item))); + node.set_entry( + self.lock_guard(), + operation_offset, + Some(Either::Right(item)), + ); } /// Removes the item at the target index. @@ -352,7 +369,7 @@ impl<'a, P: NonNullPtr + Send + Sync, M, G: SpinGuardian> CursorMut<'a, P, M, G> .deref_target() .entry_with(self.guard, off) .and_then(|entry| entry.right()); - node.set_entry(self.guard, off, None); + node.set_entry(self.lock_guard(), off, None); res }) } @@ -362,7 +379,7 @@ impl<'a, P: NonNullPtr + Send + Sync, M, G: SpinGuardian> CursorMut<'a, P, M, G> #[derive(Debug)] pub struct SetMarkError; -impl, G: SpinGuardian> CursorMut<'_, P, M, G> { +impl> CursorMut<'_, P, M> { /// Sets the input `mark` for the item at the target index. /// /// # Errors @@ -378,7 +395,7 @@ impl, G: SpinGuardian> CursorMut<'_, }) .map(|(node, off)| { let mark_index = mark.into().index(); - node.set_mark(self.guard, off, mark_index); + node.set_mark(self.lock_guard(), off, mark_index); }) .ok_or(SetMarkError) } @@ -398,21 +415,21 @@ impl, G: SpinGuardian> CursorMut<'_, }) .map(|(node, off)| { let mark_index = mark.into().index(); - node.unset_mark(self.guard, off, mark_index); + node.unset_mark(self.lock_guard(), off, mark_index); }) .ok_or(SetMarkError) } } -impl<'a, P: NonNullPtr + Send + Sync, M, G: SpinGuardian> Deref for CursorMut<'a, P, M, G> { - type Target = Cursor<'a, P, M, XLockGuard<'a, G>>; +impl<'a, P: NonNullPtr + Send + Sync, M> Deref for CursorMut<'a, P, M> { + type Target = Cursor<'a, P, M>; fn deref(&self) -> &Self::Target { &self.0 } } -impl DerefMut for CursorMut<'_, P, M, G> { +impl DerefMut for CursorMut<'_, P, M> { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } diff --git a/kernel/libs/xarray/src/lib.rs b/kernel/libs/xarray/src/lib.rs index 3ad62f1d..155b84ac 100644 --- a/kernel/libs/xarray/src/lib.rs +++ b/kernel/libs/xarray/src/lib.rs @@ -62,7 +62,7 @@ use ostd::{ non_null::NonNullPtr, LocalIrqDisabled, PreemptDisabled, RcuOption, SpinGuardian, SpinLock, SpinLockGuard, }, - task::atomic_mode::AsAtomicModeGuard, + task::atomic_mode::{AsAtomicModeGuard, InAtomicMode}, }; pub use range::Range; @@ -112,8 +112,9 @@ where _marker: PhantomData, } -/// A type that represents the spinlock guard used in [`XArray`]. -pub type XLockGuard<'a, G> = SpinLockGuard<'a, (), G>; +/// A type that marks the [`XArray`] is locked. +#[derive(Clone, Copy)] +struct XLockGuard<'a>(&'a dyn InAtomicMode); impl Default for XArray { fn default() -> Self { @@ -154,7 +155,7 @@ impl XArray { &'a self, guard: &'a G, index: u64, - ) -> Cursor<'a, P, M, G> { + ) -> Cursor<'a, P, M> { Cursor::new(self, guard, index) } @@ -163,7 +164,7 @@ impl XArray { &'a self, guard: &'a G, range: core::ops::Range, - ) -> Range<'a, P, M, G> { + ) -> Range<'a, P, M> { let cursor = self.cursor(guard, range.start); Range::new(cursor, range.end) } @@ -206,15 +207,16 @@ impl LockedXArray<'_, P, M, G> /// Clears the corresponding [`XArray`]. pub fn clear(&mut self) { if let Some(head) = self.xa.head.read_with(&self.guard) { - head.clear_parent(&self.guard); + // Having a `LockedXArray` means that the `XArray` is locked. + head.clear_parent(XLockGuard(self.guard.as_atomic_mode_guard())); } self.xa.head.update(None); } /// Creates a [`CursorMut`] to perform read- and write-related operations. - pub fn cursor_mut(&mut self, index: u64) -> cursor::CursorMut<'_, P, M, G> { - cursor::CursorMut::new(self.xa, &self.guard, index) + pub fn cursor_mut(&mut self, index: u64) -> CursorMut<'_, P, M> { + CursorMut::new(self.xa, &self.guard, index) } /// Stores the provided item at the target index. @@ -232,12 +234,12 @@ impl LockedXArray<'_, P, M, G> } /// Creates a [`Cursor`] to perform read-related operations. - pub fn cursor(&self, index: u64) -> Cursor<'_, P, M, XLockGuard> { + pub fn cursor(&self, index: u64) -> Cursor<'_, P, M> { Cursor::new(self.xa, &self.guard, index) } /// Creates a [`Range`] to immutably iterated over the specified `range`. - pub fn range(&self, range: core::ops::Range) -> Range<'_, P, M, XLockGuard> { + pub fn range(&self, range: core::ops::Range) -> Range<'_, P, M> { let cursor = self.cursor(range.start); Range::new(cursor, range.end) } diff --git a/kernel/libs/xarray/src/mark.rs b/kernel/libs/xarray/src/mark.rs index bbebf214..8d849410 100644 --- a/kernel/libs/xarray/src/mark.rs +++ b/kernel/libs/xarray/src/mark.rs @@ -2,8 +2,6 @@ use core::sync::atomic::{AtomicU64, Ordering}; -use ostd::sync::SpinGuardian; - use crate::XLockGuard; /// A mark used to indicate which slots in an [`XNode`] contain items that have been marked. @@ -28,7 +26,7 @@ impl Mark { Self::new(0) } - pub fn update(&self, offset: u8, set: bool, _guard: &XLockGuard) -> bool { + pub fn update(&self, _guard: XLockGuard, offset: u8, set: bool) -> bool { let old_val = self.inner.load(Ordering::Acquire); let new_val = if set { old_val | (1 << offset as u64) diff --git a/kernel/libs/xarray/src/node.rs b/kernel/libs/xarray/src/node.rs index e695aa04..20040056 100644 --- a/kernel/libs/xarray/src/node.rs +++ b/kernel/libs/xarray/src/node.rs @@ -7,8 +7,8 @@ use core::{ }; use ostd::{ - sync::{non_null::NonNullPtr, RcuOption, SpinGuardian}, - task::atomic_mode::AsAtomicModeGuard, + sync::{non_null::NonNullPtr, RcuOption}, + task::atomic_mode::InAtomicMode, util::Either, }; @@ -156,7 +156,7 @@ impl XNode

{ self.height } - pub fn parent<'a>(&'a self, guard: &'a dyn AsAtomicModeGuard) -> Option> { + pub fn parent<'a>(&'a self, guard: &'a dyn InAtomicMode) -> Option> { let parent = self.parent.read_with(guard)?; Some(parent) } @@ -167,7 +167,7 @@ impl XNode

{ pub fn entry_with<'a>( &'a self, - guard: &'a dyn AsAtomicModeGuard, + guard: &'a dyn InAtomicMode, offset: u8, ) -> Option> { self.slots[offset as usize].read_with(guard) @@ -188,17 +188,17 @@ impl XNode

{ impl XNode

{ /// Sets the parent pointer of this node to the given `parent`. - fn set_parent(&self, _guard: &XLockGuard, parent: NodeEntry

) { + fn set_parent(&self, _guard: XLockGuard, parent: NodeEntry

) { self.parent.update(Some(parent)); } /// Clears the parent pointers of this node and all its descendant nodes. /// /// This method should be invoked when the node is being removed from the tree. - pub fn clear_parent(&self, guard: &XLockGuard) { + pub fn clear_parent(&self, guard: XLockGuard) { self.parent.update(None); for child in self.slots.iter() { - if let Some(node) = child.read_with(guard).and_then(|entry| entry.left()) { + if let Some(node) = child.read_with(guard.0).and_then(|entry| entry.left()) { node.clear_parent(guard); } } @@ -211,13 +211,8 @@ impl XNode

{ /// updated according to whether the new node contains marked items. /// /// This method will also propagate the updated marks to the ancestors. - pub fn set_entry( - self: &Arc, - guard: &XLockGuard, - offset: u8, - entry: Option>, - ) { - let old_entry = self.slots[offset as usize].read_with(guard); + pub fn set_entry(self: &Arc, guard: XLockGuard, offset: u8, entry: Option>) { + let old_entry = self.slots[offset as usize].read_with(guard.0); if let Some(node) = old_entry.and_then(|entry| entry.left()) { node.clear_parent(guard); } @@ -245,8 +240,8 @@ impl XNode

{ /// /// This method will also update the marks on the ancestors of this node /// if necessary to ensure that the marks on the ancestors are up to date. - pub fn set_mark(&self, guard: &XLockGuard, offset: u8, mark: usize) { - let changed = self.marks[mark].update(offset, true, guard); + pub fn set_mark(&self, guard: XLockGuard, offset: u8, mark: usize) { + let changed = self.marks[mark].update(guard, offset, true); if changed { self.propagate_mark(guard, mark); } @@ -256,8 +251,8 @@ impl XNode

{ /// /// This method will also update the marks on the ancestors of this node /// if necessary to ensure that the marks on the ancestors are up to date. - pub fn unset_mark(&self, guard: &XLockGuard, offset: u8, mark: usize) { - let changed = self.marks[mark].update(offset, false, guard); + pub fn unset_mark(&self, guard: XLockGuard, offset: u8, mark: usize) { + let changed = self.marks[mark].update(guard, offset, false); if changed { self.propagate_mark(guard, mark); } @@ -271,14 +266,14 @@ impl XNode

{ /// /// This method will also update the marks on the ancestors of this node /// if necessary to ensure that the marks on the ancestors are up to date. - fn update_mark(&self, guard: &XLockGuard, offset: u8) { - let entry = self.slots[offset as usize].read_with(guard); + fn update_mark(&self, guard: XLockGuard, offset: u8) { + let entry = self.slots[offset as usize].read_with(guard.0); let Some(node) = entry.and_then(|entry| entry.left()) else { return; }; for i in 0..NUM_MARKS { - let changed = self.marks[i].update(offset, !node.is_mark_clear(i), guard); + let changed = self.marks[i].update(guard, offset, !node.is_mark_clear(i)); if changed { self.propagate_mark(guard, i); } @@ -289,13 +284,13 @@ impl XNode

{ /// /// This method must be called after the marks are updated to ensure that the marks on the /// ancestors are up to date. - fn propagate_mark(&self, guard: &XLockGuard, mark: usize) { - let Some(parent) = self.parent(guard) else { + fn propagate_mark(&self, guard: XLockGuard, mark: usize) { + let Some(parent) = self.parent(guard.0) else { return; }; let changed = - parent.marks[mark].update(self.offset_in_parent, !self.is_mark_clear(mark), guard); + parent.marks[mark].update(guard, self.offset_in_parent, !self.is_mark_clear(mark)); if changed { parent.propagate_mark(guard, mark); } diff --git a/kernel/libs/xarray/src/range.rs b/kernel/libs/xarray/src/range.rs index 64e25460..b97c9209 100644 --- a/kernel/libs/xarray/src/range.rs +++ b/kernel/libs/xarray/src/range.rs @@ -1,9 +1,6 @@ // SPDX-License-Identifier: MPL-2.0 -use ostd::{ - sync::non_null::NonNullPtr, - task::{atomic_mode::AsAtomicModeGuard, DisabledPreemptGuard}, -}; +use ostd::sync::non_null::NonNullPtr; use crate::{cursor::Cursor, mark::NoneMark}; @@ -13,23 +10,21 @@ use crate::{cursor::Cursor, mark::NoneMark}; /// /// [`XArray`]: super::XArray /// [`XArray::range`]: super::XArray::range -pub struct Range<'a, P, M = NoneMark, G = DisabledPreemptGuard> +pub struct Range<'a, P, M = NoneMark> where P: NonNullPtr + Send + Sync, { - cursor: Cursor<'a, P, M, G>, + cursor: Cursor<'a, P, M>, end: u64, } -impl<'a, P: NonNullPtr + Send + Sync, M, G: AsAtomicModeGuard> Range<'a, P, M, G> { - pub(super) fn new(cursor: Cursor<'a, P, M, G>, end: u64) -> Self { +impl<'a, P: NonNullPtr + Send + Sync, M> Range<'a, P, M> { + pub(super) fn new(cursor: Cursor<'a, P, M>, end: u64) -> Self { Range { cursor, end } } } -impl<'a, P: NonNullPtr + Send + Sync, M, G: AsAtomicModeGuard> core::iter::Iterator - for Range<'a, P, M, G> -{ +impl<'a, P: NonNullPtr + Send + Sync, M> core::iter::Iterator for Range<'a, P, M> { type Item = (u64, P::Ref<'a>); fn next(&mut self) -> Option {