add peek_wake_task in shared-scheduler

This commit is contained in:
SKTT1Ryze 2021-05-22 11:10:23 +08:00
parent 71d995a9a5
commit 5cfdb5e975
9 changed files with 159 additions and 42 deletions

View File

@ -21,4 +21,12 @@ pub trait Scheduler<T: Clone + PartialEq> {
fn remove_task(&mut self, task: &T);
/// 设置任务的优先级
fn set_priority(&mut self, task: T, priority: Self::Priority);
/// 返回调度队列的总长度
/// 如果有队列,则返回 Some否则返回 None
///
/// 目前这里是实现上的需要,后面需要移除这个方法
/// 因为具体调度器实现里面可能没有队列,这个不是调度器的共性
fn queue_len(&self) -> Option<usize> {
None
}
}

View File

@ -55,6 +55,9 @@ impl<T: Clone + PartialEq, const N: usize> Scheduler<T> for RingFifoScheduler<T,
todo!("还没做")
}
fn set_priority(&mut self, _task: T, _prio: ()) {}
fn queue_len(&self) -> Option<usize> {
Some(self.ring.len())
}
}
pub struct RingQueue<T, const N: usize> {
@ -117,37 +120,4 @@ impl<T, const N: usize> RingQueue<T, N> {
Some(unsafe { &mut *self.elem[self.front].as_mut_ptr() })
}
}
// pub fn iter_mut(&mut self) -> IterMut<'_, T, N> {
// IterMut {
// ptr: &mut self.elem as *mut [MaybeUninit<T>; N] as *mut [T; N],
// front: self.front,
// tail: self.tail,
// _marker: PhantomData
// }
// }
}
// pub struct IterMut<'a, T: 'a, const N: usize> {
// ptr: *mut [T; N],
// front: usize,
// tail: usize,
// _marker: PhantomData<&'a mut T>
// }
// // TODO: 这里有不确定 Unsafe 代码,需检查正确性
// impl<'a, T, const N: usize> Iterator for IterMut<'a, T, N> {
// type Item = &'a mut T;
// fn next(&mut self) -> Option<Self::Item> {
// if self.tail == self.front {
// // is empty
// None
// } else {
// let value = unsafe { &mut (*(self.ptr))[self.front] };
// self.front = self.front.wrapping_add(1);
// if self.front > N || self.front == 0 {
// self.front = self.front.wrapping_sub(N);
// }
// Some(value)
// }
// }
// }

View File

