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 {