add peek_wake_task in shared-scheduler
This commit is contained in:
parent
71d995a9a5
commit
5cfdb5e975
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
|
|
|
@ -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<()>,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@ pub enum TaskResult {
|
|||
Task(usize),
|
||||
/// 其它地址空间的任务要运行,应当让出时间片
|
||||
ShouldYield(usize),
|
||||
/// 调度器中没有非睡眠任务
|
||||
NoWakeTask,
|
||||
/// 队列已空,所有任务已经结束
|
||||
Finished,
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -104,6 +104,8 @@ pub enum TaskResult {
|
|||
Task(usize),
|
||||
/// 其它地址空间的任务要运行,应当让出时间片
|
||||
ShouldYield(usize),
|
||||
/// 调度器中没有非睡眠任务
|
||||
NoWakeTask,
|
||||
/// 队列已空,所有任务已经结束
|
||||
Finished,
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue