Change design of sleeping state
This commit is contained in:
parent
4d583f52a2
commit
7bae22b118
|
@ -16,6 +16,8 @@ pub trait Scheduler<T: Clone + PartialEq> {
|
||||||
fn next_task(&mut self) -> Option<T>;
|
fn next_task(&mut self) -> Option<T>;
|
||||||
/// 获取正在运行的任务,中断发生时,将保存这个任务的上下文
|
/// 获取正在运行的任务,中断发生时,将保存这个任务的上下文
|
||||||
fn current_task(&self) -> Option<T>;
|
fn current_task(&self) -> Option<T>;
|
||||||
|
/// 查找一个任务
|
||||||
|
fn find_first_task_mut(&mut self, p: impl Fn(&T) -> bool) -> Option<&mut T>;
|
||||||
/// 移除一个任务
|
/// 移除一个任务
|
||||||
fn remove_task(&mut self, task: &T);
|
fn remove_task(&mut self, task: &T);
|
||||||
/// 设置任务的优先级
|
/// 设置任务的优先级
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
//!
|
//!
|
||||||
|
|
||||||
use super::Scheduler;
|
use super::Scheduler;
|
||||||
use core::mem::MaybeUninit;
|
use core::{marker::PhantomData, mem::MaybeUninit};
|
||||||
use core::ptr;
|
use core::ptr;
|
||||||
|
|
||||||
/// 先进先出轮转任务调度器
|
/// 先进先出轮转任务调度器
|
||||||
|
@ -46,6 +46,9 @@ impl<T: Clone + PartialEq, const N: usize> Scheduler<T> for RingFifoScheduler<T,
|
||||||
fn current_task(&self) -> Option<T> {
|
fn current_task(&self) -> Option<T> {
|
||||||
self.current.clone()
|
self.current.clone()
|
||||||
}
|
}
|
||||||
|
fn find_first_task_mut(&mut self, p: impl Fn(&T) -> bool) -> Option<&mut T> {
|
||||||
|
self.ring.iter_mut().find(|t| p(t))
|
||||||
|
}
|
||||||
fn remove_task(&mut self, task: &T) {
|
fn remove_task(&mut self, task: &T) {
|
||||||
// 移除相应的线程并且确认恰移除一个线程
|
// 移除相应的线程并且确认恰移除一个线程
|
||||||
drop(task);
|
drop(task);
|
||||||
|
@ -107,40 +110,37 @@ impl<T, const N: usize> RingQueue<T, N> {
|
||||||
Some(unsafe { &*self.elem[self.front].as_ptr() })
|
Some(unsafe { &*self.elem[self.front].as_ptr() })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 如果用到这个函数,取消注释
|
pub fn iter_mut(&mut self) -> IterMut<'_, T, N> {
|
||||||
// pub fn iter(&self) -> Iter<'_, T, N> {
|
IterMut {
|
||||||
// let mut elem = [&self.elem[0]; N];
|
ptr: &mut self.elem as *mut [MaybeUninit<T>; N] as *mut [T; N],
|
||||||
// for i in 0..self.elem.len() {
|
front: self.front,
|
||||||
// elem[i] = &self.elem[i];
|
tail: self.tail,
|
||||||
// }
|
_marker: PhantomData
|
||||||
// Iter {
|
}
|
||||||
// elem,
|
}
|
||||||
// front: self.front,
|
|
||||||
// tail: self.tail
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub struct Iter<'a, T: 'a, const N: usize> {
|
pub struct IterMut<'a, T: 'a, const N: usize> {
|
||||||
// elem: [&'a MaybeUninit<T>; N],
|
ptr: *mut [T; N],
|
||||||
// front: usize,
|
front: usize,
|
||||||
// tail: usize
|
tail: usize,
|
||||||
// }
|
_marker: PhantomData<&'a mut T>
|
||||||
|
}
|
||||||
|
|
||||||
// // TODO: 这里有不确定 Unsafe 代码,需检查正确性
|
// TODO: 这里有不确定 Unsafe 代码,需检查正确性
|
||||||
// impl<'a, T, const N: usize> Iterator for Iter<'a, T, N> {
|
impl<'a, T, const N: usize> Iterator for IterMut<'a, T, N> {
|
||||||
// type Item = &'a T;
|
type Item = &'a mut T;
|
||||||
// fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
// if self.tail == self.front {
|
if self.tail == self.front {
|
||||||
// // is empty
|
// is empty
|
||||||
// None
|
None
|
||||||
// } else {
|
} else {
|
||||||
// let value = unsafe { self.elem[self.front].assume_init_ref() };
|
let value = unsafe { &mut (*(self.ptr))[self.front] };
|
||||||
// self.front = self.front.wrapping_add(1);
|
self.front = self.front.wrapping_add(1);
|
||||||
// if self.front > N || self.front == 0 {
|
if self.front > N || self.front == 0 {
|
||||||
// self.front = self.front.wrapping_sub(N);
|
self.front = self.front.wrapping_sub(N);
|
||||||
// }
|
}
|
||||||
// Some(value)
|
Some(value)
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
|
@ -22,8 +22,8 @@ mod syscall;
|
||||||
use buddy_system_allocator::LockedHeap;
|
use buddy_system_allocator::LockedHeap;
|
||||||
use core::{mem::MaybeUninit, ptr::NonNull};
|
use core::{mem::MaybeUninit, ptr::NonNull};
|
||||||
use crate::task::{
|
use crate::task::{
|
||||||
SharedTaskHandle, TaskResult, TaskRepr, SharedScheduler, SHARED_SCHEDULER,
|
TaskResult, TaskRepr, TaskState, SharedScheduler, SHARED_SCHEDULER,
|
||||||
shared_add_task, shared_peek_task, shared_delete_task,
|
shared_add_task, shared_peek_task, shared_delete_task, shared_set_task_state,
|
||||||
};
|
};
|
||||||
use crate::mm::AddressSpaceId;
|
use crate::mm::AddressSpaceId;
|
||||||
|
|
||||||
|
@ -60,8 +60,9 @@ pub static SHARED_RAW_TABLE: (
|
||||||
unsafe extern "C" fn() -> PageList, // 初始化函数,执行完之后,内核将函数指针置空
|
unsafe extern "C" fn() -> PageList, // 初始化函数,执行完之后,内核将函数指针置空
|
||||||
&'static SharedScheduler, // 共享调度器的地址
|
&'static SharedScheduler, // 共享调度器的地址
|
||||||
unsafe extern "C" fn(NonNull<()>, usize, AddressSpaceId, TaskRepr) -> bool, // 添加任务
|
unsafe extern "C" fn(NonNull<()>, usize, AddressSpaceId, TaskRepr) -> bool, // 添加任务
|
||||||
unsafe extern "C" fn(NonNull<()>, extern "C" fn(&SharedTaskHandle) -> bool) -> TaskResult, // 弹出任务
|
unsafe extern "C" fn(NonNull<()>, extern "C" fn(AddressSpaceId) -> bool) -> TaskResult, // 弹出任务
|
||||||
unsafe extern "C" fn(NonNull<()>, TaskRepr) -> bool,
|
unsafe extern "C" fn(NonNull<()>, usize, AddressSpaceId, TaskRepr) -> bool, // 删除任务
|
||||||
|
unsafe extern "C" fn(NonNull<()>, usize, AddressSpaceId, TaskRepr, TaskState), // 改变任务的状态
|
||||||
) = (
|
) = (
|
||||||
unsafe { &payload_compiled_start },
|
unsafe { &payload_compiled_start },
|
||||||
init_payload_environment,
|
init_payload_environment,
|
||||||
|
@ -69,6 +70,7 @@ pub static SHARED_RAW_TABLE: (
|
||||||
shared_add_task,
|
shared_add_task,
|
||||||
shared_peek_task,
|
shared_peek_task,
|
||||||
shared_delete_task,
|
shared_delete_task,
|
||||||
|
shared_set_task_state,
|
||||||
);
|
);
|
||||||
|
|
||||||
#[allow(non_upper_case_globals)]
|
#[allow(non_upper_case_globals)]
|
||||||
|
|
|
@ -25,22 +25,34 @@ pub enum TaskResult {
|
||||||
pub struct TaskRepr(usize);
|
pub struct TaskRepr(usize);
|
||||||
|
|
||||||
/// 共享调度器的类型
|
/// 共享调度器的类型
|
||||||
pub type SharedScheduler = Mutex<RingFifoScheduler<SharedTaskHandle, 100>>;
|
pub type SharedScheduler = Mutex<RingFifoScheduler<TaskMeta, 100>>;
|
||||||
|
|
||||||
/// 全局的共享调度器
|
/// 全局的共享调度器
|
||||||
/// 放到数据段,内核或用户从这个地址里取得共享调度器
|
/// 放到数据段,内核或用户从这个地址里取得共享调度器
|
||||||
pub static SHARED_SCHEDULER: SharedScheduler = Mutex::new(RingFifoScheduler::new());
|
pub static SHARED_SCHEDULER: SharedScheduler = Mutex::new(RingFifoScheduler::new());
|
||||||
|
|
||||||
/// 共享任务的句柄
|
/// 共享任务的元数据
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct SharedTaskHandle {
|
pub struct TaskMeta {
|
||||||
/// 运行此任务的硬件线程编号
|
/// 运行此任务的硬件线程编号
|
||||||
pub(crate) hart_id: usize,
|
pub(crate) hart_id: usize,
|
||||||
/// 地址空间的编号
|
/// 地址空间的编号
|
||||||
pub(crate) address_space_id: AddressSpaceId,
|
pub(crate) address_space_id: AddressSpaceId,
|
||||||
// 元数据指针,由所在的地址空间解释
|
// 元数据指针,由所在的地址空间解释
|
||||||
task_repr: TaskRepr,
|
task_repr: TaskRepr,
|
||||||
|
// 任务当前的状态
|
||||||
|
pub(crate) state: TaskState,
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo: 在调度器中设计,如果任务正在休眠,就跳过
|
||||||
|
|
||||||
|
/// 任务当前的状态
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum TaskState {
|
||||||
|
Ready = 0,
|
||||||
|
Sleeping = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 给共享调度器添加任务
|
/// 给共享调度器添加任务
|
||||||
|
@ -63,11 +75,12 @@ pub unsafe extern "C" fn shared_add_task(
|
||||||
hart_id: usize,
|
hart_id: usize,
|
||||||
address_space_id: AddressSpaceId,
|
address_space_id: AddressSpaceId,
|
||||||
task_repr: TaskRepr,
|
task_repr: TaskRepr,
|
||||||
) -> SharedTaskHandle {
|
) -> TaskMeta {
|
||||||
SharedTaskHandle {
|
TaskMeta {
|
||||||
hart_id,
|
hart_id,
|
||||||
address_space_id,
|
address_space_id,
|
||||||
task_repr,
|
task_repr,
|
||||||
|
state: TaskState::Ready, // 默认为就绪状态
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +89,7 @@ pub unsafe extern "C" fn shared_add_task(
|
||||||
/// 在内核态和用户态都可以调用
|
/// 在内核态和用户态都可以调用
|
||||||
pub unsafe extern "C" fn shared_peek_task(
|
pub unsafe extern "C" fn shared_peek_task(
|
||||||
shared_scheduler: NonNull<()>,
|
shared_scheduler: NonNull<()>,
|
||||||
should_switch: extern "C" fn(&SharedTaskHandle) -> bool
|
should_switch: extern "C" fn(AddressSpaceId) -> bool
|
||||||
) -> TaskResult {
|
) -> TaskResult {
|
||||||
// 得到共享调度器的引用
|
// 得到共享调度器的引用
|
||||||
// println!("[Shared peek task] {:p} {:x}", shared_scheduler, should_switch as usize);
|
// println!("[Shared peek task] {:p} {:x}", shared_scheduler, should_switch as usize);
|
||||||
|
@ -84,7 +97,7 @@ pub unsafe extern "C" fn shared_peek_task(
|
||||||
let scheduler = s.as_mut().lock();
|
let scheduler = s.as_mut().lock();
|
||||||
if let Some(task) = scheduler.peek_next_task() {
|
if let Some(task) = scheduler.peek_next_task() {
|
||||||
// println!("Pop task {:x?}!", task);
|
// println!("Pop task {:x?}!", task);
|
||||||
if should_switch(task) {
|
if should_switch(task.address_space_id) {
|
||||||
// 如果需要跳转到其他地址空间,则不弹出任务,返回需要跳转到的地址空间编号
|
// 如果需要跳转到其他地址空间,则不弹出任务,返回需要跳转到的地址空间编号
|
||||||
return TaskResult::ShouldYield(task.address_space_id.into_inner())
|
return TaskResult::ShouldYield(task.address_space_id.into_inner())
|
||||||
}
|
}
|
||||||
|
@ -103,6 +116,8 @@ pub unsafe extern "C" fn shared_peek_task(
|
||||||
/// 删除一个共享调度器中的任务
|
/// 删除一个共享调度器中的任务
|
||||||
pub unsafe extern "C" fn shared_delete_task(
|
pub unsafe extern "C" fn shared_delete_task(
|
||||||
shared_scheduler: NonNull<()>,
|
shared_scheduler: NonNull<()>,
|
||||||
|
_hart_id: usize,
|
||||||
|
_address_space_id: AddressSpaceId,
|
||||||
task_repr: TaskRepr,
|
task_repr: TaskRepr,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let mut s: NonNull<SharedScheduler> = shared_scheduler.cast();
|
let mut s: NonNull<SharedScheduler> = shared_scheduler.cast();
|
||||||
|
@ -117,3 +132,27 @@ pub unsafe extern "C" fn shared_delete_task(
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 设置任务的状态
|
||||||
|
pub unsafe extern "C" fn shared_set_task_state(
|
||||||
|
shared_scheduler: NonNull<()>,
|
||||||
|
hart_id: usize,
|
||||||
|
address_space_id: AddressSpaceId,
|
||||||
|
task_repr: TaskRepr,
|
||||||
|
new_state: TaskState,
|
||||||
|
) {
|
||||||
|
let mut s: NonNull<SharedScheduler> = shared_scheduler.cast();
|
||||||
|
let mut scheduler = s.as_mut().lock();
|
||||||
|
if let Some(task) = scheduler.find_first_task_mut(|t| task_eq(t, hart_id, address_space_id, task_repr)) {
|
||||||
|
task.state = new_state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn task_eq(
|
||||||
|
a: &TaskMeta,
|
||||||
|
hart_id: usize,
|
||||||
|
address_space_id: AddressSpaceId,
|
||||||
|
task_repr: TaskRepr,
|
||||||
|
) -> bool {
|
||||||
|
a.hart_id == hart_id && a.address_space_id == address_space_id && a.task_repr == task_repr
|
||||||
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
use alloc::collections::LinkedList;
|
use alloc::collections::LinkedList;
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
use crate::{task::{Process, SharedTaskHandle}, trap::TrapFrame};
|
use crate::task::Process;
|
||||||
use crate::memory::{AddressSpaceId, Satp};
|
use crate::memory::{AddressSpaceId, Satp};
|
||||||
|
|
||||||
/// 写一个指针到上下文指针
|
/// 写一个指针到上下文指针
|
||||||
|
|
|
@ -118,7 +118,8 @@ pub extern "C" fn rust_main(hart_id: usize) -> ! {
|
||||||
|
|
||||||
task::run_until_idle(
|
task::run_until_idle(
|
||||||
|| unsafe { shared_payload.peek_task(task::kernel_should_switch) },
|
|| unsafe { shared_payload.peek_task(task::kernel_should_switch) },
|
||||||
|task_repr| unsafe { shared_payload.delete_task(task_repr) },
|
|task_repr| unsafe { shared_payload.delete_task(hart_id, address_space_id, task_repr) },
|
||||||
|
|task_repr, new_state| unsafe { shared_payload.set_task_state(hart_id, address_space_id, task_repr, new_state)}
|
||||||
);
|
);
|
||||||
|
|
||||||
// 进入用户态
|
// 进入用户态
|
||||||
|
@ -155,6 +156,8 @@ use core::future::Future;
|
||||||
use core::task::{Context, Poll};
|
use core::task::{Context, Poll};
|
||||||
use core::pin::Pin;
|
use core::pin::Pin;
|
||||||
|
|
||||||
|
use task::TaskState;
|
||||||
|
|
||||||
|
|
||||||
impl Future for FibonacciFuture {
|
impl Future for FibonacciFuture {
|
||||||
type Output = ();
|
type Output = ();
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::task::{TaskResult, KernelTask};
|
use crate::task::{TaskResult, TaskState, KernelTask};
|
||||||
use woke::waker_ref;
|
use woke::waker_ref;
|
||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
use core::{mem, task::{Poll, Context}};
|
use core::{mem, task::{Poll, Context}};
|
||||||
|
@ -11,28 +11,24 @@ use core::{mem, task::{Poll, Context}};
|
||||||
pub fn run_until_idle(
|
pub fn run_until_idle(
|
||||||
peek_task: impl Fn() -> TaskResult,
|
peek_task: impl Fn() -> TaskResult,
|
||||||
delete_task: impl Fn(usize) -> bool,
|
delete_task: impl Fn(usize) -> bool,
|
||||||
|
set_task_state: impl Fn(usize, TaskState),
|
||||||
) {
|
) {
|
||||||
loop {
|
loop {
|
||||||
let task = peek_task();
|
let task = peek_task();
|
||||||
println!(">>> kernel executor: next task = {:x?}", task);
|
println!(">>> kernel executor: next task = {:x?}", task);
|
||||||
match task {
|
match task {
|
||||||
TaskResult::Task(task_repr) => {
|
TaskResult::Task(task_repr) => { // 在相同的(内核)地址空间里面
|
||||||
// 在相同的(内核)地址空间里面
|
set_task_state(task_repr, TaskState::Sleeping);
|
||||||
let task: Arc<KernelTask> = unsafe { Arc::from_raw(task_repr as *mut _) };
|
let task: Arc<KernelTask> = unsafe { Arc::from_raw(task_repr as *mut _) };
|
||||||
task.mark_sleep();
|
|
||||||
// make a waker for our task
|
|
||||||
let waker = waker_ref(&task);
|
let waker = waker_ref(&task);
|
||||||
// poll our future and give it a waker
|
|
||||||
let mut context = Context::from_waker(&*waker);
|
let mut context = Context::from_waker(&*waker);
|
||||||
// println!("Poll begin");
|
|
||||||
let ret = task.future.lock().as_mut().poll(&mut context);
|
let ret = task.future.lock().as_mut().poll(&mut context);
|
||||||
// println!("Ret = {:?}", ret);
|
|
||||||
if let Poll::Pending = ret {
|
if let Poll::Pending = ret {
|
||||||
|
set_task_state(task_repr, TaskState::Ready);
|
||||||
mem::forget(task); // 不要释放task的内存,它将继续保存在内存中被使用
|
mem::forget(task); // 不要释放task的内存,它将继续保存在内存中被使用
|
||||||
} else { // 否则,释放task的内存
|
} else { // 否则,释放task的内存
|
||||||
delete_task(task_repr);
|
delete_task(task_repr);
|
||||||
// drop(task)
|
} // 隐含一个drop(task)
|
||||||
}
|
|
||||||
},
|
},
|
||||||
TaskResult::ShouldYield(next_asid) => {
|
TaskResult::ShouldYield(next_asid) => {
|
||||||
todo!("切换到 next_asid (= {}) 对应的地址空间", next_asid)
|
todo!("切换到 next_asid (= {}) 对应的地址空间", next_asid)
|
||||||
|
@ -41,3 +37,9 @@ pub fn run_until_idle(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl woke::Woke for KernelTask {
|
||||||
|
fn wake_by_ref(_task: &Arc<Self>) {
|
||||||
|
//todo: use set_task_state: impl Fn(usize, TaskState),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@ use spin::Mutex;
|
||||||
use core::ops::Range;
|
use core::ops::Range;
|
||||||
use core::future::Future;
|
use core::future::Future;
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use crate::{hart::KernelHartInfo, memory::VirtualAddress};
|
use crate::memory::VirtualAddress;
|
||||||
use crate::task::{Process, SharedTaskHandle};
|
use crate::task::Process;
|
||||||
use core::pin::Pin;
|
use core::pin::Pin;
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||||
|
@ -20,7 +20,7 @@ pub struct KernelTask {
|
||||||
/// 任务信息的可变部分
|
/// 任务信息的可变部分
|
||||||
pub inner: Mutex<TaskInner>,
|
pub inner: Mutex<TaskInner>,
|
||||||
/// 任务的内容
|
/// 任务的内容
|
||||||
pub future: Mutex<Pin<Box<dyn Future<Output = ()> + 'static + Send + Sync>>> // 用UnsafeCell代替Mutex会好一点
|
pub future: Mutex<Pin<Box<dyn Future<Output = ()> + 'static + Send + Sync>>>, // 用UnsafeCell代替Mutex会好一点
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 任务的编号
|
/// 任务的编号
|
||||||
|
@ -47,10 +47,6 @@ pub struct TaskInner {
|
||||||
///
|
///
|
||||||
/// 内核任务复用执行器的栈。用户任务占有一个栈,下一个任务复用此栈。强制中断暂停时,下一个任务使用新分配的栈。
|
/// 内核任务复用执行器的栈。用户任务占有一个栈,下一个任务复用此栈。强制中断暂停时,下一个任务使用新分配的栈。
|
||||||
pub stack: Option<Range<VirtualAddress>>,
|
pub stack: Option<Range<VirtualAddress>>,
|
||||||
/// 任务是否正在休眠
|
|
||||||
pub sleeping: bool,
|
|
||||||
/// 任务是否已经结束
|
|
||||||
pub ended: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl KernelTask {
|
impl KernelTask {
|
||||||
|
@ -67,8 +63,6 @@ impl KernelTask {
|
||||||
process,
|
process,
|
||||||
inner: Mutex::new(TaskInner {
|
inner: Mutex::new(TaskInner {
|
||||||
stack: None,
|
stack: None,
|
||||||
sleeping: false,
|
|
||||||
ended: false,
|
|
||||||
}),
|
}),
|
||||||
future: Mutex::new(Box::pin(future)),
|
future: Mutex::new(Box::pin(future)),
|
||||||
})
|
})
|
||||||
|
@ -82,26 +76,6 @@ impl KernelTask {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl KernelTask {
|
|
||||||
fn mark_ready(&self) {
|
|
||||||
self.inner.lock().sleeping = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn is_sleeping(&self) -> bool {
|
|
||||||
self.inner.lock().sleeping
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn mark_sleep(&self) {
|
|
||||||
self.inner.lock().sleeping = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl woke::Woke for KernelTask {
|
|
||||||
fn wake_by_ref(task: &Arc<Self>) {
|
|
||||||
task.mark_ready();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialEq for KernelTask {
|
impl PartialEq for KernelTask {
|
||||||
fn eq(&self, other: &KernelTask) -> bool {
|
fn eq(&self, other: &KernelTask) -> bool {
|
||||||
self.id == other.id
|
self.id == other.id
|
||||||
|
@ -120,11 +94,9 @@ impl fmt::Debug for KernelTask {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let inner = self.inner.lock();
|
let inner = self.inner.lock();
|
||||||
f.debug_struct("KernelTask")
|
f.debug_struct("KernelTask")
|
||||||
.field("task id", &self.id)
|
.field("task isd", &self.id)
|
||||||
.field("address space id", &self.process.address_space_id())
|
.field("address space id", &self.process.address_space_id())
|
||||||
.field("stack", &inner.stack)
|
.field("stack", &inner.stack)
|
||||||
.field("is_sleeping", &inner.sleeping)
|
|
||||||
.field("is_ended", &inner.ended)
|
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,8 @@ pub use kernel_task::{KernelTask, TaskId};
|
||||||
pub use process::{Process, ProcessId};
|
pub use process::{Process, ProcessId};
|
||||||
pub use executor::run_until_idle;
|
pub use executor::run_until_idle;
|
||||||
pub use shared::{
|
pub use shared::{
|
||||||
SharedTaskHandle,
|
|
||||||
SharedPayload,
|
SharedPayload,
|
||||||
|
TaskState,
|
||||||
kernel_should_switch
|
kernel_should_switch
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -29,22 +29,17 @@ use core::ptr::NonNull;
|
||||||
use core::mem;
|
use core::mem;
|
||||||
use super::TaskResult;
|
use super::TaskResult;
|
||||||
|
|
||||||
/// 共享的包含Future在用户空间的地址
|
/// 任务当前的状态
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
#[repr(C)]
|
#[repr(u8)]
|
||||||
pub struct SharedTaskHandle {
|
pub enum TaskState {
|
||||||
/// 运行此任务的硬件线程编号
|
Ready = 0,
|
||||||
pub(crate) hart_id: usize,
|
Sleeping = 1,
|
||||||
/// 地址空间的编号
|
|
||||||
pub(crate) address_space_id: AddressSpaceId,
|
|
||||||
/// 对每个虚拟空间来说,task_ptr是Arc<Task>相应的虚拟地址
|
|
||||||
/// 比如内核中是内核虚拟地址,用户中是用户的虚拟地址
|
|
||||||
pub(crate) task_ptr: usize,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub extern "C" fn kernel_should_switch(handle: &SharedTaskHandle) -> bool {
|
pub extern "C" fn kernel_should_switch(address_space_id: AddressSpaceId) -> bool {
|
||||||
// 如果当前和下一个任务间地址空间变化了,就说明应当切换上下文
|
// 如果当前和下一个任务间地址空间变化了,就说明应当切换上下文
|
||||||
KernelHartInfo::current_address_space_id() != handle.address_space_id
|
KernelHartInfo::current_address_space_id() != address_space_id
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 共享载荷
|
/// 共享载荷
|
||||||
|
@ -52,19 +47,24 @@ pub extern "C" fn kernel_should_switch(handle: &SharedTaskHandle) -> bool {
|
||||||
pub struct SharedPayload {
|
pub struct SharedPayload {
|
||||||
shared_scheduler: NonNull<()>,
|
shared_scheduler: NonNull<()>,
|
||||||
shared_add_task: unsafe extern "C" fn(NonNull<()>, usize, AddressSpaceId, usize) -> bool,
|
shared_add_task: unsafe extern "C" fn(NonNull<()>, usize, AddressSpaceId, usize) -> bool,
|
||||||
shared_peek_task: unsafe extern "C" fn(NonNull<()>, extern "C" fn(&SharedTaskHandle) -> bool) -> TaskResult,
|
shared_peek_task: unsafe extern "C" fn(NonNull<()>, extern "C" fn(AddressSpaceId) -> bool) -> TaskResult,
|
||||||
shared_delete_task: unsafe extern "C" fn(NonNull<()>, usize) -> bool,
|
shared_delete_task: unsafe extern "C" fn(NonNull<()>, usize, AddressSpaceId, usize) -> bool,
|
||||||
|
shared_set_task_state: unsafe extern "C" fn(NonNull<()>, usize, AddressSpaceId, usize, TaskState),
|
||||||
}
|
}
|
||||||
|
|
||||||
type SharedPayloadAsUsize = [usize; 6]; // 编译时基地址,初始化函数,共享调度器地址,添加函数,弹出函数
|
unsafe impl Send for SharedPayload {}
|
||||||
|
unsafe impl Sync for SharedPayload {}
|
||||||
|
|
||||||
|
type SharedPayloadAsUsize = [usize; 7]; // 编译时基地址,初始化函数,共享调度器地址,添加函数,弹出函数
|
||||||
type InitFunction = unsafe extern "C" fn() -> PageList;
|
type InitFunction = unsafe extern "C" fn() -> PageList;
|
||||||
type SharedPayloadRaw = (
|
type SharedPayloadRaw = (
|
||||||
usize, // 编译时基地址,转换后类型占位,不使用
|
usize, // 编译时基地址,转换后类型占位,不使用
|
||||||
usize, // 初始化函数,执行完之后,内核将函数指针置空
|
usize, // 初始化函数,执行完之后,内核将函数指针置空
|
||||||
NonNull<()>,
|
NonNull<()>,
|
||||||
unsafe extern "C" fn(NonNull<()>, usize, AddressSpaceId, usize) -> bool,
|
unsafe extern "C" fn(NonNull<()>, usize, AddressSpaceId, usize) -> bool, // 添加任务
|
||||||
unsafe extern "C" fn(NonNull<()>, extern "C" fn(&SharedTaskHandle) -> bool) -> TaskResult,
|
unsafe extern "C" fn(NonNull<()>, extern "C" fn(AddressSpaceId) -> bool) -> TaskResult, // 弹出任务
|
||||||
unsafe extern "C" fn(NonNull<()>, usize) -> bool,
|
unsafe extern "C" fn(NonNull<()>, usize, AddressSpaceId, usize) -> bool, // 删除任务
|
||||||
|
unsafe extern "C" fn(NonNull<()>, usize, AddressSpaceId, usize, TaskState), // 改变任务的状态
|
||||||
);
|
);
|
||||||
|
|
||||||
impl SharedPayload {
|
impl SharedPayload {
|
||||||
|
@ -93,6 +93,7 @@ impl SharedPayload {
|
||||||
shared_add_task: raw_table.3,
|
shared_add_task: raw_table.3,
|
||||||
shared_peek_task: raw_table.4,
|
shared_peek_task: raw_table.4,
|
||||||
shared_delete_task: raw_table.5,
|
shared_delete_task: raw_table.5,
|
||||||
|
shared_set_task_state: raw_table.6,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,16 +106,22 @@ impl SharedPayload {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 从共享调度器中得到下一个任务
|
/// 从共享调度器中得到下一个任务
|
||||||
pub unsafe fn peek_task(&self, should_yield: extern "C" fn(&SharedTaskHandle) -> bool) -> TaskResult {
|
pub unsafe fn peek_task(&self, should_yield: extern "C" fn(AddressSpaceId) -> bool) -> TaskResult {
|
||||||
let f = self.shared_peek_task;
|
let f = self.shared_peek_task;
|
||||||
// println!("Peek = {:x}, p1 = {:p}, p2 = {:x}", f as usize, self.shared_scheduler, should_yield as usize);
|
// println!("Peek = {:x}, p1 = {:p}, p2 = {:x}", f as usize, self.shared_scheduler, should_yield as usize);
|
||||||
f(self.shared_scheduler, should_yield)
|
f(self.shared_scheduler, should_yield)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 从共享调度器中删除任务
|
/// 从共享调度器中删除任务
|
||||||
pub unsafe fn delete_task(&self, task_repr: usize) -> bool {
|
pub unsafe fn delete_task(&self, hart_id: usize, address_space_id: AddressSpaceId, task_repr: usize) -> bool {
|
||||||
let f = self.shared_delete_task;
|
let f = self.shared_delete_task;
|
||||||
f(self.shared_scheduler, task_repr)
|
f(self.shared_scheduler, hart_id, address_space_id, task_repr)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 设置一个任务的状态
|
||||||
|
pub unsafe fn set_task_state(&self, hart_id: usize, address_space_id: AddressSpaceId, task_repr: usize, new_state: TaskState) {
|
||||||
|
let f = self.shared_set_task_state;
|
||||||
|
f(self.shared_scheduler, hart_id, address_space_id, task_repr, new_state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,18 +78,20 @@ fn main() -> i32 {
|
||||||
/// 运行一个异步的main函数,在用户的entry函数里调用
|
/// 运行一个异步的main函数,在用户的entry函数里调用
|
||||||
/// 应该作为标准库的一部分,这里使用一个库函数来模拟有标准库的情况
|
/// 应该作为标准库的一部分,这里使用一个库函数来模拟有标准库的情况
|
||||||
pub fn execute_async_main(main: impl Future<Output = i32> + Send + Sync + 'static) -> i32 {
|
pub fn execute_async_main(main: impl Future<Output = i32> + Send + Sync + 'static) -> i32 {
|
||||||
|
let hart_id = 0; // todo!
|
||||||
let shared_payload = unsafe { shared::SharedPayload::new(SHARED_PAYLOAD_BASE) };
|
let shared_payload = unsafe { shared::SharedPayload::new(SHARED_PAYLOAD_BASE) };
|
||||||
let asid = unsafe { shared::AddressSpaceId::from_raw(ADDRESS_SPACE_ID) };
|
let address_space_id = unsafe { shared::AddressSpaceId::from_raw(ADDRESS_SPACE_ID) };
|
||||||
static mut EXIT_CODE: i32 = 0;
|
static mut EXIT_CODE: i32 = 0;
|
||||||
let main_task = task::UserTask::new(async move {
|
let main_task = task::UserTask::new(async move {
|
||||||
unsafe { EXIT_CODE = main.await };
|
unsafe { EXIT_CODE = main.await };
|
||||||
});
|
});
|
||||||
unsafe {
|
unsafe {
|
||||||
shared_payload.add_task(0/* todo */, asid, main_task.task_repr());
|
shared_payload.add_task(hart_id, address_space_id, main_task.task_repr());
|
||||||
}
|
}
|
||||||
shared::run_until_ready(
|
shared::run_until_ready(
|
||||||
|| unsafe { shared_payload.peek_task(shared::user_should_switch) },
|
|| unsafe { shared_payload.peek_task(shared::user_should_switch) },
|
||||||
|task_repr| unsafe { shared_payload.delete_task(task_repr) }
|
|task_repr| unsafe { shared_payload.delete_task(hart_id, address_space_id, task_repr) },
|
||||||
|
|task_repr, new_state| unsafe { shared_payload.set_task_state(hart_id, address_space_id, task_repr, new_state)}
|
||||||
);
|
);
|
||||||
unsafe { EXIT_CODE }
|
unsafe { EXIT_CODE }
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,17 +8,6 @@ use alloc::sync::Arc;
|
||||||
use core::{mem, task::{Poll, Context}};
|
use core::{mem, task::{Poll, Context}};
|
||||||
use core::ptr::NonNull;
|
use core::ptr::NonNull;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct SharedTaskHandle {
|
|
||||||
/// 处理核编号
|
|
||||||
pub(crate) hart_id: usize,
|
|
||||||
/// 地址空间编号
|
|
||||||
pub(crate) address_space_id: AddressSpaceId,
|
|
||||||
/// task_ptr 是 Arc<Task> 的虚拟地址
|
|
||||||
pub(crate) task_ptr: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct AddressSpaceId(u16);
|
pub struct AddressSpaceId(u16);
|
||||||
|
@ -30,26 +19,28 @@ impl AddressSpaceId {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub extern "C" fn user_should_switch(_handle: &SharedTaskHandle) -> bool {
|
pub extern "C" fn user_should_switch(_asid: AddressSpaceId) -> bool {
|
||||||
false
|
false // todo
|
||||||
}
|
}
|
||||||
|
|
||||||
// 该执行器目前是测试使用,当轮询到一个完成的任务就退出了
|
// 该执行器目前是测试使用,当轮询到一个完成的任务就退出了
|
||||||
pub fn run_until_ready(
|
pub fn run_until_ready(
|
||||||
peek_task: impl Fn() -> TaskResult,
|
peek_task: impl Fn() -> TaskResult,
|
||||||
delete_task: impl Fn(usize) -> bool,
|
delete_task: impl Fn(usize) -> bool,
|
||||||
|
set_task_state: impl Fn(usize, TaskState),
|
||||||
) {
|
) {
|
||||||
loop {
|
loop {
|
||||||
let task = peek_task();
|
let task = peek_task();
|
||||||
println!(">>> user executor: next task = {:x?}", task);
|
println!(">>> user executor: next task = {:x?}", task);
|
||||||
match task {
|
match task {
|
||||||
TaskResult::Task(task_repr) => { // 在相同的地址空间里面
|
TaskResult::Task(task_repr) => { // 在相同的地址空间里面
|
||||||
|
set_task_state(task_repr, TaskState::Sleeping);
|
||||||
let task: Arc<UserTask> = unsafe { Arc::from_raw(task_repr as *mut _) };
|
let task: Arc<UserTask> = unsafe { Arc::from_raw(task_repr as *mut _) };
|
||||||
let waker = waker_ref(&task);
|
let waker = waker_ref(&task);
|
||||||
let mut context = Context::from_waker(&*waker);
|
let mut context = Context::from_waker(&*waker);
|
||||||
println!(">>> User executor: task = {:p}", task);
|
|
||||||
let ret = task.future.lock().as_mut().poll(&mut context);
|
let ret = task.future.lock().as_mut().poll(&mut context);
|
||||||
if let Poll::Pending = ret {
|
if let Poll::Pending = ret {
|
||||||
|
set_task_state(task_repr, TaskState::Ready);
|
||||||
mem::forget(task); // 不要释放task的内存,它将继续保存在内存中被使用
|
mem::forget(task); // 不要释放task的内存,它将继续保存在内存中被使用
|
||||||
} else {
|
} else {
|
||||||
delete_task(task_repr);
|
delete_task(task_repr);
|
||||||
|
@ -66,23 +57,33 @@ pub fn run_until_ready(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 任务当前的状态
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum TaskState {
|
||||||
|
Ready = 0,
|
||||||
|
Sleeping = 1,
|
||||||
|
}
|
||||||
|
|
||||||
/// 共享载荷
|
/// 共享载荷
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct SharedPayload {
|
pub struct SharedPayload {
|
||||||
shared_scheduler: NonNull<()>,
|
shared_scheduler: NonNull<()>,
|
||||||
shared_add_task: unsafe extern "C" fn(NonNull<()>, usize, AddressSpaceId, usize) -> bool,
|
shared_add_task: unsafe extern "C" fn(NonNull<()>, usize, AddressSpaceId, usize) -> bool,
|
||||||
shared_peek_task: unsafe extern "C" fn(NonNull<()>, extern "C" fn(&SharedTaskHandle) -> bool) -> TaskResult,
|
shared_peek_task: unsafe extern "C" fn(NonNull<()>, extern "C" fn(AddressSpaceId) -> bool) -> TaskResult,
|
||||||
shared_delete_task: unsafe extern "C" fn(NonNull<()>, usize) -> bool,
|
shared_delete_task: unsafe extern "C" fn(NonNull<()>, usize, AddressSpaceId, usize) -> bool,
|
||||||
|
shared_set_task_state: unsafe extern "C" fn(NonNull<()>, usize, AddressSpaceId, usize, TaskState),
|
||||||
}
|
}
|
||||||
|
|
||||||
type SharedPayloadAsUsize = [usize; 6]; // 编译时基地址,(已清空)初始化函数,共享调度器地址,添加函数,弹出函数
|
type SharedPayloadAsUsize = [usize; 7]; // 编译时基地址,(已清空)初始化函数,共享调度器地址,添加函数,弹出函数
|
||||||
type SharedPayloadRaw = (
|
type SharedPayloadRaw = (
|
||||||
usize, // 编译时基地址,转换后类型占位,不使用
|
usize, // 编译时基地址,转换后类型占位,不使用
|
||||||
usize, // 初始化函数已清空,不适用
|
usize, // 初始化函数已清空,不适用
|
||||||
NonNull<()>,
|
NonNull<()>,
|
||||||
unsafe extern "C" fn(NonNull<()>, usize, AddressSpaceId, usize) -> bool,
|
unsafe extern "C" fn(NonNull<()>, usize, AddressSpaceId, usize) -> bool, // 添加任务
|
||||||
unsafe extern "C" fn(NonNull<()>, extern "C" fn(&SharedTaskHandle) -> bool) -> TaskResult,
|
unsafe extern "C" fn(NonNull<()>, extern "C" fn(AddressSpaceId) -> bool) -> TaskResult, // 弹出任务
|
||||||
unsafe extern "C" fn(NonNull<()>, usize) -> bool,
|
unsafe extern "C" fn(NonNull<()>, usize, AddressSpaceId, usize) -> bool, // 删除任务
|
||||||
|
unsafe extern "C" fn(NonNull<()>, usize, AddressSpaceId, usize, TaskState), // 改变任务的状态
|
||||||
);
|
);
|
||||||
|
|
||||||
impl SharedPayload {
|
impl SharedPayload {
|
||||||
|
@ -101,6 +102,7 @@ impl SharedPayload {
|
||||||
shared_add_task: raw_table.3,
|
shared_add_task: raw_table.3,
|
||||||
shared_peek_task: raw_table.4,
|
shared_peek_task: raw_table.4,
|
||||||
shared_delete_task: raw_table.5,
|
shared_delete_task: raw_table.5,
|
||||||
|
shared_set_task_state: raw_table.6,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,13 +111,17 @@ impl SharedPayload {
|
||||||
f(self.shared_scheduler, hart_id, address_space_id, task_repr)
|
f(self.shared_scheduler, hart_id, address_space_id, task_repr)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn peek_task(&self, should_yield: extern "C" fn(&SharedTaskHandle) -> bool) -> TaskResult {
|
pub unsafe fn peek_task(&self, should_yield: extern "C" fn(AddressSpaceId) -> bool) -> TaskResult {
|
||||||
let f = self.shared_peek_task;
|
let f = self.shared_peek_task;
|
||||||
f(self.shared_scheduler, should_yield)
|
f(self.shared_scheduler, should_yield)
|
||||||
}
|
}
|
||||||
|
pub unsafe fn delete_task(&self, hart_id: usize, address_space_id: AddressSpaceId, task_repr: usize) -> bool {
|
||||||
pub unsafe fn delete_task(&self, task_repr: usize) -> bool {
|
|
||||||
let f = self.shared_delete_task;
|
let f = self.shared_delete_task;
|
||||||
f(self.shared_scheduler, task_repr)
|
f(self.shared_scheduler, hart_id, address_space_id, task_repr)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn set_task_state(&self, hart_id: usize, address_space_id: AddressSpaceId, task_repr: usize, new_state: TaskState) {
|
||||||
|
let f = self.shared_set_task_state;
|
||||||
|
f(self.shared_scheduler, hart_id, address_space_id, task_repr, new_state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue