Merge pull request #75 from arihant2math/fix-thread-join

This commit is contained in:
Matthew Leach
2025-12-22 17:36:48 +00:00
committed by GitHub
5 changed files with 61 additions and 28 deletions

View File

@@ -169,7 +169,7 @@ pub async fn handle_syscall() {
}
0x50 => sys_fstat(arg1.into(), TUA::from_value(arg2 as _)).await,
0x51 => sys_sync().await,
0x5d => sys_exit(arg1 as _),
0x5d => sys_exit(arg1 as _).await,
0x5e => sys_exit_group(arg1 as _),
0x60 => sys_set_tid_address(VA::from_value(arg1 as _)).await,
0x62 => {
@@ -255,8 +255,8 @@ pub async fn handle_syscall() {
sys_clone(
arg1 as _,
UA::from_value(arg2 as _),
UA::from_value(arg3 as _),
UA::from_value(arg5 as _),
TUA::from_value(arg3 as _),
TUA::from_value(arg5 as _),
arg4 as _,
)
.await

View File

@@ -1,17 +1,18 @@
use super::{ctx::Context, thread_group::signal::SigSet};
use crate::memory::uaccess::copy_to_user;
use crate::{
process::{TASK_LIST, Task, TaskState},
sched::{self, current_task},
sync::SpinLock,
};
use bitflags::bitflags;
use libkernel::memory::address::TUA;
use libkernel::{
error::{KernelError, Result},
memory::address::UA,
};
use ringbuf::Arc;
use super::{ctx::Context, thread_group::signal::SigSet};
bitflags! {
#[derive(Debug)]
pub struct CloneFlags: u32 {
@@ -44,8 +45,8 @@ bitflags! {
pub async fn sys_clone(
flags: u32,
newsp: UA,
_arent_tidptr: UA,
_child_tidptr: UA,
parent_tidptr: TUA<u32>,
child_tidptr: TUA<u32>,
tls: usize,
) -> Result<usize> {
let flags = CloneFlags::from_bits_truncate(flags);
@@ -146,6 +147,11 @@ pub async fn sys_clone(
state: Arc::new(SpinLock::new(TaskState::Runnable)),
last_run: SpinLock::new(None),
robust_list: SpinLock::new(None),
child_tid_ptr: SpinLock::new(if !child_tidptr.is_null() {
Some(child_tidptr)
} else {
None
}),
}
};
@@ -157,5 +163,13 @@ pub async fn sys_clone(
sched::insert_task(Arc::new(new_task));
// Honour CLONE_*SETTID semantics for the parent and (shared-VM) child.
if flags.contains(CloneFlags::CLONE_PARENT_SETTID) && !parent_tidptr.is_null() {
copy_to_user(parent_tidptr, tid.value()).await?;
}
if flags.contains(CloneFlags::CLONE_CHILD_SETTID) && !child_tidptr.is_null() {
copy_to_user(child_tidptr, tid.value()).await?;
}
Ok(tid.value() as _)
}

View File

@@ -1,12 +1,13 @@
use crate::sched::current_task;
use alloc::vec::Vec;
use libkernel::error::Result;
use ringbuf::Arc;
use super::{
TaskState,
thread_group::{ProcessState, Tgid, ThreadGroup, signal::SigId, wait::ChildState},
};
use crate::memory::uaccess::copy_to_user;
use crate::process::threading::futex_wake_addr;
use crate::sched::current_task;
use alloc::vec::Vec;
use libkernel::error::Result;
use ringbuf::Arc;
pub fn do_exit_group(exit_code: ChildState) {
let task = current_task();
@@ -99,8 +100,18 @@ pub fn sys_exit_group(exit_code: usize) -> Result<usize> {
Ok(0)
}
pub fn sys_exit(exit_code: usize) -> Result<usize> {
pub async fn sys_exit(exit_code: usize) -> Result<usize> {
let task = current_task();
// Honour CLONE_CHILD_CLEARTID: clear the user TID word and futex-wake any waiters.
let ptr = task.child_tid_ptr.lock_save_irq().take();
if let Some(ptr) = ptr {
copy_to_user(ptr, 0u32).await?;
// Wake any thread waiting on this futex.
futex_wake_addr(ptr, 1);
}
let process = Arc::clone(&task.process);
let mut thread_lock = process.threads.lock_save_irq();

View File

@@ -181,6 +181,7 @@ pub struct Task {
pub last_run: SpinLock<Option<Instant>>,
pub state: Arc<SpinLock<TaskState>>,
pub robust_list: SpinLock<Option<TUA<RobustListHead>>>,
pub child_tid_ptr: SpinLock<Option<TUA<u32>>>,
}
impl Task {
@@ -214,6 +215,7 @@ impl Task {
fd_table: Arc::new(SpinLock::new(FileDescriptorTable::new())),
last_run: SpinLock::new(None),
robust_list: SpinLock::new(None),
child_tid_ptr: SpinLock::new(None),
}
}
@@ -241,6 +243,7 @@ impl Task {
)),
last_run: SpinLock::new(None),
robust_list: SpinLock::new(None),
child_tid_ptr: SpinLock::new(None),
}
}

View File

@@ -74,6 +74,25 @@ const FUTEX_WAIT_BITSET: i32 = 9;
const FUTEX_WAKE_BITSET: i32 = 10;
const FUTEX_PRIVATE_FLAG: i32 = 128;
/// Wake up to `nr` waiters sleeping on the futex word located at `uaddr`.
/// Returns the number of tasks actually woken.
pub fn futex_wake_addr(uaddr: TUA<u32>, nr: usize) -> usize {
let mut woke = 0;
if let Some(table) = FUTEX_TABLE.get()
&& let Some(waitq_arc) = table.lock_save_irq().get(&uaddr).cloned()
{
let mut waitq = waitq_arc.lock_save_irq();
for _ in 0..nr {
waitq.wakeups = waitq.wakeups.saturating_add(1);
waitq.wakers.wake_one();
woke += 1;
}
}
woke
}
pub async fn sys_futex(
uaddr: TUA<u32>,
op: i32,
@@ -132,21 +151,7 @@ pub async fn sys_futex(
FUTEX_WAKE | FUTEX_WAKE_BITSET => {
let nr_wake = val as usize;
let mut woke = 0;
if let Some(table) = FUTEX_TABLE.get()
&& let Some(waitq_arc) = table.lock_save_irq().get(&uaddr).cloned()
{
let mut waitq = waitq_arc.lock_save_irq();
for _ in 0..nr_wake {
// Record a pending wake-up and attempt to wake a single waiter.
waitq.wakeups = waitq.wakeups.saturating_add(1);
waitq.wakers.wake_one();
woke += 1;
}
}
Ok(woke)
Ok(futex_wake_addr(uaddr, nr_wake))
}
_ => Err(KernelError::NotSupported),