Support the wait queue that allows sleeping

This commit is contained in:
Chuandong Li 2023-07-03 00:29:59 +08:00 committed by Tate, Hongliang Tian
parent 9edcbe743d
commit fba4a9405e
5 changed files with 19 additions and 15 deletions

View File

@ -4,7 +4,7 @@ use super::SpinLock;
use alloc::{collections::VecDeque, sync::Arc}; use alloc::{collections::VecDeque, sync::Arc};
use bitflags::bitflags; use bitflags::bitflags;
use crate::task::schedule; use crate::task::{add_task, current_task, schedule, Task, TaskStatus};
/// A wait queue. /// A wait queue.
/// ///
@ -85,7 +85,6 @@ impl WaitQueue {
} }
} }
#[derive(Debug)]
struct Waiter { struct Waiter {
/// Whether the /// Whether the
is_woken_up: AtomicBool, is_woken_up: AtomicBool,
@ -93,6 +92,8 @@ struct Waiter {
flag: WaiterFlag, flag: WaiterFlag,
/// if the wait condition is ture, then the waiter is finished and can be removed from waitqueue /// if the wait condition is ture, then the waiter is finished and can be removed from waitqueue
wait_finished: AtomicBool, wait_finished: AtomicBool,
/// The `Task` held by the waiter.
task: Arc<Task>,
} }
impl Waiter { impl Waiter {
@ -101,16 +102,18 @@ impl Waiter {
is_woken_up: AtomicBool::new(false), is_woken_up: AtomicBool::new(false),
flag: WaiterFlag::empty(), flag: WaiterFlag::empty(),
wait_finished: AtomicBool::new(false), wait_finished: AtomicBool::new(false),
task: current_task().unwrap(),
} }
} }
/// make self into wait status until be called wake up /// make self into wait status until be called wake up
pub fn wait(&self) { pub fn wait(&self) {
self.is_woken_up.store(false, Ordering::SeqCst); self.is_woken_up.store(false, Ordering::SeqCst);
self.task.inner_exclusive_access().task_status = TaskStatus::Sleeping;
while !self.is_woken_up.load(Ordering::SeqCst) { while !self.is_woken_up.load(Ordering::SeqCst) {
// yield the execution, to allow other task to continue
schedule(); schedule();
} }
self.task.inner_exclusive_access().task_status = TaskStatus::Runnable;
} }
pub fn is_woken_up(&self) -> bool { pub fn is_woken_up(&self) -> bool {
@ -119,6 +122,7 @@ impl Waiter {
pub fn wake_up(&self) { pub fn wake_up(&self) {
self.is_woken_up.store(true, Ordering::SeqCst); self.is_woken_up.store(true, Ordering::SeqCst);
add_task(self.task.clone());
} }
pub fn set_finished(&self) { pub fn set_finished(&self) {

View File

@ -5,6 +5,6 @@ mod scheduler;
#[allow(clippy::module_inception)] #[allow(clippy::module_inception)]
mod task; mod task;
pub use self::processor::schedule; pub use self::processor::{current_task, schedule};
pub use self::scheduler::{set_scheduler, Scheduler}; pub use self::scheduler::{add_task, set_scheduler, Scheduler};
pub use self::task::{Task, TaskAdapter, TaskStatus}; pub use self::task::{Task, TaskAdapter, TaskStatus};

View File

@ -71,8 +71,10 @@ pub fn switch_to_task(next_task: Arc<Task>) {
PROCESSOR.lock().get_idle_task_cx_ptr() PROCESSOR.lock().get_idle_task_cx_ptr()
} else { } else {
current_task = current_task_option.unwrap(); current_task = current_task_option.unwrap();
if current_task.status() != TaskStatus::Exited { if current_task.status() == TaskStatus::Runnable {
GLOBAL_SCHEDULER.lock().enqueue(current_task.clone()); GLOBAL_SCHEDULER
.lock_irq_disabled()
.enqueue(current_task.clone());
} }
&mut current_task.inner_exclusive_access().ctx as *mut TaskContext &mut current_task.inner_exclusive_access().ctx as *mut TaskContext
}; };

View File

@ -1,12 +1,12 @@
use crate::prelude::*; use crate::prelude::*;
use crate::sync::SpinLock;
use crate::task::Task; use crate::task::Task;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use spin::Mutex;
lazy_static! { lazy_static! {
pub(crate) static ref GLOBAL_SCHEDULER: Mutex<GlobalScheduler> = pub(crate) static ref GLOBAL_SCHEDULER: SpinLock<GlobalScheduler> =
Mutex::new(GlobalScheduler { scheduler: None }); SpinLock::new(GlobalScheduler { scheduler: None });
} }
/// A scheduler for tasks. /// A scheduler for tasks.
@ -43,13 +43,13 @@ impl GlobalScheduler {
/// ///
/// This must be called before invoking `Task::spawn`. /// This must be called before invoking `Task::spawn`.
pub fn set_scheduler(scheduler: &'static dyn Scheduler) { pub fn set_scheduler(scheduler: &'static dyn Scheduler) {
GLOBAL_SCHEDULER.lock().scheduler = Some(scheduler); GLOBAL_SCHEDULER.lock_irq_disabled().scheduler = Some(scheduler);
} }
pub fn fetch_task() -> Option<Arc<Task>> { pub fn fetch_task() -> Option<Arc<Task>> {
GLOBAL_SCHEDULER.lock().dequeue() GLOBAL_SCHEDULER.lock_irq_disabled().dequeue()
} }
pub fn add_task(task: Arc<Task>) { pub fn add_task(task: Arc<Task>) {
GLOBAL_SCHEDULER.lock().enqueue(task); GLOBAL_SCHEDULER.lock_irq_disabled().enqueue(task);
} }

View File

@ -216,8 +216,6 @@ impl Task {
pub enum TaskStatus { pub enum TaskStatus {
/// The task is runnable. /// The task is runnable.
Runnable, Runnable,
/// The task is running.
Running,
/// The task is sleeping. /// The task is sleeping.
Sleeping, Sleeping,
/// The task has exited. /// The task has exited.