Files
RedBear-OS/redox-rt/src/thread.rs
T

70 lines
2.5 KiB
Rust

use core::mem::size_of;
use syscall::{Result, O_CLOEXEC};
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<FdGuard> {
let cur_thr_fd = RtTcb::current().thread_fd();
let new_thr_fd = FdGuard::new(syscall::open(
"/scheme/thisproc/new-thread/open_via_dup",
O_CLOEXEC,
)?);
copy_str(**cur_thr_fd, *new_thr_fd, "name")?;
// Inherit existing address space
{
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,
__relibc_internal_rlct_clone_ret as usize,
stack as usize,
);
let _ = syscall::write(*new_addr_space_sel_fd, &buf)?;
}
// Inherit reference to file table
{
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,
&usize::to_ne_bytes(*cur_filetable_fd),
)?;
}
// Since the signal handler is not yet initialized, signals specifically targeting the thread
// (relibc is only required to implement thread-specific signals that already originate from
// the same process) will be discarded. Process-specific signals will ignore this new thread,
// until it has initialized its own signal handler.
// Unblock context.
let start_fd = FdGuard::new(syscall::dup(*new_thr_fd, b"start")?);
let _ = syscall::write(*start_fd, &[0])?;
Ok(new_thr_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();
let mut buf = [0; size_of::<usize>() * 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!()
}