add do wake in user

This commit is contained in:
SKTT1Ryze 2021-05-26 17:02:03 +08:00
parent cb1fe70c8f
commit ebc43ad0b3
3 changed files with 75 additions and 43 deletions

View File

@ -82,9 +82,9 @@ pub fn execute_async_main(main: impl Future<Output = i32> + Send + Sync + 'stati
let shared_payload = unsafe { shared::SharedPayload::new(SHARED_PAYLOAD_BASE) };
let address_space_id = unsafe { shared::AddressSpaceId::from_raw(ADDRESS_SPACE_ID) };
static mut EXIT_CODE: i32 = 0;
let main_task = task::UserTask::new(async move {
let main_task = task::new_user(async move {
unsafe { EXIT_CODE = main.await };
});
}, shared_payload.shared_scheduler, shared_payload.shared_set_task_state);
unsafe {
shared_payload.add_task(hart_id, address_space_id, main_task.task_repr());
}
@ -100,7 +100,7 @@ pub fn execute_async_main(main: impl Future<Output = i32> + Send + Sync + 'stati
pub fn spawn(future: impl Future<Output = ()> + Send + Sync + 'static) {
let shared_payload = unsafe { shared::SharedPayload::new(SHARED_PAYLOAD_BASE) };
let asid = unsafe { shared::AddressSpaceId::from_raw(ADDRESS_SPACE_ID) };
let task = task::UserTask::new(future);
let task = task::new_user(future, shared_payload.shared_scheduler, shared_payload.shared_set_task_state);
unsafe {
shared_payload.add_task(0/* todo */, asid, task.task_repr());
}

View File

@ -1,8 +1,9 @@
use crate::do_yield;
use crate::println;
use crate::task::UserTaskRepr;
// 尝试在用户态给共享调度器添加任务
use super::task::{TaskResult, UserTask};
use super::task::TaskResult;
use woke::waker_ref;
use alloc::sync::Arc;
use core::{mem, task::{Poll, Context}};
@ -34,10 +35,10 @@ pub fn run_until_ready(
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 task: Arc<UserTaskRepr> = 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);
let ret = task.task().future.lock().as_mut().poll(&mut context);
if let Poll::Pending = ret {
mem::forget(task); // 不要释放task的内存它将继续保存在内存中被使用
} else {
@ -67,11 +68,11 @@ pub enum TaskState {
/// 共享载荷
#[repr(C)]
pub struct SharedPayload {
shared_scheduler: NonNull<()>,
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_delete_task: unsafe extern "C" fn(NonNull<()>, usize) -> bool,
shared_set_task_state: unsafe extern "C" fn(NonNull<()>, usize, TaskState),
pub(crate)shared_set_task_state: unsafe extern "C" fn(NonNull<()>, usize, TaskState),
}
type SharedPayloadAsUsize = [usize; 7]; // 编译时基地址,(已清空)初始化函数,共享调度器地址,添加函数,弹出函数

View File

@ -13,9 +13,10 @@ use core::pin::Pin;
use alloc::boxed::Box;
use core::future::Future;
use core::sync::atomic::{AtomicUsize, Ordering};
use core::ptr::NonNull;
use core::fmt;
use super::shared::TaskState;
/// 临时的用户态任务实现
pub struct UserTask {
/// 任务的编号
pub id: UserTaskId,
@ -26,6 +27,7 @@ pub struct UserTask {
}
/// 任务信息的可变部分
#[derive(Debug)]
pub struct UserTaskInner {
/// 任务是否在休眠
pub sleeping: bool,
@ -54,11 +56,10 @@ impl UserTask {
/// 创建一个用户态任务
pub fn new(
future: impl Future<Output = ()> + 'static + Send + Sync,
) -> Arc<UserTask> {
) -> UserTask {
// 得到新的用户任务编号
let id = UserTaskId::generate();
// 打包成用户态任务
Arc::new(
UserTask {
id,
inner: Mutex::new(UserTaskInner {
@ -67,33 +68,18 @@ impl UserTask {
}),
future: Mutex::new(Box::pin(future))
}
)
}
/// 转换到共享的任务编号
/// 危险:创建了一个没有边界的生命周期
pub unsafe fn task_repr(self: Arc<Self>) -> usize {
Arc::into_raw(self) as usize
}
}
impl UserTask {
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 UserTask {
fn wake_by_ref(task: &Arc<Self>) {
task.mark_ready();
impl fmt::Debug for UserTask {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let inner = self.inner.lock();
f.debug_struct("UserTask")
.field("task_id", &self.id)
.field("is sleeping", &inner.sleeping)
.field("is finished", &inner.finished)
.finish()
}
}
@ -109,3 +95,48 @@ pub enum TaskResult {
/// 队列已空,所有任务已经结束
Finished,
}
// 创建一个新的用户任务,打包它的环境
pub fn new_user(
future: impl Future<Output = ()> + 'static + Send + Sync,
shared_scheduler: NonNull<()>,
set_task_state: unsafe extern "C" fn(NonNull<()>, usize, TaskState)
) -> Arc<UserTaskRepr> {
Arc::new(
UserTaskRepr(
UserTask::new(future),
shared_scheduler.as_ptr() as usize,
set_task_state
)
)
}
#[derive(Debug)]
pub struct UserTaskRepr (
UserTask, usize,
unsafe extern "C" fn(NonNull<()>, usize, TaskState)
);
impl UserTaskRepr {
/// 转换到共享的任务编号
///
/// note(unsafe): 创建了一个没有边界的生命周期
pub unsafe fn task_repr(self: Arc<Self>) -> usize {
Arc::into_raw(self) as usize
}
pub unsafe fn do_wake(self: &Arc<Self>) {
let shared_scheduler = NonNull::new(self.1 as *mut()).unwrap();
let task_repr = Arc::as_ptr(self) as usize;
(self.2)(shared_scheduler, task_repr, TaskState::Ready)
}
#[inline] pub fn task(&self) -> &UserTask {
&self.0
}
}
impl woke::Woke for UserTaskRepr {
fn wake_by_ref(task: &Arc<Self>) {
unsafe { task.do_wake() }
}
}