Remove `user_ctx` from `Task`

This commit is contained in:
Ruihan Li 2025-08-07 19:21:50 +08:00 committed by Junyang Zhang
parent 60bc63b0e2
commit 923982c2e5
5 changed files with 19 additions and 44 deletions

View File

@ -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,

View File

@ -29,7 +29,7 @@ use crate::{
pub struct PosixThreadBuilder {
// The essential part
tid: Tid,
user_ctx: Arc<UserContext>,
user_ctx: Box<UserContext>,
process: Weak<Process>,
credentials: Credentials,
@ -46,7 +46,7 @@ pub struct PosixThreadBuilder {
}
impl PosixThreadBuilder {
pub fn new(tid: Tid, user_ctx: Arc<UserContext>, credentials: Credentials) -> Self {
pub fn new(tid: Tid, user_ctx: Box<UserContext>, credentials: Credentials) -> Self {
Self {
tid,
user_ctx,

View File

@ -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));

View File

@ -23,11 +23,11 @@ use crate::{
/// create new task with userspace and parent process
pub fn create_new_user_task(
user_ctx: Arc<UserContext>,
user_ctx: Box<UserContext>,
thread_ref: Arc<Thread>,
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, &current_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")
}

View File

@ -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<fn()> = Once::new();
@ -57,7 +57,6 @@ pub struct Task {
data: Box<dyn Any + Send + Sync>,
local_data: ForceSync<Box<dyn Any + Send>>,
user_ctx: Option<Arc<UserContext>>,
ctx: SyncUnsafeCell<TaskContext>,
/// 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<UserContext>> {
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<Box<dyn FnOnce() + Send>>,
data: Option<Box<dyn Any + Send + Sync>>,
local_data: Option<Box<dyn Any + Send>>,
user_ctx: Option<Arc<UserContext>>,
}
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<Arc<UserContext>>) -> Self {
self.user_ctx = user_ctx;
self
}
/// Builds a new task without running it immediately.
pub fn build(self) -> Result<Task> {
/// 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(),