Use new-thread proc API
This commit is contained in:
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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")]
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user