relibc: fix round-8 deferred stubs in linux platform

signal.rs: sigqueue now fills si_pid/si_uid with real getpid()/getuid()
  instead of zeros, allowing receivers to identify the sender.

mod.rs: exit_thread now frees the thread stack via munmap before calling
  __NR_exit (which exits just the calling thread on Linux, not the
  process). Previously it called process::exit(0) which leaked the stack
  and had misleading semantics.

mod.rs: rlct_clone for aarch64 is now implemented with proper inline
  assembly for the clone syscall (SYS_CLONE=220). The child pops the
  function pointer and arguments from the prepared stack, calls
  new_thread_shim, then exits via __NR_exit (93). Previously this was
  todo!() which panicked on thread creation.
This commit is contained in:
Red Bear OS
2026-07-27 09:16:17 +09:00
parent d9760bdc41
commit 0fee9dc19f
2 changed files with 85 additions and 8 deletions
+82 -5
View File
@@ -1,4 +1,4 @@
#[cfg(target_arch = "x86_64")]
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
use core::arch::asm;
use super::{Pal, types::*};
@@ -165,9 +165,15 @@ impl Pal for Sys {
}
unreachable!();
}
unsafe fn exit_thread(_stack_base: *mut (), _stack_size: usize) -> ! {
// TODO
Self::exit(0)
unsafe fn exit_thread(stack_base: *mut (), stack_size: usize) -> ! {
// Free the thread's stack before exiting. On Linux, __NR_exit only
// terminates the calling thread (not the process); __NR_exit_group
// terminates all threads. We want thread-only exit here.
if !stack_base.is_null() && stack_size > 0 {
let _ = e_raw(syscall!(MUNMAP, stack_base, stack_size));
}
unsafe { syscall!(EXIT, 0); }
unreachable!();
}
fn fchdir(fildes: c_int) -> Result<()> {
@@ -627,7 +633,78 @@ impl Pal for Sys {
stack: *mut usize,
_os_specific: &mut OsSpecific,
) -> Result<crate::pthread::OsTid> {
todo!("rlct_clone not implemented for aarch64 yet")
const SYS_CLONE_AARCH64: usize = 220;
const SYS_EXIT_AARCH64: usize = 93;
let flags = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD;
let pid;
unsafe {
asm!(
"svc #0",
// If x0 != 0 we are the parent; jump to return.
"cbnz x0, 2f",
// Child: pop function pointer and args from the stack
// that the pthread code prepared.
"ldr x9, [sp], #8", // x9 = new_thread_shim
"ldr x0, [sp], #8", // x0 = start_routine
"ldr x1, [sp], #8", // x1 = arg
"ldr x2, [sp], #8", // x2 = tcb
"ldr x3, [sp], #8", // x3 = sync_mutex
"ldr x4, [sp], #8", // skip unused
"ldr x5, [sp], #8", // skip unused
"ldr x6, [sp], #8", // skip aarch64 alignment pad
"blr x9", // call new_thread_shim(...)
// new_thread_shim returns !, but guard just in case.
"mov x8, {exit_nr}",
"mov x0, xzr",
"svc #0",
"udf #0",
"2:",
exit_nr = const SYS_EXIT_AARCH64,
inout("x0") flags => pid,
inout("x1") stack => _,
in("x2") 0usize,
in("x3") 0usize,
in("x4") 0usize,
in("x8") SYS_CLONE_AARCH64,
out("x5") _,
out("x6") _,
out("x7") _,
out("x9") _,
out("x10") _,
out("x11") _,
out("x12") _,
out("x13") _,
out("x14") _,
out("x15") _,
out("x16") _,
out("x17") _,
out("x18") _,
out("x19") _,
out("x20") _,
out("x21") _,
out("x22") _,
out("x23") _,
out("x24") _,
out("x25") _,
out("x26") _,
out("x27") _,
out("x28") _,
options(nostack),
);
}
let tid = e_raw(pid)?;
Ok(crate::pthread::OsTid { thread_id: tid })
}
unsafe fn rlct_kill(os_tid: crate::pthread::OsTid, signal: usize) -> Result<()> {
+3 -3
View File
@@ -5,7 +5,7 @@ use core::{
use super::{
super::{
PalSignal,
Pal, PalSignal,
types::{c_int, pid_t},
},
Sys, e_raw,
@@ -39,10 +39,10 @@ impl PalSignal for Sys {
si_addr: core::ptr::null_mut(),
si_code: SI_QUEUE,
si_errno: 0,
si_pid: 0, // TODO: GETPID?
si_pid: Self::getpid(),
si_signo: sig,
si_status: 0,
si_uid: 0, // TODO: GETUID?
si_uid: Self::getuid(),
si_value: val,
};
e_raw(unsafe { syscall!(RT_SIGQUEUEINFO, pid, sig, addr_of!(info)) }).map(|_| ())