Skip to content

Commit

Permalink
use Rawlist for wait queue
Browse files Browse the repository at this point in the history
Signed-off-by: guoweikang <[email protected]>
  • Loading branch information
guoweikang committed Oct 24, 2024
1 parent b2e6261 commit 9118688
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 29 deletions.
9 changes: 7 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion modules/axtask/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ kernel_guard = { version = "0.1", optional = true }
crate_interface = { version = "0.1", optional = true }
cpumask = { version = "0.1", optional = true }
scheduler = { git = "https://github.com/arceos-org/scheduler.git", tag = "v0.2.0", optional = true }
linked_list_r4l = { version = "0.2.0" , optional = true }
linked_list_r4l = { git = "https://github.com/arceos-org/linked_list_r4l.git", branch ="guoweikang/add_push_front", optional = true}
#linked_list_r4l = { version = "0.2.0" , optional = true }

[dev-dependencies]
rand = "0.8"
Expand Down
12 changes: 6 additions & 6 deletions modules/axtask/src/run_queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -367,11 +367,7 @@ impl<'a, G: BaseGuard> CurrentRunQueueRef<'a, G> {
/// 2. The caller must ensure that the current task is in the running state.
/// 3. The caller must ensure that the current task is not the idle task.
/// 4. The lock of the wait queue will be released explicitly after current task is pushed into it.
pub fn blocked_resched(
&mut self,
mut wq_guard: WaitQueueGuard,
curr_waiter: Arc<WaitTaskNode>,
) {
pub fn blocked_resched(&mut self, mut wq_guard: WaitQueueGuard, curr_waiter: &WaitTaskNode) {
let curr = &self.current_task;
assert!(curr.is_running());
assert!(!curr.is_idle());
Expand All @@ -384,7 +380,11 @@ impl<'a, G: BaseGuard> CurrentRunQueueRef<'a, G> {
// Mark the task as blocked, this has to be done before adding it to the wait queue
// while holding the lock of the wait queue.
curr.set_state(TaskState::Blocked);
wq_guard.push_back(curr_waiter);
// SAFETY: The waiter was on caller stack, the lifetime ends
// only when the task resumes running.
unsafe {
assert!(wq_guard.push_back(curr_waiter));
}
// Drop the lock of wait queue explictly.
drop(wq_guard);

Expand Down
37 changes: 17 additions & 20 deletions modules/axtask/src/wait_queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use alloc::sync::Arc;

use kernel_guard::{NoOp, NoPreemptIrqSave};
use kspin::{SpinNoIrq, SpinNoIrqGuard};
use linked_list_r4l::{def_node, List};
use linked_list_r4l::{def_node, RawList};

use crate::{current_run_queue, select_run_queue, AxTaskRef};

Expand All @@ -19,8 +19,6 @@ impl WaitTaskNode {
}
}

type Node = Arc<WaitTaskNode>;

/// A queue to store sleeping tasks.
///
/// # Examples
Expand All @@ -44,22 +42,22 @@ type Node = Arc<WaitTaskNode>;
/// assert_eq!(VALUE.load(Ordering::Relaxed), 1);
/// ```
pub struct WaitQueue {
list: SpinNoIrq<List<Node>>,
list: SpinNoIrq<RawList<WaitTaskNode>>,
}

pub(crate) type WaitQueueGuard<'a> = SpinNoIrqGuard<'a, List<Node>>;
pub(crate) type WaitQueueGuard<'a> = SpinNoIrqGuard<'a, RawList<WaitTaskNode>>;

impl WaitQueue {
/// Creates an empty wait queue.
pub const fn new() -> Self {
Self {
list: SpinNoIrq::new(List::new()),
list: SpinNoIrq::new(RawList::new()),
}
}

/// Cancel events by removing the task from the wait queue.
/// If `from_timer_list` is true, try to remove the task from the timer list.
fn cancel_events(&self, waiter: Node, _from_timer_list: bool) {
fn cancel_events(&self, waiter: WaitTaskNode, _from_timer_list: bool) {
// SAFETY:
// Waiter is only defined in the local function scope,
// therefore, it is not possible in other List.
Expand All @@ -71,10 +69,7 @@ impl WaitQueue {
// Just mark task's current timer ticket ID as expired.
#[cfg(feature = "irq")]
if _from_timer_list {
Arc::<WaitTaskNode>::into_inner(waiter)
.expect("into_inner")
.into_inner()
.timer_ticket_expired();
waiter.into_inner().timer_ticket_expired();
// Note:
// this task is still not removed from timer list of target CPU,
// which may cause some redundant timer events because it still needs to
Expand All @@ -86,8 +81,8 @@ impl WaitQueue {
/// Blocks the current task and put it into the wait queue, until other task
/// notifies it.
pub fn wait(&self) {
let waiter = Arc::new(WaitTaskNode::from_current());
current_run_queue::<NoPreemptIrqSave>().blocked_resched(self.list.lock(), waiter.clone());
let waiter = WaitTaskNode::from_current();
current_run_queue::<NoPreemptIrqSave>().blocked_resched(self.list.lock(), &waiter);
self.cancel_events(waiter, false);
}

Expand All @@ -100,14 +95,14 @@ impl WaitQueue {
where
F: Fn() -> bool,
{
let waiter = Arc::new(WaitTaskNode::from_current());
let waiter = WaitTaskNode::from_current();
loop {
let mut rq = current_run_queue::<NoPreemptIrqSave>();
let wq = self.list.lock();
if condition() {
break;
}
rq.blocked_resched(wq, waiter.clone());
rq.blocked_resched(wq, &waiter);
// Preemption may occur here.
}

Expand All @@ -118,7 +113,7 @@ impl WaitQueue {
/// notify it, or the given duration has elapsed.
#[cfg(feature = "irq")]
pub fn wait_timeout(&self, dur: core::time::Duration) -> bool {
let waiter = Arc::new(WaitTaskNode::from_current());
let waiter = WaitTaskNode::from_current();
let mut rq = current_run_queue::<NoPreemptIrqSave>();
let curr = crate::current();
let deadline = axhal::time::wall_time() + dur;
Expand All @@ -129,7 +124,7 @@ impl WaitQueue {
);
crate::timers::set_alarm_wakeup(deadline, curr.clone());

rq.blocked_resched(self.list.lock(), waiter.clone());
rq.blocked_resched(self.list.lock(), &waiter);

let timeout = axhal::time::wall_time() >= deadline;

Expand All @@ -148,7 +143,7 @@ impl WaitQueue {
where
F: Fn() -> bool,
{
let waiter = Arc::new(WaitTaskNode::from_current());
let waiter = WaitTaskNode::from_current();
let curr = crate::current();
let deadline = axhal::time::wall_time() + dur;
debug!(
Expand All @@ -169,7 +164,7 @@ impl WaitQueue {
timeout = false;
break;
}
rq.blocked_resched(wq, waiter.clone());
rq.blocked_resched(wq, &waiter);
// Preemption may occur here.
}

Expand All @@ -185,7 +180,9 @@ impl WaitQueue {
pub fn notify_one(&self, resched: bool) -> bool {
let mut wq = self.list.lock();
if let Some(waiter) = wq.pop_front() {
unblock_one_task(waiter.inner().clone(), resched);
// SAFETY: waiter NonNull<T> is valid created by block
let waiter_ref = unsafe { waiter.as_ref() };
unblock_one_task(waiter_ref.inner().clone(), resched);
true
} else {
false
Expand Down

0 comments on commit 9118688

Please sign in to comment.