diff --git a/kernel/src/process/clone.rs b/kernel/src/process/clone.rs index 81e037b76..afc9633cf 100644 --- a/kernel/src/process/clone.rs +++ b/kernel/src/process/clone.rs @@ -260,7 +260,7 @@ fn clone_child_task( // Clone FPU context let child_fpu_context = thread_local.fpu().clone_context(); - let child_user_ctx = Arc::new(clone_user_ctx( + let child_user_ctx = Box::new(clone_user_ctx( parent_context, clone_args.stack, clone_args.stack_size, @@ -327,7 +327,7 @@ fn clone_child_process( }; // Clone the user context - let child_user_ctx = Arc::new(clone_user_ctx( + let child_user_ctx = Box::new(clone_user_ctx( parent_context, clone_args.stack, clone_args.stack_size, diff --git a/kernel/src/process/posix_thread/builder.rs b/kernel/src/process/posix_thread/builder.rs index 5267e9dad..d86e27898 100644 --- a/kernel/src/process/posix_thread/builder.rs +++ b/kernel/src/process/posix_thread/builder.rs @@ -29,7 +29,7 @@ use crate::{ pub struct PosixThreadBuilder { // The essential part tid: Tid, - user_ctx: Arc, + user_ctx: Box, process: Weak, credentials: Credentials, @@ -46,7 +46,7 @@ pub struct PosixThreadBuilder { } impl PosixThreadBuilder { - pub fn new(tid: Tid, user_ctx: Arc, credentials: Credentials) -> Self { + pub fn new(tid: Tid, user_ctx: Box, credentials: Credentials) -> Self { Self { tid, user_ctx, diff --git a/kernel/src/process/process/init_proc.rs b/kernel/src/process/process/init_proc.rs index f278c5d30..c8f3500e9 100644 --- a/kernel/src/process/process/init_proc.rs +++ b/kernel/src/process/process/init_proc.rs @@ -121,7 +121,7 @@ fn create_init_task( user_ctx.set_instruction_pointer(elf_load_info.entry_point as _); user_ctx.set_stack_pointer(elf_load_info.user_stack_top as _); let thread_name = Some(ThreadName::new_from_executable_path(executable_path)?); - let thread_builder = PosixThreadBuilder::new(tid, Arc::new(user_ctx), credentials) + let thread_builder = PosixThreadBuilder::new(tid, Box::new(user_ctx), credentials) .thread_name(thread_name) .process(process) .fs(Arc::new(fs)); diff --git a/kernel/src/thread/task.rs b/kernel/src/thread/task.rs index 3686e80ec..ebc114ecd 100644 --- a/kernel/src/thread/task.rs +++ b/kernel/src/thread/task.rs @@ -23,11 +23,11 @@ use crate::{ /// create new task with userspace and parent process pub fn create_new_user_task( - user_ctx: Arc, + user_ctx: Box, thread_ref: Arc, thread_local: ThreadLocal, ) -> Task { - fn user_task_entry() { + fn user_task_entry(user_ctx: UserContext) { let current_task = Task::current().unwrap(); let current_thread = current_task.as_thread().unwrap(); let current_posix_thread = current_thread.as_posix_thread().unwrap(); @@ -35,10 +35,8 @@ pub fn create_new_user_task( let current_process = current_posix_thread.process(); let (stop_waiter, _) = Waiter::new_pair(); - let user_ctx = current_task - .user_ctx() - .expect("user task should have user context"); - let mut user_mode = UserMode::new(UserContext::clone(user_ctx)); + let mut user_mode = UserMode::new(user_ctx); + user_mode.context_mut().activate_tls_pointer(); debug!( "[Task entry] rip = 0x{:x}", user_mode.context().instruction_pointer() @@ -52,11 +50,10 @@ pub fn create_new_user_task( user_mode.context().syscall_ret() ); - let child_tid_ptr = current_thread_local.set_child_tid().get(); - // The `clone` syscall may require child process to write the thread pid to the specified address. // Make sure the store operation completes before the clone call returns control to user space // in the child process. + let child_tid_ptr = current_thread_local.set_child_tid().get(); if is_userspace_vaddr(child_tid_ptr) { current_userspace!() .write_val(child_tid_ptr, ¤t_posix_thread.tid()) @@ -116,14 +113,15 @@ pub fn create_new_user_task( } } - TaskOptions::new(|| { + let user_task_func = move || user_task_entry(*user_ctx); + + TaskOptions::new(move || { // TODO: If a kernel "oops" is caught, we should kill the entire // process rather than just ending the thread. - let _ = oops::catch_panics_as_oops(user_task_entry); + let _ = oops::catch_panics_as_oops(user_task_func); }) .data(thread_ref) .local_data(thread_local) - .user_ctx(Some(user_ctx)) .build() .expect("spawn task failed") } diff --git a/ostd/src/task/mod.rs b/ostd/src/task/mod.rs index 6cdb6062c..0c8238860 100644 --- a/ostd/src/task/mod.rs +++ b/ostd/src/task/mod.rs @@ -28,7 +28,7 @@ pub use self::{ scheduler::info::{AtomicCpuId, TaskScheduleInfo}, }; pub(crate) use crate::arch::task::{context_switch, TaskContext}; -use crate::{cpu::context::UserContext, prelude::*, trap::in_interrupt_context}; +use crate::{prelude::*, trap::in_interrupt_context}; static PRE_SCHEDULE_HANDLER: Once = Once::new(); @@ -57,7 +57,6 @@ pub struct Task { data: Box, local_data: ForceSync>, - user_ctx: Option>, ctx: SyncUnsafeCell, /// kernel stack, note that the top is SyscallFrame/TrapFrame kstack: KernelStack, @@ -128,15 +127,6 @@ impl Task { pub fn schedule_info(&self) -> &TaskScheduleInfo { &self.schedule_info } - - /// Returns the user context of this task, if it has. - pub fn user_ctx(&self) -> Option<&Arc> { - if self.user_ctx.is_some() { - Some(self.user_ctx.as_ref().unwrap()) - } else { - None - } - } } /// Options to create or spawn a new task. @@ -144,7 +134,6 @@ pub struct TaskOptions { func: Option>, data: Option>, local_data: Option>, - user_ctx: Option>, } impl TaskOptions { @@ -157,7 +146,6 @@ impl TaskOptions { func: Some(Box::new(func)), data: None, local_data: None, - user_ctx: None, } } @@ -188,12 +176,6 @@ impl TaskOptions { self } - /// Sets the user context associated with the task. - pub fn user_ctx(mut self, user_ctx: Option>) -> Self { - self.user_ctx = user_ctx; - self - } - /// Builds a new task without running it immediately. pub fn build(self) -> Result { /// all task will entering this function @@ -225,12 +207,8 @@ impl TaskOptions { let kstack = KernelStack::new_with_guard_page()?; - let mut ctx = SyncUnsafeCell::new(TaskContext::default()); - if let Some(user_ctx) = self.user_ctx.as_ref() { - ctx.get_mut().set_tls_pointer(user_ctx.tls_pointer()); - }; - ctx.get_mut() - .set_instruction_pointer(kernel_task_entry as usize); + let mut ctx = TaskContext::default(); + ctx.set_instruction_pointer(kernel_task_entry as usize); // We should reserve space for the return address in the stack, otherwise // we will write across the page boundary due to the implementation of // the context switch. @@ -239,14 +217,13 @@ impl TaskOptions { // to at least 16 bytes. And a larger alignment is needed if larger arguments // are passed to the function. The `kernel_task_entry` function does not // have any arguments, so we only need to align the stack pointer to 16 bytes. - ctx.get_mut().set_stack_pointer(kstack.end_vaddr() - 16); + ctx.set_stack_pointer(kstack.end_vaddr() - 16); let new_task = Task { func: ForceSync::new(Cell::new(self.func)), data: self.data.unwrap_or_else(|| Box::new(())), local_data: ForceSync::new(self.local_data.unwrap_or_else(|| Box::new(()))), - user_ctx: self.user_ctx, - ctx, + ctx: SyncUnsafeCell::new(ctx), kstack, schedule_info: TaskScheduleInfo { cpu: AtomicCpuId::default(),