Use new-thread proc API

This commit is contained in:
4lDO2
2024-07-09 16:13:57 +02:00
parent bf26de70e2
commit c286dd6d33
9 changed files with 121 additions and 79 deletions
+6 -2
View File
@@ -12,7 +12,7 @@ use syscall::{
use crate::{
proc::{fork_inner, FdGuard},
signal::{inner_c, tmp_disable_signals, RtSigarea, SigStack, PROC_CONTROL_STRUCT},
Tcb,
RtTcb, Tcb,
};
// Setup a stack starting from the very end of the address space, and then growing downwards.
@@ -93,7 +93,11 @@ unsafe extern "sysv64" fn fork_impl(initial_rsp: *mut usize) -> usize {
unsafe extern "sysv64" fn child_hook(cur_filetable_fd: usize, new_pid_fd: usize) {
let _ = syscall::close(cur_filetable_fd);
let _ = syscall::close(new_pid_fd);
// TODO: Currently equivalent, but this will not be the case later.
RtTcb::current()
.thr_fd
.get()
.write(Some(FdGuard::new(new_pid_fd)));
}
asmfunction!(__relibc_internal_fork_wrapper -> usize: ["
+45 -25
View File
@@ -9,9 +9,12 @@
)]
#![forbid(unreachable_patterns)]
use generic_rt::{ExpectTlsFree, GenericTcb};
use core::cell::UnsafeCell;
use self::signal::RtSigarea;
use generic_rt::{ExpectTlsFree, GenericTcb};
use syscall::{Sigcontrol, O_CLOEXEC};
use self::proc::FdGuard;
extern crate alloc;
@@ -46,11 +49,33 @@ pub mod sync;
pub mod sys;
pub mod thread;
pub type Tcb = GenericTcb<RtSigarea>;
#[derive(Debug, Default)]
pub struct RtTcb {
pub control: Sigcontrol,
pub arch: UnsafeCell<crate::arch::SigArea>,
pub thr_fd: UnsafeCell<Option<FdGuard>>,
}
impl RtTcb {
pub fn current() -> &'static Self {
unsafe { &Tcb::current().unwrap().os_specific }
}
pub fn thread_fd(&self) -> &FdGuard {
unsafe {
if (&*self.thr_fd.get()).is_none() {
self.thr_fd.get().write(Some(FdGuard::new(
syscall::open("thisproc:current/open_via_dup", O_CLOEXEC).unwrap(),
)));
}
(&*self.thr_fd.get()).as_ref().unwrap()
}
}
}
pub type Tcb = GenericTcb<RtTcb>;
/// OS and architecture specific code to activate TLS - Redox aarch64
#[cfg(target_arch = "aarch64")]
pub unsafe fn tcb_activate(tls_end: usize, tls_len: usize) {
pub unsafe fn tcb_activate(_tcb: &RtTcb, tls_end: usize, tls_len: usize) {
// Uses ABI page
let abi_ptr = tls_end - tls_len - 16;
core::ptr::write(abi_ptr as *mut usize, tls_end);
@@ -62,42 +87,36 @@ pub unsafe fn tcb_activate(tls_end: usize, tls_len: usize) {
/// OS and architecture specific code to activate TLS - Redox x86
#[cfg(target_arch = "x86")]
pub unsafe fn tcb_activate(tls_end: usize, _tls_len: usize) {
pub unsafe fn tcb_activate(tcb: &RtTcb, tls_end: usize, _tls_len: usize) {
let mut env = syscall::EnvRegisters::default();
let file = syscall::open(
"thisproc:current/regs/env",
syscall::O_CLOEXEC | syscall::O_RDWR,
)
.expect_notls("failed to open handle for process registers");
let file = FdGuard::new(
syscall::dup(**tcb.thread_fd(), b"regs/env")
.expect_notls("failed to open handle for process registers"),
);
let _ = syscall::read(file, &mut env).expect_notls("failed to read gsbase");
let _ = syscall::read(*file, &mut env).expect_notls("failed to read gsbase");
env.gsbase = tls_end as u32;
let _ = syscall::write(file, &env).expect_notls("failed to write gsbase");
let _ = syscall::close(file);
let _ = syscall::write(*file, &env).expect_notls("failed to write gsbase");
}
/// OS and architecture specific code to activate TLS - Redox x86_64
#[cfg(target_arch = "x86_64")]
pub unsafe fn tcb_activate(tls_end_and_tcb_start: usize, _tls_len: usize) {
pub unsafe fn tcb_activate(tcb: &RtTcb, tls_end_and_tcb_start: usize, _tls_len: usize) {
let mut env = syscall::EnvRegisters::default();
let file = syscall::open(
"thisproc:current/regs/env",
syscall::O_CLOEXEC | syscall::O_RDWR,
)
.expect_notls("failed to open handle for process registers");
let file = FdGuard::new(
syscall::dup(**tcb.thread_fd(), b"regs/env")
.expect_notls("failed to open handle for process registers"),
);
let _ = syscall::read(file, &mut env).expect_notls("failed to read fsbase");
let _ = syscall::read(*file, &mut env).expect_notls("failed to read fsbase");
env.fsbase = tls_end_and_tcb_start as u64;
let _ = syscall::write(file, &env).expect_notls("failed to write fsbase");
let _ = syscall::close(file);
let _ = syscall::write(*file, &env).expect_notls("failed to write fsbase");
}
/// Initialize redox-rt in situations where relibc is not used
@@ -127,7 +146,8 @@ pub fn initialize_freestanding() {
#[cfg(not(target_arch = "aarch64"))]
unsafe {
tcb_activate(page as *mut Tcb as usize, 0)
let tcb_addr = page as *mut Tcb as usize;
tcb_activate(&page.os_specific, tcb_addr, 0)
}
#[cfg(target_arch = "aarch64")]
unsafe {
+10 -4
View File
@@ -1,5 +1,6 @@
use core::{fmt::Debug, mem::size_of};
use crate::{arch::*, auxv_defs::*};
use core::mem::size_of;
use alloc::{boxed::Box, collections::BTreeMap, vec};
@@ -697,6 +698,11 @@ impl Drop for FdGuard {
}
}
}
impl Debug for FdGuard {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "[fd {}]", self.fd)
}
}
pub fn create_set_addr_space_buf(
space: usize,
ip: usize,
@@ -714,7 +720,7 @@ pub fn create_set_addr_space_buf(
/// descriptors from other schemes are reobtained with `dup`, and grants referencing such file
/// descriptors are reobtained through `fmap`. Other mappings are kept but duplicated using CoW.
pub fn fork_impl() -> Result<usize> {
let mut old_mask = crate::signal::get_sigmask()?;
let old_mask = crate::signal::get_sigmask()?;
let pid = unsafe { Error::demux(__relibc_internal_fork_wrapper())? };
if pid == 0 {
@@ -728,7 +734,7 @@ pub fn fork_inner(initial_rsp: *mut usize) -> Result<usize> {
{
let cur_pid_fd = FdGuard::new(syscall::open("thisproc:current/open_via_dup", O_CLOEXEC)?);
(new_pid_fd, new_pid) = new_context()?;
(new_pid_fd, new_pid) = new_child_process()?;
copy_str(*cur_pid_fd, *new_pid_fd, "name")?;
@@ -853,7 +859,7 @@ pub fn fork_inner(initial_rsp: *mut usize) -> Result<usize> {
Ok(new_pid)
}
pub fn new_context() -> Result<(FdGuard, usize)> {
pub fn new_child_process() -> Result<(FdGuard, usize)> {
// Create a new context (fields such as uid/gid will be inherited from the current context).
let fd = FdGuard::new(syscall::open("thisproc:new/open_via_dup", O_CLOEXEC)?);
+9 -16
View File
@@ -11,7 +11,7 @@ use syscall::{
SIGWINCH, SIGXCPU, SIGXFSZ,
};
use crate::{arch::*, sync::Mutex, Tcb};
use crate::{arch::*, proc::FdGuard, sync::Mutex, RtTcb, Tcb};
#[cfg(target_arch = "x86_64")]
static CPUID_EAX1_ECX: core::sync::atomic::AtomicU32 = core::sync::atomic::AtomicU32::new(0);
@@ -450,9 +450,9 @@ const fn sig_bit(sig: usize) -> u64 {
1 << (sig - 1)
}
pub fn setup_sighandler(area: &RtSigarea) {
pub fn setup_sighandler(tcb: &RtTcb) {
{
let mut sigactions = SIGACTIONS_LOCK.lock();
let _guard = SIGACTIONS_LOCK.lock();
for (sig_idx, action) in PROC_CONTROL_STRUCT.actions.iter().enumerate() {
let sig = sig_idx + 1;
let bits = if matches!(sig, SIGTSTP | SIGTTIN | SIGTTOU) {
@@ -468,7 +468,7 @@ pub fn setup_sighandler(area: &RtSigarea) {
);
}
}
let arch = unsafe { &mut *area.arch.get() };
let arch = unsafe { &mut *tcb.arch.get() };
{
// The asm decides whether to use the altstack, based on whether the saved stack pointer
// was already on that stack. Thus, setting the altstack to the entire address space, is
@@ -489,22 +489,15 @@ pub fn setup_sighandler(area: &RtSigarea) {
let data = current_setsighandler_struct();
let fd = syscall::open(
"thisproc:current/sighandler",
syscall::O_WRONLY | syscall::O_CLOEXEC,
)
.expect("failed to open thisproc:current/sighandler");
syscall::write(fd, &data).expect("failed to write to thisproc:current/sighandler");
let _ = syscall::close(fd);
let fd = FdGuard::new(
syscall::dup(**tcb.thread_fd(), b"sighandler").expect("failed to open sighandler fd"),
);
let _ = syscall::write(*fd, &data).expect("failed to write to sighandler fd");
// TODO: Inherited set of ignored signals
set_sigmask(Some(0), None);
}
#[derive(Debug, Default)]
pub struct RtSigarea {
pub control: Sigcontrol,
pub arch: UnsafeCell<crate::arch::SigArea>,
}
pub type RtSigarea = RtTcb; // TODO
pub fn current_setsighandler_struct() -> SetSighandlerData {
SetSighandlerData {
user_handler: sighandler_function(),
+1 -2
View File
@@ -81,8 +81,7 @@ pub fn sys_waitpid(pid: usize, status: &mut usize, flags: usize) -> Result<usize
syscall::waitpid(
pid,
status,
syscall::WaitFlags::from_bits(flags)
.expect("waitpid: invalid bit pattern"),
syscall::WaitFlags::from_bits(flags).expect("waitpid: invalid bit pattern"),
)
})
}
+15 -12
View File
@@ -1,18 +1,21 @@
use syscall::{Result, SetSighandlerData, O_CLOEXEC};
use syscall::{Result, O_CLOEXEC};
use crate::{arch::*, proc::*, signal::sighandler_function};
use crate::{arch::*, proc::*, 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<usize> {
let cur_pid_fd = FdGuard::new(syscall::open("thisproc:current/open_via_dup", O_CLOEXEC)?);
let (new_pid_fd, new_pid) = new_context()?;
pub unsafe fn rlct_clone_impl(stack: *mut usize) -> Result<FdGuard> {
let cur_thr_fd = RtTcb::current().thread_fd();
let new_thr_fd = FdGuard::new(syscall::open(
"thisproc:new-thread/open_via_dup",
O_CLOEXEC,
)?);
copy_str(*cur_pid_fd, *new_pid_fd, "name")?;
copy_str(**cur_thr_fd, *new_thr_fd, "name")?;
// Inherit existing address space
{
let cur_addr_space_fd = FdGuard::new(syscall::dup(*cur_pid_fd, b"addrspace")?);
let new_addr_space_sel_fd = FdGuard::new(syscall::dup(*new_pid_fd, b"current-addrspace")?);
let cur_addr_space_fd = FdGuard::new(syscall::dup(**cur_thr_fd, b"addrspace")?);
let new_addr_space_sel_fd = FdGuard::new(syscall::dup(*new_thr_fd, b"current-addrspace")?);
let buf = create_set_addr_space_buf(
*cur_addr_space_fd,
@@ -24,8 +27,8 @@ pub unsafe fn rlct_clone_impl(stack: *mut usize) -> Result<usize> {
// Inherit reference to file table
{
let cur_filetable_fd = FdGuard::new(syscall::dup(*cur_pid_fd, b"filetable")?);
let new_filetable_sel_fd = FdGuard::new(syscall::dup(*new_pid_fd, b"current-filetable")?);
let cur_filetable_fd = FdGuard::new(syscall::dup(**cur_thr_fd, b"filetable")?);
let new_filetable_sel_fd = FdGuard::new(syscall::dup(*new_thr_fd, b"current-filetable")?);
let _ = syscall::write(
*new_filetable_sel_fd,
@@ -39,8 +42,8 @@ pub unsafe fn rlct_clone_impl(stack: *mut usize) -> Result<usize> {
// until it has initialized its own signal handler.
// Unblock context.
let start_fd = FdGuard::new(syscall::dup(*new_pid_fd, b"start")?);
let start_fd = FdGuard::new(syscall::dup(*new_thr_fd, b"start")?);
let _ = syscall::write(*start_fd, &[0])?;
Ok(new_pid)
Ok(new_thr_fd)
}
+4 -4
View File
@@ -195,7 +195,7 @@ impl Tcb {
/// Activate TLS
pub unsafe fn activate(&mut self) {
Self::os_arch_activate(self.tls_end as usize, self.tls_len);
Self::os_arch_activate(&self.os_specific, self.tls_end as usize, self.tls_len);
}
/// Mapping with correct flags for TCB and TLS
@@ -231,14 +231,14 @@ impl Tcb {
/// OS and architecture specific code to activate TLS - Linux x86_64
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
unsafe fn os_arch_activate(tls_end: usize, _tls_len: usize) {
unsafe fn os_arch_activate(os: &(), tls_end: usize, _tls_len: usize) {
const ARCH_SET_FS: usize = 0x1002;
syscall!(ARCH_PRCTL, ARCH_SET_FS, tls_end);
}
#[cfg(target_os = "redox")]
unsafe fn os_arch_activate(tls_end: usize, tls_len: usize) {
redox_rt::tcb_activate(tls_end, tls_len)
unsafe fn os_arch_activate(os: &OsSpecific, tls_end: usize, tls_len: usize) {
redox_rt::tcb_activate(os, tls_end, tls_len)
}
}
+9 -6
View File
@@ -1,4 +1,5 @@
use core::{convert::TryFrom, mem, ptr, slice, str};
use redox_rt::RtTcb;
use syscall::{
self,
data::{Map, Stat as redox_stat, StatVfs as redox_statvfs, TimeSpec as redox_timespec},
@@ -792,21 +793,23 @@ impl Pal for Sys {
let _guard = clone::rdlock();
let res = clone::rlct_clone_impl(stack);
res.map(|context_id| crate::pthread::OsTid { context_id })
.map_err(|error| crate::pthread::Errno(error.errno))
res.map(|mut fd| crate::pthread::OsTid {
thread_fd: fd.take(),
})
.map_err(|error| crate::pthread::Errno(error.errno))
}
unsafe fn rlct_kill(
os_tid: crate::pthread::OsTid,
signal: usize,
) -> Result<(), crate::pthread::Errno> {
syscall::kill(os_tid.context_id, signal)
.map_err(|error| crate::pthread::Errno(error.errno))?;
todo!();
/*syscall::kill(os_tid.context_id, signal)
.map_err(|error| crate::pthread::Errno(error.errno))?;*/
Ok(())
}
fn current_os_tid() -> crate::pthread::OsTid {
// TODO
crate::pthread::OsTid {
context_id: Self::getpid() as _,
thread_fd: **RtTcb::current().thread_fd(),
}
}
+22 -8
View File
@@ -2,7 +2,8 @@
use core::{
cell::{Cell, UnsafeCell},
ptr::NonNull,
mem::MaybeUninit,
ptr::{addr_of, NonNull},
sync::atomic::{AtomicBool, AtomicUsize, Ordering},
};
@@ -67,13 +68,13 @@ pub struct Pthread {
pub(crate) stack_base: *mut c_void,
pub(crate) stack_size: usize,
pub(crate) os_tid: UnsafeCell<OsTid>,
pub os_tid: UnsafeCell<OsTid>,
}
#[derive(Clone, Copy, Debug, Default, Ord, Eq, PartialOrd, PartialEq)]
pub struct OsTid {
#[cfg(target_os = "redox")]
pub context_id: usize,
pub thread_fd: usize,
#[cfg(target_os = "linux")]
pub thread_id: usize,
}
@@ -147,6 +148,9 @@ pub(crate) unsafe fn create(
let synchronization_mutex = Mutex::locked(current_sigmask);
let synchronization_mutex = &synchronization_mutex;
let tid_mutex = Mutex::<MaybeUninit<OsTid>>::new(MaybeUninit::uninit());
let mut tid_guard = tid_mutex.lock();
let stack_size = attrs.stacksize.next_multiple_of(Sys::getpagesize());
let stack_base = if attrs.stack != 0 {
@@ -208,7 +212,7 @@ pub(crate) unsafe fn create(
}
push(0);
push(synchronization_mutex as *const _ as usize);
push(0);
push(addr_of!(tid_mutex) as usize);
push(new_tcb as *mut _ as usize);
push(arg as usize);
@@ -222,6 +226,8 @@ pub(crate) unsafe fn create(
};
core::mem::forget(stack_raii);
tid_guard.write(os_tid);
drop(tid_guard);
let _ = synchronization_mutex.lock();
OS_TID_TO_PTHREAD
@@ -235,10 +241,18 @@ unsafe extern "C" fn new_thread_shim(
entry_point: unsafe extern "C" fn(*mut c_void) -> *mut c_void,
arg: *mut c_void,
tcb: *mut Tcb,
_pthread: *mut Pthread,
mutex: *const Mutex<u64>,
mutex1: *const Mutex<MaybeUninit<OsTid>>,
mutex2: *const Mutex<u64>,
) -> ! {
let procmask = (*mutex).as_ptr().read();
let procmask = (&*mutex2).as_ptr().read();
let tid = (*(&*mutex1).lock()).assume_init();
#[cfg(target_os = "redox")]
(*tcb)
.os_specific
.thr_fd
.get()
.write(Some(redox_rt::proc::FdGuard::new(tid.thread_fd)));
if let Some(tcb) = tcb.as_mut() {
tcb.copy_masters().unwrap();
@@ -247,7 +261,7 @@ unsafe extern "C" fn new_thread_shim(
(*tcb).pthread.os_tid.get().write(Sys::current_os_tid());
(&*mutex).manual_unlock();
(&*mutex2).manual_unlock();
#[cfg(target_os = "redox")]
{