mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-12 06:46:48 +00:00
Support the wait queue that allows sleeping
This commit is contained in:
parent
9edcbe743d
commit
fba4a9405e
@ -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) {
|
||||||
|
@ -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};
|
||||||
|
@ -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
|
||||||
};
|
};
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user