From a7ebe8e21466b5341179b9a811bbef8e5847e480 Mon Sep 17 00:00:00 2001 From: Matthew Leach Date: Sun, 21 Dec 2025 08:15:51 +0000 Subject: [PATCH] threading: fix clone to spawn threads Fix issues identify in `sys_clone` logic to enable basic threading. --- src/arch/arm64/exceptions/syscall.rs | 2 +- src/process/clone.rs | 13 ++++++++----- src/process/thread_group.rs | 4 ++-- src/process/thread_group/builder.rs | 5 ++++- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/arch/arm64/exceptions/syscall.rs b/src/arch/arm64/exceptions/syscall.rs index 0bfb60e..8678692 100644 --- a/src/arch/arm64/exceptions/syscall.rs +++ b/src/arch/arm64/exceptions/syscall.rs @@ -254,7 +254,7 @@ pub async fn handle_syscall() { 0xdc => { sys_clone( arg1 as _, - arg2 as _, + UA::from_value(arg2 as _), UA::from_value(arg3 as _), UA::from_value(arg4 as _), arg5 as _, diff --git a/src/process/clone.rs b/src/process/clone.rs index ef65397..e39a29c 100644 --- a/src/process/clone.rs +++ b/src/process/clone.rs @@ -43,7 +43,7 @@ bitflags! { pub async fn sys_clone( flags: u32, - _newsp: usize, + newsp: UA, _arent_tidptr: UA, _child_tidptr: UA, _tls: usize, @@ -53,12 +53,19 @@ pub async fn sys_clone( let new_task = { let current_task = current_task(); + let mut user_ctx = *current_task.ctx.lock_save_irq().user(); + + // TODO: Make this arch indepdenant. The child returns '0' on clone. + user_ctx.x[0] = 0; + let (tg, tid) = if flags.contains(CloneFlags::CLONE_THREAD) { if !flags.contains(CloneFlags::CLONE_SIGHAND & CloneFlags::CLONE_VM) { // CLONE_THREAD requires both CLONE_SIGHAND and CLONE_VM to be // set. return Err(KernelError::InvalidValue); } + user_ctx.sp_el0 = newsp.value() as _; + ( // A new task whtin this thread group. current_task.process.clone(), @@ -113,10 +120,6 @@ pub async fn sys_clone( let creds = current_task.creds.lock_save_irq().clone(); - let mut user_ctx = *current_task.ctx.lock_save_irq().user(); - // TODO: Make this arch indepdenant. The child returns '0' on clone. - user_ctx.x[0] = 0; - let new_sigmask = *current_task.sig_mask.lock_save_irq(); Task { diff --git a/src/process/thread_group.rs b/src/process/thread_group.rs index d6841d5..6e8eea4 100644 --- a/src/process/thread_group.rs +++ b/src/process/thread_group.rs @@ -108,11 +108,11 @@ impl ThreadGroup { // Return the next avilable thread id. Will never return a thread who's ID // == TGID, since that is defined as the main, root thread. pub fn next_tid(&self) -> Tid { - let mut v = self.next_tid.fetch_add(1, Ordering::SeqCst); + let mut v = self.next_tid.fetch_add(1, Ordering::Relaxed); // Skip the TGID. if v == self.tgid.value() { - v = self.next_tid.fetch_add(1, Ordering::SeqCst) + v = self.next_tid.fetch_add(1, Ordering::Relaxed) } Tid(v) diff --git a/src/process/thread_group/builder.rs b/src/process/thread_group/builder.rs index 25c70bb..455f6c8 100644 --- a/src/process/thread_group/builder.rs +++ b/src/process/thread_group/builder.rs @@ -68,7 +68,10 @@ impl ThreadGroupBuilder { .unwrap_or_else(|| Arc::new(SpinLock::new(ResourceLimits::default()))), pending_signals: SpinLock::new(SigSet::empty()), child_notifiers: ChildNotifiers::new(), - next_tid: AtomicU32::new(0), + // Don't start from '0'. Since clone expects the parent to return + // the tid and the child to return '0', if we started from '0' we + // couldn't then differentiate between a child and a parent. + next_tid: AtomicU32::new(1), state: SpinLock::new(ProcessState::Running), threads: SpinLock::new(BTreeMap::new()), });