@ -23,7 +23,7 @@ use buddy_system_allocator::LockedHeap;
use core::{mem::MaybeUninit, ptr::NonNull};
use crate::task::{
TaskResult, TaskRepr, TaskState, SharedScheduler, SHARED_SCHEDULER,
shared_add_task, shared_peek_task, shared_delete_task, shared_set_task_state,
shared_add_task, shared_peek_task, shared_peek_wake_task, shared_delete_task, shared_set_task_state,
};
use crate::mm::AddressSpaceId;
@ -61,6 +61,7 @@ pub static SHARED_RAW_TABLE: (
&'static SharedScheduler, // 共享调度器的地址
unsafe extern "C" fn(NonNull<()>, usize, AddressSpaceId, TaskRepr) -> bool, // 添加任务
unsafe extern "C" fn(NonNull<()>, extern "C" fn(AddressSpaceId) -> 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<()>, TaskRepr, TaskState), // 改变任务的状态
) = (
@ -69,6 +70,7 @@ pub static SHARED_RAW_TABLE: (
&SHARED_SCHEDULER,
shared_add_task,
shared_peek_task,
shared_peek_wake_task,
shared_delete_task,
shared_set_task_state,
);

View File

@ -15,6 +15,8 @@ pub enum TaskResult {
/// 其他地址空间的任务要运行,应当让出时间片
/// 并返回下一个地址空间的编号
ShouldYield(usize),
/// 调度器里面没有醒着的任务,但存在睡眠任务
NoWakeTask,
/// 队列已空,所有任务已经结束
Finished
}
@ -106,13 +108,57 @@ pub unsafe extern "C" fn shared_peek_task(
drop(scheduler); // 释放锁
return TaskResult::Task(task_repr)
// 调用者拿到任务后,执行此任务,然后必须销毁任务,否则任务会被重新拿出来再执行一次
// CCC: 这样的设计好像会增加一些时间复杂度,后面需要再考虑一下这部分的设计
} else {
// 没有任务了,返回已完成
return TaskResult::Finished;
}
}
/// 从共享调度器中找到下一个任务
/// 如果任务处于睡眠状态则重新放入调度队列尾部
///
/// 内核态和用户态都可以调用
pub unsafe extern "C" fn shared_peek_wake_task(
shared_scheduler: NonNull<()>,
should_switch: extern "C" fn(AddressSpaceId) -> bool
) -> TaskResult {
let mut s: NonNull<SharedScheduler> = shared_scheduler.cast();
let mut scheduler = s.as_mut().lock();
let mut ret_task;
let mut count = 0; // 计数器,防止无限循环
loop {
ret_task = scheduler.peek_next_task();
match ret_task {
Some(task) => {
if task.state == TaskState::Sleeping {
if count >= scheduler.queue_len().unwrap() {
// 已经全部遍历过一遍,没有找到醒着的任务
// 返回 TaskResult::NoWakeTask, 提示执行器调度器里面还有睡眠任务
// 如果等待时间过长,则下一次时间中断的时候切换地址空间
return TaskResult::NoWakeTask;
}
// 睡眠状态,将当前任务放到调度队列尾部
let sleep_task = scheduler.next_task().unwrap();
scheduler.add_task(sleep_task);
count = count.wrapping_add(1);
// 进行下一个循环
} else {
if should_switch(task.address_space_id) {
// 需要跳转到其他地址空间
return TaskResult::ShouldYield(task.address_space_id.into_inner());
} else {
let task_repr = task.task_repr;
drop(scheduler);
return TaskResult::Task(task_repr);
}
}
},
None => return TaskResult::Finished
}
}
}
/// 删除一个共享调度器中的任务
pub unsafe extern "C" fn shared_delete_task(
shared_scheduler: NonNull<()>,

View File

@ -32,6 +32,41 @@ pub fn run_until_idle(
TaskResult::ShouldYield(next_asid) => {
todo!("切换到 next_asid (= {}) 对应的地址空间", next_asid)
},
TaskResult::NoWakeTask => {
todo!()
},
TaskResult::Finished => break
}
}
}
pub fn run_wake_until_idle(
peek_wake_task: impl Fn() -> TaskResult,
delete_task: impl Fn(usize) -> bool,
set_task_state: impl Fn(usize, TaskState),
) {
loop {
let task = peek_wake_task();
println!(">>> kernel executor: next task = {:x?}", task);
match task {
TaskResult::Task(task_repr) => { // 在相同的(内核)地址空间里面
set_task_state(task_repr, TaskState::Sleeping);
let task: Arc<KernelTaskRepr> = unsafe { Arc::from_raw(task_repr as *mut _) };
let waker = waker_ref(&task);
let mut context = Context::from_waker(&*waker);
let ret = task.task().future.lock().as_mut().poll(&mut context);
if let Poll::Pending = ret {
mem::forget(task); // 不要释放task的内存它将继续保存在内存中被使用
} else { // 否则释放task的内存
delete_task(task_repr);
} // 隐含一个drop(task)
},
TaskResult::ShouldYield(next_asid) => {
todo!("切换到 next_asid (= {}) 对应的地址空间", next_asid)
},
TaskResult::NoWakeTask => {
todo!()
},
TaskResult::Finished => break
}
}

View File

@ -23,6 +23,8 @@ pub enum TaskResult {
Task(usize),
/// 其它地址空间的任务要运行,应当让出时间片
ShouldYield(usize),
/// 调度器中没有非睡眠任务
NoWakeTask,
/// 队列已空,所有任务已经结束
Finished,
}

View File

@ -48,6 +48,7 @@ pub struct SharedPayload {
pub(crate) shared_scheduler: NonNull<()>,
shared_add_task: unsafe extern "C" fn(NonNull<()>, usize, AddressSpaceId, usize) -> bool,
shared_peek_task: unsafe extern "C" fn(NonNull<()>, extern "C" fn(AddressSpaceId) -> bool) -> TaskResult,
shared_peek_wake_task: unsafe extern "C" fn(NonNull<()>, extern "C" fn(AddressSpaceId) -> bool) -> TaskResult,
shared_delete_task: unsafe extern "C" fn(NonNull<()>, usize) -> bool,
pub(crate) shared_set_task_state: unsafe extern "C" fn(NonNull<()>, usize, TaskState),
}
@ -55,7 +56,7 @@ pub struct SharedPayload {
unsafe impl Send for SharedPayload {}
unsafe impl Sync for SharedPayload {}
type SharedPayloadAsUsize = [usize; 7]; // 编译时基地址,初始化函数,共享调度器地址,添加函数,弹出函数
type SharedPayloadAsUsize = [usize; 8]; // 编译时基地址,初始化函数,共享调度器地址,添加函数,弹出函数
type InitFunction = unsafe extern "C" fn() -> PageList;
type SharedPayloadRaw = (
usize, // 编译时基地址,转换后类型占位,不使用
@ -63,6 +64,7 @@ type SharedPayloadRaw = (
NonNull<()>,
unsafe extern "C" fn(NonNull<()>, usize, AddressSpaceId, usize) -> bool, // 添加任务
unsafe extern "C" fn(NonNull<()>, extern "C" fn(AddressSpaceId) -> 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, TaskState), // 改变任务的状态
);
@ -92,8 +94,9 @@ impl SharedPayload {
shared_scheduler: raw_table.2,
shared_add_task: raw_table.3,
shared_peek_task: raw_table.4,
shared_delete_task: raw_table.5,
shared_set_task_state: raw_table.6,
shared_peek_wake_task: raw_table.5,
shared_delete_task: raw_table.6,
shared_set_task_state: raw_table.7,
}
}
@ -112,6 +115,13 @@ impl SharedPayload {
f(self.shared_scheduler, should_yield)
}
/// 从共享调度器中得到下一个非睡眠任务
pub unsafe fn peek_wake_task(&self, should_yield: extern "C" fn(AddressSpaceId) -> bool) -> TaskResult {
let f = self.shared_peek_wake_task;
// println!("Peek wake = {:x}, p1 = {:p}, p2 = {:x}", f as usize, self.shared_scheduler, should_yield as usize);
f(self.shared_scheduler, should_yield)
}
/// 从共享调度器中删除任务
pub unsafe fn delete_task(&self, task_repr: usize) -> bool {
let f = self.shared_delete_task;

View File

@ -23,7 +23,6 @@ pub extern "C" fn user_should_switch(_asid: AddressSpaceId) -> bool {
false // todo
}
// 该执行器目前是测试使用,当轮询到一个完成的任务就退出了
pub fn run_until_ready(
peek_task: impl Fn() -> TaskResult,
delete_task: impl Fn(usize) -> bool,
@ -49,6 +48,40 @@ pub fn run_until_ready(
// 让出操作
do_yield(next_asid);
},
TaskResult::NoWakeTask => todo!(),
TaskResult::Finished => {
break;
}
}
}
}
pub fn run_wake_until_ready(
peek_wake_task: impl Fn() -> TaskResult,
delete_task: impl Fn(usize) -> bool,
set_task_state: impl Fn(usize, TaskState),
) {
loop {
let task = peek_wake_task();
println!(">>> user executor: next task = {:x?}", task);
match task {
TaskResult::Task(task_repr) => { // 在相同的地址空间里面
set_task_state(task_repr, TaskState::Sleeping);
let task: Arc<UserTask> = unsafe { Arc::from_raw(task_repr as *mut _) };
let waker = waker_ref(&task);
let mut context = Context::from_waker(&*waker);
let ret = task.future.lock().as_mut().poll(&mut context);
if let Poll::Pending = ret {
mem::forget(task); // 不要释放task的内存它将继续保存在内存中被使用
} else {
delete_task(task_repr);
}
},
TaskResult::ShouldYield(next_asid) => {
// 让出操作
do_yield(next_asid);
},
TaskResult::NoWakeTask => todo!(),
TaskResult::Finished => {
break;
}
@ -70,17 +103,19 @@ pub struct SharedPayload {
shared_scheduler: NonNull<()>,
shared_add_task: unsafe extern "C" fn(NonNull<()>, usize, AddressSpaceId, usize) -> bool,
shared_peek_task: unsafe extern "C" fn(NonNull<()>, extern "C" fn(AddressSpaceId) -> bool) -> TaskResult,
shared_peek_wake_task: unsafe extern "C" fn(NonNull<()>, extern "C" fn(AddressSpaceId) -> bool) -> TaskResult,
shared_delete_task: unsafe extern "C" fn(NonNull<()>, usize) -> bool,
shared_set_task_state: unsafe extern "C" fn(NonNull<()>, usize, TaskState),
}
type SharedPayloadAsUsize = [usize; 7]; // 编译时基地址,(已清空)初始化函数,共享调度器地址,添加函数,弹出函数
type SharedPayloadAsUsize = [usize; 8]; // 编译时基地址,(已清空)初始化函数,共享调度器地址,添加函数,弹出函数
type SharedPayloadRaw = (
usize, // 编译时基地址,转换后类型占位,不使用
usize, // 初始化函数已清空,不适用
NonNull<()>,
unsafe extern "C" fn(NonNull<()>, usize, AddressSpaceId, usize) -> bool, // 添加任务
unsafe extern "C" fn(NonNull<()>, extern "C" fn(AddressSpaceId) -> 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, TaskState), // 改变任务的状态
);
@ -100,8 +135,9 @@ impl SharedPayload {
shared_scheduler: raw_table.2,
shared_add_task: raw_table.3,
shared_peek_task: raw_table.4,
shared_delete_task: raw_table.5,
shared_set_task_state: raw_table.6,
shared_peek_wake_task: raw_table.5,
shared_delete_task: raw_table.6,
shared_set_task_state: raw_table.7,
}
}
@ -114,6 +150,12 @@ impl SharedPayload {
let f = self.shared_peek_task;
f(self.shared_scheduler, should_yield)
}
pub unsafe fn peek_wake_task(&self, should_yield: extern "C" fn(AddressSpaceId) -> bool) -> TaskResult {
let f = self.shared_peek_wake_task;
f(self.shared_scheduler, should_yield)
}
pub unsafe fn delete_task(&self, task_repr: usize) -> bool {
let f = self.shared_delete_task;
f(self.shared_scheduler, task_repr)

View File

@ -104,6 +104,8 @@ pub enum TaskResult {
Task(usize),
/// 其它地址空间的任务要运行,应当让出时间片
ShouldYield(usize),
/// 调度器中没有非睡眠任务
NoWakeTask,
/// 队列已空,所有任务已经结束
Finished,
}