Change design of sleeping state

This commit is contained in:
luojia65 2021-04-25 14:32:47 +08:00
parent 4d583f52a2
commit 7bae22b118
12 changed files with 175 additions and 140 deletions

View File

@ -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);
/// 设置任务的优先级 /// 设置任务的优先级

View File

@ -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)
// } }
// } }
// } }

View File

@ -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)]

View File

@ -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
}

View File

@ -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};
/// 写一个指针到上下文指针 /// 写一个指针到上下文指针

View File

@ -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 = ();

View File

@ -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),
}
}

View File

@ -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()
} }
} }

View File

@ -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
}; };

View File

@ -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)
} }
} }

View File

@ -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 }
} }

View File

@ -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)
} }
} }