From fed49a29af87bd4bf5e4ad652651ffee6d6d1c11 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Mon, 5 Aug 2024 13:22:18 +0200 Subject: [PATCH] Properly deallocate thread stack on pthread_exit. --- redox-rt/src/thread.rs | 20 ++++++++++++++++---- src/platform/linux/mod.rs | 2 +- src/platform/pal/mod.rs | 2 +- src/platform/redox/mod.rs | 4 ++-- src/pthread/mod.rs | 12 ++++++------ 5 files changed, 26 insertions(+), 14 deletions(-) diff --git a/redox-rt/src/thread.rs b/redox-rt/src/thread.rs index 664588ab77..1791732a22 100644 --- a/redox-rt/src/thread.rs +++ b/redox-rt/src/thread.rs @@ -1,6 +1,8 @@ +use core::mem::size_of; + use syscall::{Result, O_CLOEXEC}; -use crate::{arch::*, proc::*, RtTcb}; +use crate::{arch::*, proc::*, signal::tmp_disable_signals, RtTcb}; /// Spawns a new context sharing the same address space as the current one (i.e. a new thread). pub unsafe fn rlct_clone_impl(stack: *mut usize) -> Result { @@ -48,10 +50,20 @@ pub unsafe fn rlct_clone_impl(stack: *mut usize) -> Result { Ok(new_thr_fd) } -pub fn exit_this_thread() -> ! { - let thread_fd = RtTcb::current().thread_fd(); +pub unsafe fn exit_this_thread(stack_base: *mut (), stack_size: usize) -> ! { + let _guard = tmp_disable_signals(); + + let tcb = RtTcb::current(); + let thread_fd = tcb.thread_fd(); + + let _ = syscall::funmap(tcb as *const RtTcb as usize, syscall::PAGE_SIZE); + // TODO: modify interface so it writes directly to the thread fd? let status_fd = syscall::dup(**thread_fd, b"status").unwrap(); - syscall::write(status_fd, &usize::MAX.to_ne_bytes()).unwrap(); + let mut buf = [0; size_of::() * 3]; + plain::slice_from_mut_bytes(&mut buf) + .unwrap() + .copy_from_slice(&[usize::MAX, stack_base as usize, stack_size]); + syscall::write(status_fd, &buf).unwrap(); unreachable!() } diff --git a/src/platform/linux/mod.rs b/src/platform/linux/mod.rs index 0646f1b78c..b258b52da5 100644 --- a/src/platform/linux/mod.rs +++ b/src/platform/linux/mod.rs @@ -157,7 +157,7 @@ impl Pal for Sys { } loop {} } - fn exit_thread() -> ! { + unsafe fn exit_thread(_stack_base: *mut (), _stack_size: usize) -> ! { // TODO Self::exit(0) } diff --git a/src/platform/pal/mod.rs b/src/platform/pal/mod.rs index 3a234dfec3..09dea6cba9 100644 --- a/src/platform/pal/mod.rs +++ b/src/platform/pal/mod.rs @@ -55,7 +55,7 @@ pub trait Pal { fn exit(status: c_int) -> !; - fn exit_thread() -> !; + unsafe fn exit_thread(stack_base: *mut (), stack_size: usize) -> !; fn fchdir(fildes: c_int) -> c_int; diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index a3bda34315..57482b4d9b 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -1137,7 +1137,7 @@ impl Pal for Sys { (unsafe { syscall::syscall5(syscall::number::SYS_GETPID, !0, !0, !0, !0, !0) }).is_ok() } - fn exit_thread() -> ! { - redox_rt::thread::exit_this_thread() + unsafe fn exit_thread(stack_base: *mut (), stack_size: usize) -> ! { + redox_rt::thread::exit_this_thread(stack_base, stack_size) } } diff --git a/src/pthread/mod.rs b/src/pthread/mod.rs index 2d2fc7b20f..d7b97fe1de 100644 --- a/src/pthread/mod.rs +++ b/src/pthread/mod.rs @@ -2,7 +2,7 @@ use core::{ cell::{Cell, UnsafeCell}, - mem::MaybeUninit, + mem::{offset_of, MaybeUninit}, ptr::{addr_of, NonNull}, sync::atomic::{AtomicBool, AtomicUsize, Ordering}, }; @@ -22,8 +22,6 @@ use crate::{ use crate::sync::{waitval::Waitval, Mutex}; -const MAIN_PTHREAD_ID: usize = 1; - /// Called only by the main thread, as part of relibc_start. pub unsafe fn init() { Tcb::current() @@ -269,7 +267,7 @@ pub unsafe fn join(thread: &Pthread) -> Result { pub unsafe fn detach(thread: &Pthread) -> Result<(), Errno> { thread .flags - .fetch_or(PthreadFlags::DETACHED.bits(), Ordering::Release); + .fetch_or(PthreadFlags::DETACHED.bits(), Ordering::AcqRel); Ok(()) } @@ -294,6 +292,8 @@ pub unsafe fn exit_current_thread(retval: Retval) -> ! { header::tls::run_all_destructors(); let this = current_thread().expect("failed to obtain current thread when exiting"); + let stack_base = this.stack_base; + let stack_size = this.stack_size; if this.flags.load(Ordering::Acquire) & PthreadFlags::DETACHED.bits() != 0 { // When detached, the thread state no longer makes any sense, and can immediately be @@ -304,12 +304,12 @@ pub unsafe fn exit_current_thread(retval: Retval) -> ! { this.waitval.post(retval); } - Sys::exit_thread() + Sys::exit_thread(stack_base.cast(), stack_size) } unsafe fn dealloc_thread(thread: &Pthread) { + // TODO: How should this be handled on Linux? OS_TID_TO_PTHREAD.lock().remove(&thread.os_tid.get().read()); - //drop(Box::from_raw(thread as *const Pthread as *mut Pthread)); } pub const SIGRT_RLCT_CANCEL: usize = 33; pub const SIGRT_RLCT_TIMER: usize = 34;