Merge pull request #29 from HUST-OS/main

merge main to clean_up_the_code
This commit is contained in:
Chunchi Che 2021-04-25 00:05:39 +08:00 committed by GitHub
commit 114857add4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 361 additions and 315 deletions

View File

@ -6,19 +6,7 @@ mod user_syscall;
pub use user_syscall::user_trap_handler; pub use user_syscall::user_trap_handler;
use config::*; use config::*;
use crate::memory::{AddressSpaceId, Satp, VirtualPageNumber, VirtualAddress,};
use crate::{
hart::KernelHartInfo,
memory::{
AddressSpaceId,
Satp,
VirtualPageNumber,
VirtualAddress,
PhysicalPageNumber,
KERNEL_MAP_OFFSET
}
};
use bit_field::BitField; use bit_field::BitField;
pub enum SyscallResult { pub enum SyscallResult {
@ -34,10 +22,10 @@ impl SyscallResult {
} }
} }
pub fn syscall(param: [usize; 6], func: usize, module: usize) -> SyscallResult { pub fn syscall(param: [usize; 6], user_satp: usize, func: usize, module: usize) -> SyscallResult {
match module { match module {
MODULE_PROCESS => do_process(param, func), MODULE_PROCESS => do_process(param, user_satp, func),
MODULE_TEST_INTERFACE => do_test_interfase(param, func), MODULE_TEST_INTERFACE => do_test_interface(param, user_satp, func),
MODULE_TASK => do_task(param, func), MODULE_TASK => do_task(param, func),
_ => panic!("Unknown module {:x}", module), _ => panic!("Unknown module {:x}", module),
} }
@ -51,41 +39,44 @@ fn switch_next_task(param: [usize; 6], func: usize) -> SyscallResult {
todo!() todo!()
} }
fn do_process(param: [usize; 6], func: usize) -> SyscallResult { fn do_process(param: [usize; 6], user_satp: usize, func: usize) -> SyscallResult {
match func { match func {
FUNC_PROCESS_EXIT => SyscallResult::Terminate(param[0] as i32), FUNC_PROCESS_EXIT => SyscallResult::Terminate(param[0] as i32),
FUNC_PROCESS_PANIC => panic!("User panic!"), FUNC_PROCESS_PANIC => { //[line as usize, col as usize, f_buf, f_len, m_buf, m_len]
let [line, col, f_buf, f_len, m_buf, m_len] = param;
let user_satp = crate::memory::Satp::new(user_satp);
let file_name = if f_buf == 0 {
None
} else {
let slice = unsafe { get_user_buf(user_satp, f_buf, f_len) };
Some(core::str::from_utf8(slice).unwrap())
};
let msg = if m_buf == 0 {
None
} else {
let slice = unsafe { get_user_buf(user_satp, m_buf, m_len) };
Some(core::str::from_utf8(slice).unwrap())
};
let file_name = file_name.unwrap_or("<no file>");
let msg = msg.unwrap_or("<no message>");
println!("[Kernel] User process panicked at '{}', {}:{}:{}", msg, file_name, line, col);
SyscallResult::Terminate(-1)
},
_ => panic!("Unknown syscall process, func: {}, param: {:?}", func, param) _ => panic!("Unknown syscall process, func: {}, param: {:?}", func, param)
} }
} }
fn do_test_interfase(param: [usize; 6], func: usize) -> SyscallResult { fn do_test_interface(param: [usize; 6], user_satp: usize, func: usize) -> SyscallResult {
match func { match func {
FUNC_TEST_WRITE => { FUNC_TEST_WRITE => {
let (asid, _fd, buf_ptr, buf_len) = let (_iface, buf_ptr, buf_len) =
(param[0], param[1], param[2], param[3]); // 地址空间参数,文件描述符,缓冲区指针,缓冲区长度 (param[0], param[1], param[2]); // 调试接口编号,缓冲区指针,缓冲区长度
// println!("[kernel] enter do_test_write with asid: {}, buf_ptr: {:#x}, buf_len: {}", asid, buf_ptr, buf_len); let user_satp = crate::memory::Satp::new(user_satp);
let user_asid = unsafe { AddressSpaceId::from_raw(asid) }; let slice = unsafe { get_user_buf(user_satp, buf_ptr, buf_len) };
if let Some(user_satp) = KernelHartInfo::get_satp(user_asid) { for &byte in slice {
let offset = buf_ptr.get_bits(0..12); // Sv39 里面虚拟地址偏移量为低 12 位 crate::sbi::console_putchar(byte as usize);
let vpn = VirtualPageNumber::floor(VirtualAddress(buf_ptr));
let ppn = user_satp.translate(vpn).unwrap();
unsafe {
let ptr = (ppn
.start_address()
.0
.wrapping_add(KERNEL_MAP_OFFSET)
.wrapping_add(offset) as *const u8)
.as_ref()
.unwrap();
let slice = core::slice::from_raw_parts(ptr, buf_len);
let str = core::str::from_utf8(slice).unwrap();
print!("{}", str);
SyscallResult::Procceed {code: 0, extra: buf_len}
}
} else {
panic!("User asid not found!")
} }
SyscallResult::Procceed { code: 0, extra: buf_len }
}, },
_ => panic!("Unknown syscall test, func: {}, param: {:?}", func, param) _ => panic!("Unknown syscall test, func: {}, param: {:?}", func, param)
} }
@ -93,4 +84,14 @@ fn do_test_interfase(param: [usize; 6], func: usize) -> SyscallResult {
fn do_task(param: [usize; 6], func: usize) -> SyscallResult { fn do_task(param: [usize; 6], func: usize) -> SyscallResult {
todo!() todo!()
} }
unsafe fn get_user_buf<'a>(user_satp: Satp, buf_ptr: usize, buf_len: usize) -> &'a [u8] {
let offset = buf_ptr.get_bits(0..12); // Sv39 里面虚拟地址偏移量为低 12 位
let vpn = VirtualPageNumber::floor(VirtualAddress(buf_ptr));
let ppn = user_satp.translate(vpn).expect("no page fault");
let va = ppn.start_address().virtual_address_linear()
.0.wrapping_add(offset);
let ptr = (va as *const u8).as_ref().expect("non-null pointer");
core::slice::from_raw_parts(ptr, buf_len)
}

View File

@ -12,8 +12,8 @@ pub extern "C" fn user_trap_handler() {
unsafe { unsafe {
asm!("mv {}, t2", out(reg) user_satp, options(nomem, nostack)); asm!("mv {}, t2", out(reg) user_satp, options(nomem, nostack));
} }
let user_satp = Satp::new(user_satp); let user_satp_2 = Satp::new(user_satp);
let swap_cx = unsafe { get_swap_cx(&user_satp) }; let swap_cx = unsafe { get_swap_cx(&user_satp_2) };
// 从 SwapContext 中读东西 // 从 SwapContext 中读东西
let a0 = swap_cx.x[9]; let a0 = swap_cx.x[9];
let a1 = swap_cx.x[10]; let a1 = swap_cx.x[10];
@ -34,18 +34,17 @@ pub extern "C" fn user_trap_handler() {
crate::sbi::shutdown(); crate::sbi::shutdown();
}, },
Trap::Exception(scause::Exception::UserEnvCall) => { Trap::Exception(scause::Exception::UserEnvCall) => {
let func = a6;
let param = [a0, a1, a2, a3, a4, a5]; let param = [a0, a1, a2, a3, a4, a5];
match syscall(param, func, a7) { match syscall(param, user_satp, a6, a7) {
SyscallResult::Procceed { code, extra} => { SyscallResult::Procceed { code, extra} => {
swap_cx.x[9] = code; swap_cx.x[9] = code;
swap_cx.x[10] = extra; swap_cx.x[10] = extra;
swap_cx.epc = swap_cx.epc.wrapping_add(4); swap_cx.epc = swap_cx.epc.wrapping_add(4);
trap::switch_to_user(swap_cx, user_satp.inner()) trap::switch_to_user(swap_cx, user_satp)
}, },
SyscallResult::Retry => { SyscallResult::Retry => {
// 不跳过指令,继续运行 // 不跳过指令,继续运行
trap::switch_to_user(swap_cx, user_satp.inner()) trap::switch_to_user(swap_cx, user_satp)
}, },
SyscallResult::NextASID{ satp } => { SyscallResult::NextASID{ satp } => {
// 需要转到目标地址空间去运行 // 需要转到目标地址空间去运行

View File

@ -1,4 +1,4 @@
use crate::task::{TaskResult, SharedTaskHandle, KernelTask}; use crate::task::{TaskResult, 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}};

View File

@ -265,9 +265,9 @@ fn breakpoint(trap_frame: &mut TrapFrame) -> *mut TrapFrame {
} }
fn syscall(trap_frame: &mut TrapFrame) -> *mut TrapFrame { fn syscall(trap_frame: &mut TrapFrame) -> *mut TrapFrame {
println!("Syscall at {:#08x}", trap_frame.sepc); println!("Syscall at {:#08x}; note that user_satp /*todo*/", trap_frame.sepc);
let param = [trap_frame.x[10], trap_frame.x[11], 0, 0, 0, 0]; // a0, a1 let param = [trap_frame.x[10], trap_frame.x[11], 0, 0, 0, 0]; // a0, a1
match do_syscall(param, trap_frame.x[16], trap_frame.x[17]) { // a6, a7 match do_syscall(param, 0/* todo */, trap_frame.x[16], trap_frame.x[17]) { // a6, a7
SyscallResult::Procceed { code, extra } => { SyscallResult::Procceed { code, extra } => {
trap_frame.x[10] = code; // a0 trap_frame.x[10] = code; // a0
trap_frame.x[11] = extra; // a1 trap_frame.x[11] = extra; // a1

View File

@ -0,0 +1,20 @@
#![no_std]
#![no_main]
#![feature(asm)]
#![feature(llvm_asm)]
extern crate alloc;
#[macro_use]
extern crate tornado_user;
use alloc::vec;
// 同步函数的例子没有调用execute_async_main
#[no_mangle]
fn main() -> i32 {
println!("[user] enter main!");
let mut test_v = vec![1, 2, 3, 4, 5];
test_v.iter_mut().for_each(|x| *x += 1);
assert_eq!(test_v, vec![2, 3, 4, 5, 6]);
println!("[User] alloc-test: success!");
0
}

View File

@ -1,75 +1,65 @@
#![no_std] #![no_std]
#![no_main] #![no_main]
#![feature(asm)] #![feature(asm)]
#![feature(llvm_asm)] #![feature(llvm_asm)]
extern crate alloc; extern crate alloc;
#[macro_use] #[macro_use]
extern crate tornado_user; extern crate tornado_user;
use alloc::vec; use core::future::Future;
use core::future::Future; use core::task::{Context, Poll};
use core::task::{Context, Poll}; use core::pin::Pin;
use core::pin::Pin;
use tornado_user::{ async fn async_main() -> i32 {
SHARED_PAYLOAD_BASE, // todo: 唤醒逻辑
shared, tornado_user::spawn(async {
task, let ans = FibonacciFuture::new(5).await;
exit, println!("[User] Fibonacci[5] = {}", ans);
}; });
let ans = FibonacciFuture::new(6).await;
#[no_mangle] println!("[User] Fibonacci[6] = {}", ans);
fn main() -> ! { 0
let mut test_v = vec![1, 2, 3, 4, 5]; }
test_v.iter_mut().for_each(|x| *x += 1);
assert_eq!(test_v, vec![2, 3, 4, 5, 6]); // 异步main函数由entry调用execute_async_main
let shared_payload = unsafe { shared::SharedPayload::new(SHARED_PAYLOAD_BASE) }; #[no_mangle]
let task = task::UserTask::new(FibonacciFuture::new(6)); fn main() -> i32 {
unsafe { tornado_user::execute_async_main(async_main())
/* todo: hart_id, asid */ }
shared_payload.add_task(0, tornado_user::shared::AddressSpaceId::from_raw(tornado_user::ADDRESS_SPACE_ID), task.task_repr());
}
struct FibonacciFuture {
shared::run_until_idle( a: usize,
|| unsafe { shared_payload.peek_task(shared::user_should_switch) }, b: usize,
|task_repr| unsafe { shared_payload.delete_task(task_repr) } i: usize,
); cnt: usize
// 用户态退出的系统调用 }
exit(0);
unreachable!() impl FibonacciFuture {
} fn new(cnt: usize) -> FibonacciFuture {
FibonacciFuture {
struct FibonacciFuture { a: 0,
a: usize, b: 1,
b: usize, i: 0,
i: usize, cnt
cnt: usize }
} }
}
impl FibonacciFuture {
fn new(cnt: usize) -> FibonacciFuture { impl Future for FibonacciFuture {
FibonacciFuture { type Output = usize;
a: 0, fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
b: 1, if self.i == self.cnt {
i: 0, println!("Fibonacci {} result: {}", self.cnt, self.a);
cnt Poll::Ready(self.a)
} } else {
} let t = self.a;
} self.a += self.b;
self.b = t;
impl Future for FibonacciFuture { self.i += 1;
type Output = (); println!("Fibonacci {}: i = {}, a = {}, b = {}", self.cnt, self.i, self.a, self.b);
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { cx.waker().wake_by_ref();
if self.i == self.cnt { Poll::Pending
println!("Fibonacci result: {}", self.a); }
Poll::Ready(()) }
} else { }
let t = self.a;
self.a += self.b;
self.b = t;
self.i += 1;
println!("Fibonacci: i = {}, a = {}, b = {}", self.i, self.a, self.b);
cx.waker().wake_by_ref();
Poll::Pending
}
}
}

View File

@ -0,0 +1,27 @@
use core::fmt::{self, Write};
use super::test_write;
struct Stdout;
impl Write for Stdout {
fn write_str(&mut self, s: &str) -> fmt::Result {
test_write(s.as_bytes());
Ok(())
}
}
pub fn print(args: fmt::Arguments) {
Stdout.write_fmt(args).unwrap();
}
#[macro_export]
macro_rules! print {
($fmt: literal $(, $($arg: tt)+)?) => {
$crate::console::print(format_args!($fmt $(, $($arg)+)?));
}
}
#[macro_export]
macro_rules! println {
($fmt: literal $(, $($arg: tt)+)?) => {
$crate::console::print(format_args!(concat!($fmt, "\n") $(, $($arg)+)?));
}
}

View File

@ -7,65 +7,108 @@
extern crate alloc; extern crate alloc;
#[macro_use]
pub mod console;
pub mod shared; pub mod shared;
pub mod task; pub mod task;
use buddy_system_allocator::LockedHeap; use buddy_system_allocator::LockedHeap;
use core::future::Future;
const USER_HEAP_SIZE: usize = 64 * 1024;
const USER_HEAP_SIZE: usize = 32768;
pub static mut ADDRESS_SPACE_ID: usize = 0;
pub static mut SHARED_PAYLOAD_BASE: usize = 0;
static mut HEAP_SPACE: [u8; USER_HEAP_SIZE] = [0; USER_HEAP_SIZE]; static mut HEAP_SPACE: [u8; USER_HEAP_SIZE] = [0; USER_HEAP_SIZE];
static mut SHARED_PAYLOAD_BASE: usize = 0;
static mut ADDRESS_SPACE_ID: usize = 0;
#[global_allocator] #[global_allocator]
static HEAP: LockedHeap = LockedHeap::empty(); static HEAP: LockedHeap = LockedHeap::empty();
#[cfg_attr(not(test), panic_handler)] #[cfg_attr(not(test), panic_handler)]
pub fn panic_handler(_panic_info: &core::panic::PanicInfo) -> ! { pub fn panic_handler(panic_info: &core::panic::PanicInfo) -> ! {
sys_panic(); let err = panic_info.message().unwrap().as_str();
if let Some(location) = panic_info.location() {
syscall::sys_panic(Some(location.file()), location.line(), location.column(), err);
} else {
syscall::sys_panic(None, 0, 0, err);
}
unreachable!() unreachable!()
} }
#[cfg_attr(not(test), alloc_error_handler)] #[cfg_attr(not(test), alloc_error_handler)]
pub fn handle_alloc_error(_layout: core::alloc::Layout) -> ! { pub fn handle_alloc_error(layout: core::alloc::Layout) -> ! {
sys_panic(); println!("[User] user alloc error, layout = {:?}", layout);
unreachable!() panic!("user alloc error: {:?}", layout)
} }
#[no_mangle] #[no_mangle]
#[link_section = ".text.entry"] #[link_section = ".text.entry"]
pub extern "C" fn _start() -> ! { pub extern "C" fn _start() -> ! {
let mut ret: usize; let mut address_space_id: usize;
let mut shared_payload_base: usize;
unsafe { unsafe {
// 从 gp 寄存器里面取出 shared_raw_table 的地址 // 从 gp 寄存器里面取出 shared_raw_table 的地址
asm!("mv {}, gp", out(reg) ret, options(nomem, nostack)); asm!("mv {}, gp", out(reg) shared_payload_base, options(nomem, nostack));
SHARED_PAYLOAD_BASE = ret; SHARED_PAYLOAD_BASE = shared_payload_base;
// 从 tp 寄存器里面取出该用户态的地址空间编号 // 从 tp 寄存器里面取出该用户态的地址空间编号
asm!("mv {}, tp", out(reg) ret, options(nomem, nostack)); asm!("mv {}, tp", out(reg) address_space_id, options(nomem, nostack));
ADDRESS_SPACE_ID = ret; ADDRESS_SPACE_ID = address_space_id;
extern "C" { }
fn sbss(); fn ebss(); extern "C" {
} fn sbss(); fn ebss();
}
unsafe {
r0::zero_bss(&mut sbss as *mut _ as *mut u32, &mut ebss as *mut _ as *mut u32); r0::zero_bss(&mut sbss as *mut _ as *mut u32, &mut ebss as *mut _ as *mut u32);
HEAP.lock().init(HEAP_SPACE.as_ptr() as usize, USER_HEAP_SIZE); HEAP.lock().init(HEAP_SPACE.as_ptr() as usize, USER_HEAP_SIZE);
} }
main() let exit_code = main();
exit(exit_code);
unreachable!()
} }
#[linkage = "weak"] #[linkage = "weak"]
#[link_section = ".text"] // 必须指定否则llvm好像会把名字为“entry”的函数链接到最开始……
#[no_mangle] #[no_mangle]
fn main() -> ! { fn main() -> i32 {
println!("[User] No main function found; user exit");
panic!("Can not find main!"); panic!("Can not find main!");
} }
/// 运行一个异步的main函数在用户的entry函数里调用
/// 应该作为标准库的一部分,这里使用一个库函数来模拟有标准库的情况
pub fn execute_async_main(main: impl Future<Output = i32> + Send + Sync + 'static) -> i32 {
let shared_payload = unsafe { shared::SharedPayload::new(SHARED_PAYLOAD_BASE) };
let asid = unsafe { shared::AddressSpaceId::from_raw(ADDRESS_SPACE_ID) };
static mut EXIT_CODE: i32 = 0;
let main_task = task::UserTask::new(async move {
unsafe { EXIT_CODE = main.await };
});
unsafe {
shared_payload.add_task(0/* todo */, asid, main_task.task_repr());
}
shared::run_until_ready(
|| unsafe { shared_payload.peek_task(shared::user_should_switch) },
|task_repr| unsafe { shared_payload.delete_task(task_repr) }
);
unsafe { EXIT_CODE }
}
/// 生成一个新的任务
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);
unsafe {
shared_payload.add_task(0/* todo */, asid, task.task_repr());
}
}
use syscall::*; use syscall::*;
pub fn exit(exit_code: i32) -> SyscallResult { sys_exit(exit_code) } pub fn exit(exit_code: i32) -> SyscallResult { sys_exit(exit_code) }
pub fn do_yield(next_asid: usize) -> SyscallResult { sys_yield(next_asid) } pub fn do_yield(next_asid: usize) -> SyscallResult { sys_yield(next_asid) }
pub fn test_write(buf: &[u8]) -> SyscallResult { unsafe { sys_test_write(ADDRESS_SPACE_ID, buf) }} pub fn test_write(buf: &[u8]) -> SyscallResult { sys_test_write(buf) }
mod syscall { mod syscall {
const MODULE_PROCESS: usize = 0x114514; const MODULE_PROCESS: usize = 0x114514;
const MODULE_TEST_INTERFACE: usize = 0x233666; const MODULE_TEST_INTERFACE: usize = 0x233666;
@ -186,51 +229,23 @@ mod syscall {
} }
pub fn sys_exit(exit_code: i32) -> SyscallResult { pub fn sys_exit(exit_code: i32) -> SyscallResult {
syscall_1(MODULE_PROCESS, FUNC_PROCESS_EXIT, exit_code as usize) // 暂时放着,写法不规范 syscall_1(MODULE_PROCESS, FUNC_PROCESS_EXIT, exit_code as usize)
} }
pub fn sys_panic() -> SyscallResult { pub fn sys_panic(file_name: Option<&str>, line: u32, col: u32, msg: Option<&str>) -> SyscallResult {
syscall_0(MODULE_PROCESS, FUNC_PROCESS_PANIC) let (f_buf, f_len) = file_name.map(|s| (s.as_ptr() as usize, s.len())).unwrap_or((0, 0));
} let (m_buf, m_len) = msg.map(|s| (s.as_ptr() as usize, s.len())).unwrap_or((0, 0));
syscall_6(
MODULE_PROCESS, FUNC_PROCESS_PANIC,
[line as usize, col as usize, f_buf, f_len, m_buf, m_len]
)
}
pub fn sys_yield(next_asid: usize) -> SyscallResult { pub fn sys_yield(next_asid: usize) -> SyscallResult {
todo!() todo!()
} }
pub fn sys_test_write(asid: usize, buf: &[u8]) -> SyscallResult { pub fn sys_test_write(buf: &[u8]) -> SyscallResult {
syscall_4(MODULE_TEST_INTERFACE, FUNC_TEST_WRITE, [asid, 0, buf.as_ptr() as usize, buf.len()]) syscall_3(MODULE_TEST_INTERFACE, FUNC_TEST_WRITE, [0, buf.as_ptr() as usize, buf.len()])
} }
} }
#[macro_use]
pub mod console {
use core::fmt::{self, Write};
use super::test_write;
struct Stdout;
impl Write for Stdout {
fn write_str(&mut self, s: &str) -> fmt::Result {
test_write(s.as_bytes());
Ok(())
}
}
pub fn print(args: fmt::Arguments) {
Stdout.write_fmt(args).unwrap();
}
#[macro_export]
macro_rules! print {
($fmt: literal $(, $($arg: tt)+)?) => {
$crate::console::print(format_args!($fmt $(, $($arg)+)?));
}
}
#[macro_export]
macro_rules! println {
($fmt: literal $(, $($arg: tt)+)?) => {
$crate::console::print(format_args!(concat!($fmt, "\n") $(, $($arg)+)?));
}
}
}

View File

@ -1,123 +1,121 @@
use crate::do_yield; use crate::do_yield;
use crate::println; use crate::println;
// 尝试在用户态给共享调度器添加任务 // 尝试在用户态给共享调度器添加任务
use super::task::{TaskResult, UserTask}; use super::task::{TaskResult, UserTask};
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}};
use core::ptr::NonNull; use core::ptr::NonNull;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(C)] #[repr(C)]
pub struct SharedTaskHandle { pub struct SharedTaskHandle {
/// 处理核编号 /// 处理核编号
pub(crate) hart_id: usize, pub(crate) hart_id: usize,
/// 地址空间编号 /// 地址空间编号
pub(crate) address_space_id: AddressSpaceId, pub(crate) address_space_id: AddressSpaceId,
/// task_ptr 是 Arc<Task> 的虚拟地址 /// task_ptr 是 Arc<Task> 的虚拟地址
pub(crate) task_ptr: usize, 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);
impl AddressSpaceId { impl AddressSpaceId {
// todo: 可见性 // todo: 可见性
pub unsafe fn from_raw(asid: usize) -> AddressSpaceId { pub unsafe fn from_raw(asid: usize) -> AddressSpaceId {
AddressSpaceId(asid as u16) AddressSpaceId(asid as u16)
} }
} }
pub extern "C" fn user_should_switch(_handle: &SharedTaskHandle) -> bool { pub extern "C" fn user_should_switch(_handle: &SharedTaskHandle) -> bool {
false false
} }
// 该执行器目前是测试使用,当轮询到一个完成的任务就退出了 // 该执行器目前是测试使用,当轮询到一个完成的任务就退出了
pub fn run_until_idle( 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,
) { ) {
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) => { // 在相同的地址空间里面
// 在相同的(内核)地址空间里面 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);
task.mark_sleep(); let mut context = Context::from_waker(&*waker);
// make a waker for our task println!(">>> User executor: task = {:p}", task);
let waker = waker_ref(&task); let ret = task.future.lock().as_mut().poll(&mut context);
// poll our future and give it a waker if let Poll::Pending = ret {
let mut context = Context::from_waker(&*waker); mem::forget(task); // 不要释放task的内存它将继续保存在内存中被使用
} else {
let ret = task.future.lock().as_mut().poll(&mut context); delete_task(task_repr);
if let Poll::Pending = ret { }
mem::forget(task); // 不要释放task的内存它将继续保存在内存中被使用 },
} else { TaskResult::ShouldYield(next_asid) => {
delete_task(task_repr); // 让出操作
} do_yield(next_asid);
}, },
TaskResult::ShouldYield(next_asid) => { TaskResult::Finished => {
// 让出操作 break;
do_yield(next_asid); }
}, }
TaskResult::Finished => break }
} }
}
} /// 共享载荷
#[repr(C)]
/// 共享载荷 pub struct SharedPayload {
#[repr(C)] shared_scheduler: NonNull<()>,
pub struct SharedPayload { shared_add_task: unsafe extern "C" fn(NonNull<()>, usize, AddressSpaceId, usize) -> bool,
shared_scheduler: NonNull<()>, shared_peek_task: unsafe extern "C" fn(NonNull<()>, extern "C" fn(&SharedTaskHandle) -> bool) -> TaskResult,
shared_add_task: unsafe extern "C" fn(NonNull<()>, usize, AddressSpaceId, usize) -> bool, shared_delete_task: unsafe extern "C" fn(NonNull<()>, usize) -> bool,
shared_peek_task: unsafe extern "C" fn(NonNull<()>, extern "C" fn(&SharedTaskHandle) -> bool) -> TaskResult, }
shared_delete_task: unsafe extern "C" fn(NonNull<()>, usize) -> bool,
} type SharedPayloadAsUsize = [usize; 6]; // 编译时基地址,(已清空)初始化函数,共享调度器地址,添加函数,弹出函数
type SharedPayloadRaw = (
type SharedPayloadAsUsize = [usize; 6]; // 编译时基地址,(已清空)初始化函数,共享调度器地址,添加函数,弹出函数 usize, // 编译时基地址,转换后类型占位,不使用
type SharedPayloadRaw = ( usize, // 初始化函数已清空,不适用
usize, // 编译时基地址,转换后类型占位,不使用 NonNull<()>,
usize, // 初始化函数已清空,不适用 unsafe extern "C" fn(NonNull<()>, usize, AddressSpaceId, usize) -> bool,
NonNull<()>, unsafe extern "C" fn(NonNull<()>, extern "C" fn(&SharedTaskHandle) -> bool) -> TaskResult,
unsafe extern "C" fn(NonNull<()>, usize, AddressSpaceId, usize) -> bool, unsafe extern "C" fn(NonNull<()>, usize) -> bool,
unsafe extern "C" fn(NonNull<()>, extern "C" fn(&SharedTaskHandle) -> bool) -> TaskResult, );
unsafe extern "C" fn(NonNull<()>, usize) -> bool,
); impl SharedPayload {
pub unsafe fn new(base: usize) -> Self {
impl SharedPayload { let mut payload_usize = *(base as *const SharedPayloadAsUsize);
pub unsafe fn new(base: usize) -> Self { let compiled_offset = payload_usize[0];
let mut payload_usize = *(base as *const SharedPayloadAsUsize); for (i, idx) in payload_usize.iter_mut().enumerate() {
let compiled_offset = payload_usize[0]; if i == 0 || i == 1 {
for (i, idx) in payload_usize.iter_mut().enumerate() { continue
if i == 0 || i == 1 { }
continue *idx = idx.wrapping_sub(compiled_offset).wrapping_add(base);
} }
*idx = idx.wrapping_sub(compiled_offset).wrapping_add(base); let raw_table: SharedPayloadRaw = mem::transmute(payload_usize);
} Self {
let raw_table: SharedPayloadRaw = mem::transmute(payload_usize); shared_scheduler: raw_table.2,
Self { shared_add_task: raw_table.3,
shared_scheduler: raw_table.2, shared_peek_task: raw_table.4,
shared_add_task: raw_table.3, shared_delete_task: raw_table.5,
shared_peek_task: raw_table.4, }
shared_delete_task: raw_table.5, }
}
} pub unsafe fn add_task(&self, hart_id: usize, address_space_id: AddressSpaceId, task_repr: usize) -> bool {
let f = self.shared_add_task;
pub unsafe fn add_task(&self, hart_id: usize, address_space_id: AddressSpaceId, task_repr: usize) -> bool { f(self.shared_scheduler, hart_id, address_space_id, task_repr)
let f = self.shared_add_task; }
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 {
let f = self.shared_peek_task;
pub unsafe fn peek_task(&self, should_yield: extern "C" fn(&SharedTaskHandle) -> bool) -> TaskResult { f(self.shared_scheduler, should_yield)
let f = self.shared_peek_task; }
f(self.shared_scheduler, should_yield)
} pub unsafe fn delete_task(&self, task_repr: usize) -> bool {
let f = self.shared_delete_task;
pub unsafe fn delete_task(&self, task_repr: usize) -> bool { f(self.shared_scheduler, task_repr)
let f = self.shared_delete_task; }
f(self.shared_scheduler, task_repr) }
}
}

View File

@ -13,15 +13,12 @@ use core::pin::Pin;
use alloc::boxed::Box; use alloc::boxed::Box;
use core::future::Future; use core::future::Future;
use core::sync::atomic::{AtomicUsize, Ordering}; use core::sync::atomic::{AtomicUsize, Ordering};
use super::shared::{AddressSpaceId};
/// 临时的用户态任务实现 /// 临时的用户态任务实现
pub struct UserTask { pub struct UserTask {
/// 任务的编号 /// 任务的编号
pub id: UserTaskId, pub id: UserTaskId,
/// 任务所属的地址空间
pub asid: AddressSpaceId,
/// 任务信息的可变部分 /// 任务信息的可变部分
pub inner: Mutex<UserTaskInner>, pub inner: Mutex<UserTaskInner>,
/// 任务的 future /// 任务的 future
@ -64,7 +61,6 @@ impl UserTask {
Arc::new( Arc::new(
UserTask { UserTask {
id, id,
asid: unsafe { AddressSpaceId::from_raw(crate::ADDRESS_SPACE_ID) },
inner: Mutex::new(UserTaskInner { inner: Mutex::new(UserTaskInner {
sleeping: false, sleeping: false,
finished: false, finished: false,