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:
@@ -1,4 +1,4 @@
|
|||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
|
||||||
use core::arch::asm;
|
use core::arch::asm;
|
||||||
|
|
||||||
use super::{Pal, types::*};
|
use super::{Pal, types::*};
|
||||||
@@ -165,9 +165,15 @@ impl Pal for Sys {
|
|||||||
}
|
}
|
||||||
unreachable!();
|
unreachable!();
|
||||||
}
|
}
|
||||||
unsafe fn exit_thread(_stack_base: *mut (), _stack_size: usize) -> ! {
|
unsafe fn exit_thread(stack_base: *mut (), stack_size: usize) -> ! {
|
||||||
// TODO
|
// Free the thread's stack before exiting. On Linux, __NR_exit only
|
||||||
Self::exit(0)
|
// 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<()> {
|
fn fchdir(fildes: c_int) -> Result<()> {
|
||||||
@@ -627,7 +633,78 @@ impl Pal for Sys {
|
|||||||
stack: *mut usize,
|
stack: *mut usize,
|
||||||
_os_specific: &mut OsSpecific,
|
_os_specific: &mut OsSpecific,
|
||||||
) -> Result<crate::pthread::OsTid> {
|
) -> 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<()> {
|
unsafe fn rlct_kill(os_tid: crate::pthread::OsTid, signal: usize) -> Result<()> {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use core::{
|
|||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
super::{
|
super::{
|
||||||
PalSignal,
|
Pal, PalSignal,
|
||||||
types::{c_int, pid_t},
|
types::{c_int, pid_t},
|
||||||
},
|
},
|
||||||
Sys, e_raw,
|
Sys, e_raw,
|
||||||
@@ -39,10 +39,10 @@ impl PalSignal for Sys {
|
|||||||
si_addr: core::ptr::null_mut(),
|
si_addr: core::ptr::null_mut(),
|
||||||
si_code: SI_QUEUE,
|
si_code: SI_QUEUE,
|
||||||
si_errno: 0,
|
si_errno: 0,
|
||||||
si_pid: 0, // TODO: GETPID?
|
si_pid: Self::getpid(),
|
||||||
si_signo: sig,
|
si_signo: sig,
|
||||||
si_status: 0,
|
si_status: 0,
|
||||||
si_uid: 0, // TODO: GETUID?
|
si_uid: Self::getuid(),
|
||||||
si_value: val,
|
si_value: val,
|
||||||
};
|
};
|
||||||
e_raw(unsafe { syscall!(RT_SIGQUEUEINFO, pid, sig, addr_of!(info)) }).map(|_| ())
|
e_raw(unsafe { syscall!(RT_SIGQUEUEINFO, pid, sig, addr_of!(info)) }).map(|_| ())
|
||||||
|
|||||||
Reference in New Issue
Block a user