diff --git a/os/src/main.rs b/os/src/main.rs index f237c194..3801a01e 100644 --- a/os/src/main.rs +++ b/os/src/main.rs @@ -54,6 +54,7 @@ pub fn rust_main() -> ! { trap::enable_timer_interrupt(); timer::set_next_trigger(); task::stackless_coroutine::kernel_stackless_coroutine_test(); + task::kernel_stackful_coroutine_test(); fs::list_apps(); task::add_initproc(); task::run_tasks(); diff --git a/os/src/mm/frame_allocator.rs b/os/src/mm/frame_allocator.rs index 4bc7db26..5121977b 100644 --- a/os/src/mm/frame_allocator.rs +++ b/os/src/mm/frame_allocator.rs @@ -5,6 +5,7 @@ use alloc::vec::Vec; use core::fmt::{self, Debug, Formatter}; use lazy_static::*; +#[derive(Clone)] pub struct FrameTracker { pub ppn: PhysPageNum, } diff --git a/os/src/mm/memory_set.rs b/os/src/mm/memory_set.rs index 0d0b0f1d..e2e10ef6 100644 --- a/os/src/mm/memory_set.rs +++ b/os/src/mm/memory_set.rs @@ -242,8 +242,17 @@ impl MemorySet { //*self = Self::new_bare(); self.areas.clear(); } + + pub fn kernel_copy() -> Self { + let areas = KERNEL_SPACE.exclusive_access().areas.clone(); + Self { + page_table: PageTable::from_token(kernel_token()), + areas: areas, + } + } } +#[derive(Clone)] pub struct MapArea { vpn_range: VPNRange, data_frames: BTreeMap, diff --git a/os/src/task/context.rs b/os/src/task/context.rs index e4f59d8a..73d7b319 100644 --- a/os/src/task/context.rs +++ b/os/src/task/context.rs @@ -2,9 +2,9 @@ use crate::trap::trap_return; #[repr(C)] pub struct TaskContext { - ra: usize, - sp: usize, - s: [usize; 12], + pub ra: usize, + pub sp: usize, + pub s: [usize; 12], } impl TaskContext { @@ -15,6 +15,15 @@ impl TaskContext { s: [0; 12], } } + + pub fn kthread_init() -> Self { + Self { + ra: 0xAAAAAAAA, + sp: 0xBBBBBBBB, + s: [0xCCCCCCCC; 12], + } + } + pub fn goto_trap_return(kstack_ptr: usize) -> Self { Self { ra: trap_return as usize, diff --git a/os/src/task/id.rs b/os/src/task/id.rs index 178a09f6..8257b178 100644 --- a/os/src/task/id.rs +++ b/os/src/task/id.rs @@ -221,3 +221,41 @@ impl Drop for TaskUserRes { self.dealloc_user_res(); } } + +use alloc::alloc::{alloc, dealloc, Layout}; + +#[derive(Clone)] +pub struct KStack(usize); + +const STACK_SIZE: usize = 0x8000; + +impl KStack { + pub fn new() -> KStack { + let bottom = + unsafe { + alloc(Layout::from_size_align(STACK_SIZE, STACK_SIZE).unwrap()) + } as usize; + KStack(bottom) + } + + pub fn top(&self) -> usize { + self.0 + STACK_SIZE + } +} +use core::fmt::{self, Debug, Formatter}; +impl Debug for KStack { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.write_fmt(format_args!("KStack:{:#x}", self.0)) + } +} + +impl Drop for KStack { + fn drop(&mut self) { + unsafe { + dealloc( + self.0 as _, + Layout::from_size_align(STACK_SIZE, STACK_SIZE).unwrap() + ); + } + } +} \ No newline at end of file diff --git a/os/src/task/mod.rs b/os/src/task/mod.rs index 7e8743b6..990b1dce 100644 --- a/os/src/task/mod.rs +++ b/os/src/task/mod.rs @@ -131,3 +131,82 @@ pub fn current_add_signal(signal: SignalFlags) { let mut process_inner = process.inner_exclusive_access(); process_inner.signals |= signal; } + + +#[no_mangle] +pub fn kthread_create(f: fn()) { + + println!("kthread_create"); + + //�����ں��߳� + let new_tcb = TaskControlBlock::create_kthread(f); + // let kernel_stack = new_tcb.get_kernel_stack(); + let new_task = Arc::new(new_tcb); + + //��������������,���û��̷߳���һ�����. + // println!("add task"); + add_task(Arc::clone(&new_task)); +} + +#[no_mangle] +pub fn kernel_stackful_coroutine_test() { + println!("kernel_stackful_coroutine_test"); + kthread_create( || + { + let id = 1; + println!("kernel thread {:?} STARTING", id); + for i in 0..10 { + println!("kernel thread: {} counter: {}", id, i); + } + println!("kernel thread {:?} FINISHED", id); + kthread_stop(); + } + ); + kthread_create( || + { + let id = 2; + println!("kernel thread {:?} STARTING", 2); + for i in 0..10 { + println!("kernel thread: {} counter: {}", 2, i); + kthread_yield(); + } + println!("kernel thread {:?} FINISHED", 2); + kthread_stop(); + } + ); + kthread_create( || + { + let id = 3; + println!("kernel thread {:?} STARTING", 3); + for i in 0..10 { + println!("kernel thread: {} counter: {}", 3, i); + kthread_yield(); + } + println!("kernel thread {:?} FINISHED", 3); + kthread_stop(); + } + ); +} + +pub fn kthread_stop(){ + do_exit(); +} +#[no_mangle] +pub fn do_exit(){ + println!("kthread do exit"); + exit_kthread_and_run_next(0); + panic!("Unreachable in sys_exit!"); +} + +pub fn kthread_yield(){ + suspend_current_and_run_next(); +} + + +#[no_mangle] +pub fn exit_kthread_and_run_next(exit_code: i32) { + println!("exit_kthread_and_run_next"); + // we do not have to save task context + let mut _unused = TaskContext::zero_init(); + schedule(&mut _unused as *mut _); +} \ No newline at end of file diff --git a/os/src/task/process.rs b/os/src/task/process.rs index ffff14fe..28a967e0 100644 --- a/os/src/task/process.rs +++ b/os/src/task/process.rs @@ -256,4 +256,30 @@ impl ProcessControlBlock { pub fn getpid(&self) -> usize { self.pid.0 } + + pub fn kernel_process() -> Arc{ + let memory_set = MemorySet::kernel_copy(); + let process = Arc::new( + ProcessControlBlock { + pid: super::pid_alloc(), + inner: unsafe { + UPSafeCell::new( + ProcessControlBlockInner { + is_zombie: false, + memory_set: memory_set, + parent: None, + children: Vec::new(), + exit_code: 0, + fd_table: Vec::new(), + signals: SignalFlags::empty(), + tasks: Vec::new(), + task_res_allocator: RecycleAllocator::new(), + mutex_list: Vec::new(), + semaphore_list: Vec::new(), + condvar_list: Vec::new(), + }) + }, + }); + process + } } diff --git a/os/src/task/task.rs b/os/src/task/task.rs index 99900de3..839a4e21 100644 --- a/os/src/task/task.rs +++ b/os/src/task/task.rs @@ -23,6 +23,11 @@ impl TaskControlBlock { let inner = process.inner_exclusive_access(); inner.memory_set.token() } + + // pub fn get_kernel_stack(&self) -> usize { + // self.kstack + // } + } pub struct TaskControlBlockInner { @@ -68,6 +73,41 @@ impl TaskControlBlock { }, } } + + pub fn create_kthread(f: fn()) -> Self{ + use crate::mm::{KERNEL_SPACE, PhysPageNum, VirtAddr, PhysAddr}; + let process = ProcessControlBlock::kernel_process(); + let process = Arc::downgrade(&process); + + let kstack = kstack_alloc(); + let kernelstack = crate::task::id::KStack::new(); + let kstack_top = kernelstack.top(); + + let mut context = TaskContext::kthread_init(); + let context_addr = &context as *const TaskContext as usize; + let pa = PhysAddr::from(context_addr); + let context_ppn = pa.floor(); + + context.ra = f as usize; + context.sp = kstack_top; + + println!("context ppn :{:#x?}", context_ppn); + + Self { + process, + kstack, + inner: unsafe { + UPSafeCell::new(TaskControlBlockInner { + res: None, + trap_cx_ppn: context_ppn, + task_cx: context, + task_status: TaskStatus::Ready, + exit_code: None, + }) + }, + } + } + } #[derive(Copy, Clone, PartialEq)]