From 1d110c86fb2eb0b6fda396a0c00bbd6beb20549d Mon Sep 17 00:00:00 2001 From: luojia65 Date: Sat, 24 Apr 2021 22:15:24 +0800 Subject: [PATCH 1/5] Reformat user library --- tornado-kernel/src/syscall/mod.rs | 80 ++++++++------ tornado-kernel/src/syscall/user_syscall.rs | 11 +- tornado-kernel/src/task/executor.rs | 2 +- tornado-kernel/src/trap/handler.rs | 4 +- tornado-user/src/bin/alloc-test.rs | 20 ++++ tornado-user/src/bin/user_task.rs | 43 +++----- tornado-user/src/console.rs | 27 +++++ tornado-user/src/lib.rs | 121 +++++++++++---------- tornado-user/src/shared.rs | 22 ++-- tornado-user/src/task.rs | 9 +- 10 files changed, 190 insertions(+), 149 deletions(-) create mode 100644 tornado-user/src/bin/alloc-test.rs create mode 100644 tornado-user/src/console.rs diff --git a/tornado-kernel/src/syscall/mod.rs b/tornado-kernel/src/syscall/mod.rs index 0b4f4bd..84e1a9d 100644 --- a/tornado-kernel/src/syscall/mod.rs +++ b/tornado-kernel/src/syscall/mod.rs @@ -18,7 +18,7 @@ use crate::{ KERNEL_MAP_OFFSET } }; - +use riscv::register::sstatus; use bit_field::BitField; pub enum SyscallResult { @@ -34,10 +34,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 { - MODULE_PROCESS => do_process(param, func), - MODULE_TEST_INTERFACE => do_test_interfase(param, func), + MODULE_PROCESS => do_process(param, user_satp, func), + MODULE_TEST_INTERFACE => do_test_interface(param, user_satp, func), MODULE_TASK => do_task(param, func), _ => panic!("Unknown module {:x}", module), } @@ -51,41 +51,44 @@ fn switch_next_task(param: [usize; 6], func: usize) -> SyscallResult { todo!() } -fn do_process(param: [usize; 6], func: usize) -> SyscallResult { +fn do_process(param: [usize; 6], user_satp: usize, func: usize) -> SyscallResult { match func { 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(""); + let msg = msg.unwrap_or(""); + println!("[Kernel] User process panicked at '{}', {}:{}:{}", msg, file_name, line, col); + SyscallResult::Terminate(-1) + }, _ => 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 { - FUNC_TEST_WRITE => { - let (asid, _fd, buf_ptr, buf_len) = - (param[0], param[1], param[2], param[3]); // 地址空间参数,文件描述符,缓冲区指针,缓冲区长度 - // println!("[kernel] enter do_test_write with asid: {}, buf_ptr: {:#x}, buf_len: {}", asid, buf_ptr, buf_len); - let user_asid = unsafe { AddressSpaceId::from_raw(asid) }; - if let Some(user_satp) = KernelHartInfo::get_satp(user_asid) { - let offset = buf_ptr.get_bits(0..12); // Sv39 里面虚拟地址偏移量为低 12 位 - 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!") + FUNC_TEST_WRITE => { + let (_iface, buf_ptr, buf_len) = + (param[0], param[1], param[2]); // 调试接口编号,缓冲区指针,缓冲区长度 + let user_satp = crate::memory::Satp::new(user_satp); + let slice = unsafe { get_user_buf(user_satp, buf_ptr, buf_len) }; + for &byte in slice { + crate::sbi::console_putchar(byte as usize); } + SyscallResult::Procceed { code: 0, extra: buf_len } }, _ => panic!("Unknown syscall test, func: {}, param: {:?}", func, param) } @@ -93,4 +96,17 @@ fn do_test_interfase(param: [usize; 6], func: usize) -> SyscallResult { fn do_task(param: [usize; 6], func: usize) -> SyscallResult { todo!() -} \ No newline at end of file +} + +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 slice = unsafe { + let ptr = (va as *const u8).as_ref().expect("non-null pointer"); + core::slice::from_raw_parts(ptr, buf_len) + }; + slice +} diff --git a/tornado-kernel/src/syscall/user_syscall.rs b/tornado-kernel/src/syscall/user_syscall.rs index 0beb89a..77606b5 100644 --- a/tornado-kernel/src/syscall/user_syscall.rs +++ b/tornado-kernel/src/syscall/user_syscall.rs @@ -12,8 +12,8 @@ pub extern "C" fn user_trap_handler() { unsafe { asm!("mv {}, t2", out(reg) user_satp, options(nomem, nostack)); } - let user_satp = Satp::new(user_satp); - let swap_cx = unsafe { get_swap_cx(&user_satp) }; + let user_satp_2 = Satp::new(user_satp); + let swap_cx = unsafe { get_swap_cx(&user_satp_2) }; // 从 SwapContext 中读东西 let a0 = swap_cx.x[9]; let a1 = swap_cx.x[10]; @@ -34,18 +34,17 @@ pub extern "C" fn user_trap_handler() { crate::sbi::shutdown(); }, Trap::Exception(scause::Exception::UserEnvCall) => { - let func = a6; let param = [a0, a1, a2, a3, a4, a5]; - match syscall(param, func, a7) { + match syscall(param, user_satp, a6, a7) { SyscallResult::Procceed { code, extra} => { swap_cx.x[9] = code; swap_cx.x[10] = extra; 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 => { // 不跳过指令,继续运行 - trap::switch_to_user(swap_cx, user_satp.inner()) + trap::switch_to_user(swap_cx, user_satp) }, SyscallResult::NextASID{ satp } => { // 需要转到目标地址空间去运行 diff --git a/tornado-kernel/src/task/executor.rs b/tornado-kernel/src/task/executor.rs index d7519c5..3723ffc 100644 --- a/tornado-kernel/src/task/executor.rs +++ b/tornado-kernel/src/task/executor.rs @@ -1,4 +1,4 @@ -use crate::task::{TaskResult, SharedTaskHandle, KernelTask}; +use crate::task::{TaskResult, KernelTask}; use woke::waker_ref; use alloc::sync::Arc; use core::{mem, task::{Poll, Context}}; diff --git a/tornado-kernel/src/trap/handler.rs b/tornado-kernel/src/trap/handler.rs index 4c5568c..b1d01f5 100644 --- a/tornado-kernel/src/trap/handler.rs +++ b/tornado-kernel/src/trap/handler.rs @@ -265,9 +265,9 @@ fn breakpoint(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 - 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 } => { trap_frame.x[10] = code; // a0 trap_frame.x[11] = extra; // a1 diff --git a/tornado-user/src/bin/alloc-test.rs b/tornado-user/src/bin/alloc-test.rs new file mode 100644 index 0000000..5dde8ae --- /dev/null +++ b/tornado-user/src/bin/alloc-test.rs @@ -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 entry() -> 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 +} diff --git a/tornado-user/src/bin/user_task.rs b/tornado-user/src/bin/user_task.rs index 3a829c4..df9c242 100644 --- a/tornado-user/src/bin/user_task.rs +++ b/tornado-user/src/bin/user_task.rs @@ -6,40 +6,23 @@ extern crate alloc; #[macro_use] extern crate tornado_user; -use alloc::vec; use core::future::Future; use core::task::{Context, Poll}; use core::pin::Pin; -use tornado_user::{ - SHARED_PAYLOAD_BASE, - shared, - task, - exit, -}; -#[no_mangle] -fn main() -> ! { - 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]); - let shared_payload = unsafe { shared::SharedPayload::new(SHARED_PAYLOAD_BASE) }; - let task = task::UserTask::new(FibonacciFuture::new(6)); - unsafe { - /* todo: hart_id, asid */ - shared_payload.add_task(0, tornado_user::shared::AddressSpaceId::from_raw(tornado_user::ADDRESS_SPACE_ID), task.task_repr()); - } - - let ret = shared::run_until_ready( - || unsafe { shared_payload.peek_task(shared::user_should_switch) }, - |task_repr| unsafe { shared_payload.delete_task(task_repr) } - ); - assert_eq!(ret, Some(8)); - // 用户态退出的系统调用 - exit(0); - unreachable!() +async fn main() -> i32 { + let ans = FibonacciFuture::new(6).await; + println!("[User] Fibonacci[6] = {}", ans); + 0 } +// 异步main函数,由entry调用execute_async_main +#[no_mangle] +pub fn entry() -> i32 { + tornado_user::execute_async_main(main()) +} + + struct FibonacciFuture { a: usize, b: usize, @@ -62,14 +45,16 @@ impl Future for FibonacciFuture { type Output = usize; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { if self.i == self.cnt { + println!("Fibonacci result: {}", self.a); Poll::Ready(self.a) } 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 } } -} \ No newline at end of file +} diff --git a/tornado-user/src/console.rs b/tornado-user/src/console.rs new file mode 100644 index 0000000..6797cce --- /dev/null +++ b/tornado-user/src/console.rs @@ -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)+)?)); + } +} diff --git a/tornado-user/src/lib.rs b/tornado-user/src/lib.rs index aad71b2..af260f9 100644 --- a/tornado-user/src/lib.rs +++ b/tornado-user/src/lib.rs @@ -7,45 +7,55 @@ extern crate alloc; +#[macro_use] +pub mod console; pub mod shared; pub mod task; use buddy_system_allocator::LockedHeap; +use core::future::Future; - -const USER_HEAP_SIZE: usize = 32768; - -pub static mut ADDRESS_SPACE_ID: usize = 0; -pub static mut SHARED_PAYLOAD_BASE: usize = 0; +const USER_HEAP_SIZE: usize = 64 * 1024; 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] static HEAP: LockedHeap = LockedHeap::empty(); #[cfg_attr(not(test), panic_handler)] -pub fn panic_handler(_panic_info: &core::panic::PanicInfo) -> ! { - sys_panic(); +pub fn panic_handler(panic_info: &core::panic::PanicInfo) -> ! { + 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!() } #[cfg_attr(not(test), alloc_error_handler)] -pub fn handle_alloc_error(_layout: core::alloc::Layout) -> ! { - sys_panic(); - unreachable!() +pub fn handle_alloc_error(layout: core::alloc::Layout) -> ! { + println!("[User] user alloc error, layout = {:?}", layout); + panic!("user alloc error: {:?}", layout) } #[no_mangle] #[link_section = ".text.entry"] pub extern "C" fn _start() -> ! { - let mut ret: usize; + let mut address_space_id: usize; + let mut shared_payload_base: usize; unsafe { // 从 gp 寄存器里面取出 shared_raw_table 的地址 - asm!("mv {}, gp", out(reg) ret, options(nomem, nostack)); - SHARED_PAYLOAD_BASE = ret; + asm!("mv {}, gp", out(reg) shared_payload_base, options(nomem, nostack)); // 从 tp 寄存器里面取出该用户态的地址空间编号 - asm!("mv {}, tp", out(reg) ret, options(nomem, nostack)); - ADDRESS_SPACE_ID = ret; + asm!("mv {}, tp", out(reg) address_space_id, options(nomem, nostack)); + } + unsafe { + ADDRESS_SPACE_ID = address_space_id; + SHARED_PAYLOAD_BASE = shared_payload_base; } extern "C" { fn sbss(); fn ebss(); @@ -56,20 +66,45 @@ pub extern "C" fn _start() -> ! { unsafe { HEAP.lock().init(HEAP_SPACE.as_ptr() as usize, USER_HEAP_SIZE); } - main() + let exit_code = entry(); + exit(exit_code); + unreachable!() } #[linkage = "weak"] #[no_mangle] -fn main() -> ! { +fn entry() -> i32 { + println!("[User] No main function found; user exit"); panic!("Can not find main!"); } +/// 运行一个异步的main函数,在用户的entry函数里调用 +/// 应该作为标准库的一部分,这里使用一个库函数来模拟有标准库的情况 +pub fn execute_async_main(main: impl Future + Send + Sync + 'static) -> i32 { + let shared_payload = unsafe { shared::SharedPayload::new(SHARED_PAYLOAD_BASE) }; + let asid = unsafe { shared::AddressSpaceId::from_raw(ADDRESS_SPACE_ID) }; + let exit_code = alloc::sync::Arc::new(spin::Mutex::new(0)); + let exit_code_2 = exit_code.clone(); + let main_task = task::UserTask::new(async move { + *exit_code_2.lock() = 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) } + ); + let ans = *exit_code.lock(); + drop(exit_code); + ans +} + use syscall::*; 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 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 { const MODULE_PROCESS: usize = 0x114514; const MODULE_TEST_INTERFACE: usize = 0x233666; @@ -190,51 +225,23 @@ mod syscall { } 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 { - syscall_0(MODULE_PROCESS, FUNC_PROCESS_PANIC) - } + pub fn sys_panic(file_name: Option<&str>, line: u32, col: u32, msg: Option<&str>) -> SyscallResult { + 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 { todo!() } - pub fn sys_test_write(asid: usize, buf: &[u8]) -> SyscallResult { - syscall_4(MODULE_TEST_INTERFACE, FUNC_TEST_WRITE, [asid, 0, buf.as_ptr() as usize, buf.len()]) + pub fn sys_test_write(buf: &[u8]) -> SyscallResult { + 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)+)?)); - } - } -} \ No newline at end of file diff --git a/tornado-user/src/shared.rs b/tornado-user/src/shared.rs index dfc1811..c06263e 100644 --- a/tornado-user/src/shared.rs +++ b/tornado-user/src/shared.rs @@ -37,27 +37,21 @@ pub extern "C" fn user_should_switch(_handle: &SharedTaskHandle) -> bool { pub fn run_until_ready( peek_task: impl Fn() -> TaskResult, delete_task: impl Fn(usize) -> bool, -) -> Option { - let run_ret; +) { loop { let task = peek_task(); match task { - TaskResult::Task(task_repr) => { - // 在相同的(内核)地址空间里面 + TaskResult::Task(task_repr) => { // 在相同的地址空间里面 let task: Arc = unsafe { Arc::from_raw(task_repr as *mut _) }; - task.mark_sleep(); - // make a waker for our task let waker = waker_ref(&task); - // poll our future and give it a waker let mut context = Context::from_waker(&*waker); - + println!(">>> User executor: task = {:p}", task); let ret = task.future.lock().as_mut().poll(&mut context); - if let Poll::Ready(x) = ret { - run_ret = Some(x); - delete_task(task_repr); - break; - } else { + if let Poll::Pending = ret { mem::forget(task); // 不要释放task的内存,它将继续保存在内存中被使用 + } else { + delete_task(task_repr); + break; // todo, remove } }, TaskResult::ShouldYield(next_asid) => { @@ -65,12 +59,10 @@ pub fn run_until_ready( do_yield(next_asid); }, TaskResult::Finished => { - run_ret = None; break; } } } - run_ret } /// 共享载荷 diff --git a/tornado-user/src/task.rs b/tornado-user/src/task.rs index d99c17f..f0eba59 100644 --- a/tornado-user/src/task.rs +++ b/tornado-user/src/task.rs @@ -13,19 +13,16 @@ use core::pin::Pin; use alloc::boxed::Box; use core::future::Future; use core::sync::atomic::{AtomicUsize, Ordering}; -use super::shared::{SharedTaskHandle, AddressSpaceId}; /// 临时的用户态任务实现 pub struct UserTask { /// 任务的编号 pub id: UserTaskId, - /// 任务所属的地址空间 - pub asid: AddressSpaceId, /// 任务信息的可变部分 pub inner: Mutex, /// 任务的 future - pub future: Mutex + 'static + Send + Sync>>> // 用UnsafeCell代替Mutex会好一点 + pub future: Mutex + 'static + Send + Sync>>> // 用UnsafeCell代替Mutex会好一点 } /// 任务信息的可变部分 @@ -57,7 +54,7 @@ impl UserTaskId { impl UserTask { /// 创建一个用户态任务 pub fn new( - future: impl Future + 'static + Send + Sync, + future: impl Future + 'static + Send + Sync, ) -> Arc { // 得到新的用户任务编号 let id = UserTaskId::generate(); @@ -65,8 +62,6 @@ impl UserTask { Arc::new( UserTask { id, - // todo: 地址空间编号 - asid: unsafe { AddressSpaceId::from_raw(crate::ADDRESS_SPACE_ID) }, inner: Mutex::new(UserTaskInner { sleeping: false, finished: false, From 50088829159dc00df9f36ae16286736a24b801ec Mon Sep 17 00:00:00 2001 From: luojia65 Date: Sat, 24 Apr 2021 23:07:19 +0800 Subject: [PATCH 2/5] Bug fix: LLVM seems to link function with name 'entry' to program entry --- tornado-user/src/bin/alloc-test.rs | 2 +- tornado-user/src/bin/user_task.rs | 6 +++--- tornado-user/src/lib.rs | 18 +++++++----------- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/tornado-user/src/bin/alloc-test.rs b/tornado-user/src/bin/alloc-test.rs index 5dde8ae..b12fb43 100644 --- a/tornado-user/src/bin/alloc-test.rs +++ b/tornado-user/src/bin/alloc-test.rs @@ -10,7 +10,7 @@ use alloc::vec; // 同步函数的例子,没有调用execute_async_main #[no_mangle] -fn entry() -> i32 { +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); diff --git a/tornado-user/src/bin/user_task.rs b/tornado-user/src/bin/user_task.rs index df9c242..3b923aa 100644 --- a/tornado-user/src/bin/user_task.rs +++ b/tornado-user/src/bin/user_task.rs @@ -10,7 +10,7 @@ use core::future::Future; use core::task::{Context, Poll}; use core::pin::Pin; -async fn main() -> i32 { +async fn async_main() -> i32 { let ans = FibonacciFuture::new(6).await; println!("[User] Fibonacci[6] = {}", ans); 0 @@ -18,8 +18,8 @@ async fn main() -> i32 { // 异步main函数,由entry调用execute_async_main #[no_mangle] -pub fn entry() -> i32 { - tornado_user::execute_async_main(main()) +fn main() -> i32 { + tornado_user::execute_async_main(async_main()) } diff --git a/tornado-user/src/lib.rs b/tornado-user/src/lib.rs index af260f9..25534cc 100644 --- a/tornado-user/src/lib.rs +++ b/tornado-user/src/lib.rs @@ -50,12 +50,10 @@ pub extern "C" fn _start() -> ! { unsafe { // 从 gp 寄存器里面取出 shared_raw_table 的地址 asm!("mv {}, gp", out(reg) shared_payload_base, options(nomem, nostack)); + SHARED_PAYLOAD_BASE = shared_payload_base; // 从 tp 寄存器里面取出该用户态的地址空间编号 asm!("mv {}, tp", out(reg) address_space_id, options(nomem, nostack)); - } - unsafe { ADDRESS_SPACE_ID = address_space_id; - SHARED_PAYLOAD_BASE = shared_payload_base; } extern "C" { fn sbss(); fn ebss(); @@ -66,14 +64,15 @@ pub extern "C" fn _start() -> ! { unsafe { HEAP.lock().init(HEAP_SPACE.as_ptr() as usize, USER_HEAP_SIZE); } - let exit_code = entry(); + let exit_code = main(); exit(exit_code); unreachable!() } #[linkage = "weak"] +#[link_section = ".text"] // 必须指定,否则llvm好像会把名字为“entry”的函数链接到最开始…… #[no_mangle] -fn entry() -> i32 { +fn main() -> i32 { println!("[User] No main function found; user exit"); panic!("Can not find main!"); } @@ -83,10 +82,9 @@ fn entry() -> i32 { pub fn execute_async_main(main: impl Future + Send + Sync + 'static) -> i32 { let shared_payload = unsafe { shared::SharedPayload::new(SHARED_PAYLOAD_BASE) }; let asid = unsafe { shared::AddressSpaceId::from_raw(ADDRESS_SPACE_ID) }; - let exit_code = alloc::sync::Arc::new(spin::Mutex::new(0)); - let exit_code_2 = exit_code.clone(); + static mut EXIT_CODE: i32 = 0; let main_task = task::UserTask::new(async move { - *exit_code_2.lock() = main.await; + unsafe { EXIT_CODE = main.await }; }); unsafe { shared_payload.add_task(0/* todo */, asid, main_task.task_repr()); @@ -95,9 +93,7 @@ pub fn execute_async_main(main: impl Future + Send + Sync + 'stati || unsafe { shared_payload.peek_task(shared::user_should_switch) }, |task_repr| unsafe { shared_payload.delete_task(task_repr) } ); - let ans = *exit_code.lock(); - drop(exit_code); - ans + unsafe { EXIT_CODE } } use syscall::*; From d79a28c05f2df16322508d9f93dfa31b85313e90 Mon Sep 17 00:00:00 2001 From: luojia65 Date: Sat, 24 Apr 2021 23:09:42 +0800 Subject: [PATCH 3/5] Code clean-up --- tornado-kernel/src/syscall/mod.rs | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/tornado-kernel/src/syscall/mod.rs b/tornado-kernel/src/syscall/mod.rs index 84e1a9d..5c2f8aa 100644 --- a/tornado-kernel/src/syscall/mod.rs +++ b/tornado-kernel/src/syscall/mod.rs @@ -6,19 +6,7 @@ mod user_syscall; pub use user_syscall::user_trap_handler; use config::*; - -use crate::{ - hart::KernelHartInfo, - memory::{ - AddressSpaceId, - Satp, - VirtualPageNumber, - VirtualAddress, - PhysicalPageNumber, - KERNEL_MAP_OFFSET - } -}; -use riscv::register::sstatus; +use crate::memory::{AddressSpaceId, Satp, VirtualPageNumber, VirtualAddress,}; use bit_field::BitField; pub enum SyscallResult { @@ -104,9 +92,6 @@ unsafe fn get_user_buf<'a>(user_satp: Satp, buf_ptr: usize, buf_len: usize) -> & let ppn = user_satp.translate(vpn).expect("no page fault"); let va = ppn.start_address().virtual_address_linear() .0.wrapping_add(offset); - let slice = unsafe { - let ptr = (va as *const u8).as_ref().expect("non-null pointer"); - core::slice::from_raw_parts(ptr, buf_len) - }; - slice + let ptr = (va as *const u8).as_ref().expect("non-null pointer"); + core::slice::from_raw_parts(ptr, buf_len) } From 7b305f171b483bb5a26a7a65a2c8d618eca3d7a0 Mon Sep 17 00:00:00 2001 From: luojia65 Date: Sat, 24 Apr 2021 23:14:54 +0800 Subject: [PATCH 4/5] Bug fix --- tornado-user/src/bin/user_task.rs | 2 +- tornado-user/src/shared.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tornado-user/src/bin/user_task.rs b/tornado-user/src/bin/user_task.rs index 9f4e79d..b9b7263 100644 --- a/tornado-user/src/bin/user_task.rs +++ b/tornado-user/src/bin/user_task.rs @@ -42,7 +42,7 @@ impl FibonacciFuture { } impl Future for FibonacciFuture { - type Output = (); + type Output = usize; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { if self.i == self.cnt { println!("Fibonacci result: {}", self.a); diff --git a/tornado-user/src/shared.rs b/tornado-user/src/shared.rs index 53cf0f7..ad6e86f 100644 --- a/tornado-user/src/shared.rs +++ b/tornado-user/src/shared.rs @@ -35,7 +35,7 @@ pub extern "C" fn user_should_switch(_handle: &SharedTaskHandle) -> bool { } // 该执行器目前是测试使用,当轮询到一个完成的任务就退出了 -pub fn run_until_idle( +pub fn run_until_ready( peek_task: impl Fn() -> TaskResult, delete_task: impl Fn(usize) -> bool, ) { From 0a05ae056d246c4c7691f11a488dabbc7de91f6e Mon Sep 17 00:00:00 2001 From: luojia65 Date: Sat, 24 Apr 2021 23:19:38 +0800 Subject: [PATCH 5/5] Spawn primitive --- tornado-user/src/bin/user_task.rs | 9 +++++++-- tornado-user/src/lib.rs | 10 ++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/tornado-user/src/bin/user_task.rs b/tornado-user/src/bin/user_task.rs index b9b7263..03b38a5 100644 --- a/tornado-user/src/bin/user_task.rs +++ b/tornado-user/src/bin/user_task.rs @@ -11,6 +11,11 @@ use core::task::{Context, Poll}; use core::pin::Pin; async fn async_main() -> i32 { + // todo: 唤醒逻辑 + tornado_user::spawn(async { + let ans = FibonacciFuture::new(5).await; + println!("[User] Fibonacci[5] = {}", ans); + }); let ans = FibonacciFuture::new(6).await; println!("[User] Fibonacci[6] = {}", ans); 0 @@ -45,14 +50,14 @@ impl Future for FibonacciFuture { type Output = usize; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { if self.i == self.cnt { - println!("Fibonacci result: {}", self.a); + println!("Fibonacci {} result: {}", self.cnt, self.a); Poll::Ready(self.a) } 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); + println!("Fibonacci {}: i = {}, a = {}, b = {}", self.cnt, self.i, self.a, self.b); cx.waker().wake_by_ref(); Poll::Pending } diff --git a/tornado-user/src/lib.rs b/tornado-user/src/lib.rs index ece4cd9..4c5b944 100644 --- a/tornado-user/src/lib.rs +++ b/tornado-user/src/lib.rs @@ -94,6 +94,16 @@ pub fn execute_async_main(main: impl Future + Send + Sync + 'stati unsafe { EXIT_CODE } } +/// 生成一个新的任务 +pub fn spawn(future: impl Future + 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::*; pub fn exit(exit_code: i32) -> SyscallResult { sys_exit(exit_code) }