feature: thread::current() using tpidr_el0
This commit is contained in:
parent
6eac5287a2
commit
7c622a78f8
@ -32,27 +32,6 @@ __aa64_ctx_enter_kernel:
|
||||
eret
|
||||
|
||||
__aa64_ctx_enter_from_fork:
|
||||
// stack.push(frame.x[18]);
|
||||
// stack.push(frame.x[17]);
|
||||
// stack.push(frame.x[16]);
|
||||
// stack.push(frame.x[15]);
|
||||
// stack.push(frame.x[14]);
|
||||
// stack.push(frame.x[13]);
|
||||
// stack.push(frame.x[12]);
|
||||
// stack.push(frame.x[11]);
|
||||
// stack.push(frame.x[10]);
|
||||
// stack.push(frame.x[9]);
|
||||
// stack.push(frame.x[8]);
|
||||
// stack.push(frame.x[7]);
|
||||
// stack.push(frame.x[6]);
|
||||
// stack.push(frame.x[5]);
|
||||
// stack.push(frame.x[4]);
|
||||
// stack.push(frame.x[3]);
|
||||
// stack.push(frame.x[2]);
|
||||
// stack.push(frame.x[1]);
|
||||
|
||||
// stack.push(frame.elr_el1 as usize);
|
||||
// stack.push(frame.sp_el0 as usize);
|
||||
ldp x0, x1, [sp, #16 * 0]
|
||||
msr sp_el0, x0
|
||||
msr elr_el1, x1
|
||||
@ -82,7 +61,8 @@ __aa64_ctx_switch:
|
||||
stp x27, x28, [sp, #16 * 4]
|
||||
stp x29, x30, [sp, #16 * 5]
|
||||
mrs x19, TTBR0_EL1
|
||||
stp x19, xzr, [sp, #16 * 6]
|
||||
mrs x20, TPIDR_EL0
|
||||
stp x19, x20, [sp, #16 * 6]
|
||||
|
||||
mov x19, sp
|
||||
str x19, [x1]
|
||||
@ -90,8 +70,9 @@ __aa64_ctx_switch_to:
|
||||
ldr x0, [x0]
|
||||
mov sp, x0
|
||||
|
||||
ldp x19, xzr, [sp, #16 * 6]
|
||||
ldp x19, x20, [sp, #16 * 6]
|
||||
msr TTBR0_EL1, x19
|
||||
msr TPIDR_EL0, x20
|
||||
ldp x19, x20, [sp, #16 * 0]
|
||||
ldp x21, x22, [sp, #16 * 1]
|
||||
ldp x23, x24, [sp, #16 * 2]
|
||||
|
@ -67,7 +67,7 @@ impl Context {
|
||||
stack.push(frame.sp_el0 as usize);
|
||||
|
||||
// Setup common
|
||||
stack.push(0);
|
||||
stack.push(0); // tpidr_el0
|
||||
stack.push(ttbr0);
|
||||
stack.push(__aa64_ctx_enter_from_fork as usize); // x30/lr
|
||||
stack.push(frame.x[29]); // x29
|
||||
@ -96,7 +96,7 @@ impl Context {
|
||||
|
||||
stack.push(entry);
|
||||
stack.push(arg);
|
||||
stack.push(/* ttbr0 */ 0);
|
||||
stack.push(0);
|
||||
stack.push(ustack);
|
||||
|
||||
stack.setup_common(__aa64_ctx_enter_user as usize, ttbr0);
|
||||
@ -176,7 +176,7 @@ impl Stack {
|
||||
}
|
||||
|
||||
pub fn setup_common(&mut self, entry: usize, ttbr: usize) {
|
||||
self.push(0);
|
||||
self.push(0); // tpidr_el0
|
||||
self.push(ttbr);
|
||||
self.push(entry); // x30/lr
|
||||
self.push(0); // x29
|
||||
|
@ -197,11 +197,10 @@ impl Process {
|
||||
|
||||
// TODO a way to terminate a single thread?
|
||||
/// Terminates a process.
|
||||
pub fn exit<I: Into<ExitCode>>(status: I) {
|
||||
pub fn exit(status: ExitCode) {
|
||||
unsafe {
|
||||
asm!("msr daifclr, #0xF");
|
||||
}
|
||||
let status = status.into();
|
||||
let thread = Thread::current();
|
||||
let process = thread.owner().unwrap();
|
||||
let mut lock = process.inner.lock();
|
||||
@ -213,7 +212,7 @@ impl Process {
|
||||
|
||||
for &tid in lock.threads.iter() {
|
||||
debugln!("Dequeue {:?}", tid);
|
||||
Thread::get(tid).unwrap().terminate();
|
||||
Thread::get(tid).unwrap().terminate(status);
|
||||
SCHED.dequeue(tid);
|
||||
}
|
||||
SCHED.debug();
|
||||
@ -234,7 +233,7 @@ impl Process {
|
||||
panic!("This code should never run");
|
||||
}
|
||||
|
||||
pub fn exit_thread(thread: ThreadRef) {
|
||||
pub fn exit_thread(thread: ThreadRef, status: ExitCode) {
|
||||
let switch = {
|
||||
let switch = thread.state() == ThreadState::Running;
|
||||
let process = thread.owner().unwrap();
|
||||
@ -244,13 +243,13 @@ impl Process {
|
||||
if lock.threads.len() == 1 {
|
||||
// TODO call Process::exit instead?
|
||||
drop(lock);
|
||||
Process::exit(ExitCode::from(0));
|
||||
Process::exit(status);
|
||||
panic!();
|
||||
}
|
||||
|
||||
lock.threads.retain(|&e| e != tid);
|
||||
|
||||
thread.terminate();
|
||||
thread.terminate(status);
|
||||
SCHED.dequeue(tid);
|
||||
debugln!("Thread {} terminated", tid);
|
||||
|
||||
|
@ -1,10 +1,11 @@
|
||||
use crate::arch::aarch64::exception::ExceptionFrame;
|
||||
use crate::proc::{wait::Wait, Process, ProcessRef, SCHED, THREADS};
|
||||
use crate::sync::IrqSafeSpinLock;
|
||||
use crate::util::InitOnce;
|
||||
use alloc::{rc::Rc, vec::Vec};
|
||||
use core::cell::UnsafeCell;
|
||||
use core::sync::atomic::{AtomicU32, Ordering};
|
||||
use libsys::{error::Errno, proc::Pid, signal::Signal};
|
||||
use libsys::{error::Errno, proc::{Pid, ExitCode}, signal::Signal};
|
||||
|
||||
pub use crate::arch::platform::context::{self, Context};
|
||||
|
||||
@ -36,6 +37,7 @@ struct ThreadInner {
|
||||
pub struct Thread {
|
||||
inner: IrqSafeSpinLock<ThreadInner>,
|
||||
exit_wait: Wait,
|
||||
exit_status: InitOnce<ExitCode>,
|
||||
pub(super) ctx: UnsafeCell<Context>,
|
||||
signal_ctx: UnsafeCell<Context>,
|
||||
signal_pending: AtomicU32,
|
||||
@ -70,6 +72,7 @@ impl Thread {
|
||||
signal_ctx: UnsafeCell::new(Context::empty()),
|
||||
signal_pending: AtomicU32::new(0),
|
||||
exit_wait: Wait::new(),
|
||||
exit_status: InitOnce::new(),
|
||||
inner: IrqSafeSpinLock::new(ThreadInner {
|
||||
signal_entry: 0,
|
||||
signal_stack: 0,
|
||||
@ -100,6 +103,7 @@ impl Thread {
|
||||
signal_ctx: UnsafeCell::new(Context::empty()),
|
||||
signal_pending: AtomicU32::new(0),
|
||||
exit_wait: Wait::new(),
|
||||
exit_status: InitOnce::new(),
|
||||
inner: IrqSafeSpinLock::new(ThreadInner {
|
||||
signal_entry: 0,
|
||||
signal_stack: 0,
|
||||
@ -127,6 +131,7 @@ impl Thread {
|
||||
signal_ctx: UnsafeCell::new(Context::empty()),
|
||||
signal_pending: AtomicU32::new(0),
|
||||
exit_wait: Wait::new(),
|
||||
exit_status: InitOnce::new(),
|
||||
inner: IrqSafeSpinLock::new(ThreadInner {
|
||||
signal_entry: 0,
|
||||
signal_stack: 0,
|
||||
@ -295,7 +300,7 @@ impl Thread {
|
||||
let mut lock = self.inner.lock();
|
||||
if lock.signal_entry == 0 || lock.signal_stack == 0 {
|
||||
drop(lock);
|
||||
Process::exit_thread(self);
|
||||
Process::exit_thread(self, ExitCode::from(-1));
|
||||
panic!();
|
||||
}
|
||||
|
||||
@ -322,7 +327,7 @@ impl Thread {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn terminate(&self) {
|
||||
pub fn terminate(&self, status: ExitCode) {
|
||||
let mut lock = self.inner.lock();
|
||||
lock.state = State::Finished;
|
||||
let tid = lock.id;
|
||||
@ -331,6 +336,7 @@ impl Thread {
|
||||
if let Some(wait) = wait {
|
||||
wait.abort(tid);
|
||||
}
|
||||
self.exit_status.init(status);
|
||||
self.exit_wait.wakeup_all();
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ use libsys::{
|
||||
abi,
|
||||
error::Errno,
|
||||
ioctl::IoctlCmd,
|
||||
proc::Pid,
|
||||
proc::{ExitCode, Pid},
|
||||
signal::{Signal, SignalDestination},
|
||||
stat::{FdSet, AccessMode, FileDescriptor, FileMode, OpenFlags, Stat, AT_EMPTY_PATH},
|
||||
traits::{Read, Write},
|
||||
@ -55,13 +55,16 @@ pub fn syscall(num: usize, args: &[usize]) -> Result<usize, Errno> {
|
||||
match num {
|
||||
// Process management system calls
|
||||
abi::SYS_EXIT => {
|
||||
Process::exit(args[0] as i32);
|
||||
Process::exit(ExitCode::from(args[0] as i32));
|
||||
unreachable!();
|
||||
}
|
||||
abi::SYS_EX_THREAD_EXIT => {
|
||||
Process::exit_thread(Thread::current());
|
||||
Process::exit_thread(Thread::current(), ExitCode::from(args[0] as i32));
|
||||
unreachable!();
|
||||
},
|
||||
abi::SYS_EX_GETTID => {
|
||||
Ok(Thread::current().id() as usize)
|
||||
},
|
||||
|
||||
// I/O system calls
|
||||
abi::SYS_OPENAT => {
|
||||
|
@ -8,6 +8,7 @@ pub const SYS_EX_CLONE: usize = 133;
|
||||
pub const SYS_EX_YIELD: usize = 134;
|
||||
pub const SYS_EX_THREAD_EXIT: usize = 135;
|
||||
pub const SYS_EX_THREAD_WAIT: usize = 136;
|
||||
pub const SYS_EX_GETTID: usize = 137;
|
||||
|
||||
pub const SYS_EXIT: usize = 1;
|
||||
pub const SYS_READ: usize = 2;
|
||||
@ -21,3 +22,4 @@ pub const SYS_WAITPID: usize = 9;
|
||||
pub const SYS_IOCTL: usize = 10;
|
||||
pub const SYS_SELECT: usize = 11;
|
||||
pub const SYS_FACCESSAT: usize = 12;
|
||||
// pub const SYS_GETPID: usize = 13;
|
||||
|
@ -188,7 +188,7 @@ pub fn sys_fstatat(
|
||||
///
|
||||
/// System call
|
||||
#[inline(always)]
|
||||
pub fn sys_fork() -> Result<Option<Pid>, Errno> {
|
||||
pub unsafe fn sys_fork() -> Result<Option<Pid>, Errno> {
|
||||
Errno::from_syscall(unsafe { syscall!(abi::SYS_FORK) }).map(|res| {
|
||||
if res != 0 {
|
||||
Some(unsafe { Pid::from_raw(res as u32) })
|
||||
@ -344,3 +344,10 @@ pub fn sys_faccessat(
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn sys_ex_gettid() -> u32 {
|
||||
unsafe {
|
||||
syscall!(abi::SYS_EX_GETTID) as u32
|
||||
}
|
||||
}
|
||||
|
@ -16,21 +16,8 @@ pub mod os;
|
||||
pub mod sys;
|
||||
pub mod sync;
|
||||
pub mod thread;
|
||||
pub mod signal;
|
||||
|
||||
use sys::Signal;
|
||||
|
||||
#[inline(never)]
|
||||
pub(crate) extern "C" fn _signal_handler(arg: Signal) -> ! {
|
||||
trace!("Entered signal handler: arg={:?}", arg);
|
||||
match arg {
|
||||
Signal::Interrupt | Signal::SegmentationFault =>
|
||||
loop {},
|
||||
_ => todo!()
|
||||
}
|
||||
sys::sys_ex_sigreturn();
|
||||
}
|
||||
|
||||
static mut SIGNAL_STACK: [u8; 4096] = [0; 4096];
|
||||
|
||||
#[link_section = ".text._start"]
|
||||
#[no_mangle]
|
||||
@ -40,11 +27,7 @@ extern "C" fn _start(_arg: usize) -> ! {
|
||||
}
|
||||
|
||||
unsafe {
|
||||
sys::sys_ex_signal(
|
||||
_signal_handler as usize,
|
||||
SIGNAL_STACK.as_ptr() as usize + 4096,
|
||||
)
|
||||
.unwrap();
|
||||
thread::init_main();
|
||||
}
|
||||
|
||||
let res = unsafe { main() };
|
||||
@ -53,8 +36,9 @@ extern "C" fn _start(_arg: usize) -> ! {
|
||||
|
||||
#[panic_handler]
|
||||
fn panic_handler(pi: &PanicInfo) -> ! {
|
||||
// TODO handle non-main thread panics
|
||||
// TODO unwind to send panic argument back to parent thread
|
||||
// TODO print to stdout/stderr (if available)
|
||||
trace!("Panic ocurred: {}", pi);
|
||||
let thread = thread::current();
|
||||
trace!("{:?} panicked: {:?}", thread, pi);
|
||||
sys::sys_exit(ExitCode::from(-1));
|
||||
}
|
||||
|
13
libusr/src/signal.rs
Normal file
13
libusr/src/signal.rs
Normal file
@ -0,0 +1,13 @@
|
||||
use libsys::{calls::sys_ex_sigreturn, signal::Signal};
|
||||
use crate::trace;
|
||||
|
||||
#[inline(never)]
|
||||
pub(crate) extern "C" fn signal_handler(arg: Signal) -> ! {
|
||||
trace!("Entered signal handler: arg={:?}", arg);
|
||||
match arg {
|
||||
Signal::Interrupt | Signal::SegmentationFault =>
|
||||
loop {},
|
||||
_ => todo!()
|
||||
}
|
||||
sys_ex_sigreturn();
|
||||
}
|
@ -2,12 +2,14 @@ use alloc::{boxed::Box, sync::Arc, vec};
|
||||
use core::cell::UnsafeCell;
|
||||
use core::mem::MaybeUninit;
|
||||
use libsys::{
|
||||
calls::{sys_ex_clone, sys_ex_signal, sys_ex_thread_exit, sys_ex_thread_wait},
|
||||
calls::{sys_ex_clone, sys_ex_signal, sys_ex_thread_exit, sys_ex_thread_wait, sys_ex_gettid},
|
||||
error::Errno,
|
||||
proc::ExitCode,
|
||||
};
|
||||
|
||||
use crate::trace;
|
||||
use core::sync::atomic::{AtomicU32, Ordering};
|
||||
use core::any::Any;
|
||||
use crate::{trace, signal};
|
||||
use core::fmt;
|
||||
|
||||
struct NativeData<F, T>
|
||||
where
|
||||
@ -16,24 +18,67 @@ where
|
||||
T: Send + 'static,
|
||||
{
|
||||
closure: F,
|
||||
result: Arc<UnsafeCell<MaybeUninit<T>>>,
|
||||
result: ThreadPacket<T>,
|
||||
stack: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Thread {
|
||||
id: u32
|
||||
}
|
||||
|
||||
pub type ThreadResult<T> = Result<T, Box<dyn Any + Send + Sync>>;
|
||||
pub type ThreadPacket<T> = Arc<UnsafeCell<MaybeUninit<ThreadResult<T>>>>;
|
||||
|
||||
pub struct JoinHandle<T> {
|
||||
native: u32,
|
||||
result: Arc<UnsafeCell<MaybeUninit<T>>>,
|
||||
result: ThreadPacket<T>
|
||||
}
|
||||
|
||||
impl Thread {
|
||||
pub const fn id(&self) -> u32 {
|
||||
self.id
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Thread {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_struct("Thread").field("id", &self.id).finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> JoinHandle<T> {
|
||||
pub fn join(self) -> Result<T, ()> {
|
||||
pub fn join(self) -> ThreadResult<T> {
|
||||
sys_ex_thread_wait(self.native).unwrap();
|
||||
if let Ok(result) = Arc::try_unwrap(self.result) {
|
||||
Ok(unsafe { result.into_inner().assume_init() })
|
||||
} else {
|
||||
Err(())
|
||||
unsafe { Arc::try_unwrap(self.result).unwrap().into_inner().assume_init() }
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn init_common(signal_stack_pointer: *mut u8) {
|
||||
let tid = sys_ex_gettid();
|
||||
asm!("msr tpidr_el0, {}", in(reg) tid);
|
||||
|
||||
// thread::current() should be valid at this point
|
||||
|
||||
sys_ex_signal(
|
||||
signal::signal_handler as usize,
|
||||
signal_stack_pointer as usize
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn init_main() {
|
||||
static mut SIGNAL_STACK: [u8; 4096] = [0; 4096];
|
||||
init_common(SIGNAL_STACK.as_mut_ptr().add(SIGNAL_STACK.len()))
|
||||
}
|
||||
|
||||
pub fn current() -> Thread {
|
||||
let mut id: u32;
|
||||
unsafe {
|
||||
asm!("mrs {}, tpidr_el0", out(reg) id);
|
||||
}
|
||||
|
||||
Thread { id }
|
||||
}
|
||||
|
||||
pub fn spawn<F, T>(f: F) -> JoinHandle<T>
|
||||
@ -57,18 +102,14 @@ where
|
||||
let mut signal_stack = vec![0u8; 8192];
|
||||
|
||||
unsafe {
|
||||
sys_ex_signal(
|
||||
crate::_signal_handler as usize,
|
||||
signal_stack.as_mut_ptr() as usize + signal_stack.len(),
|
||||
)
|
||||
.unwrap();
|
||||
init_common(signal_stack.as_mut_ptr().add(signal_stack.len()));
|
||||
}
|
||||
|
||||
let data: Box<NativeData<F, T>> = unsafe { Box::from_raw(data) };
|
||||
let res = (data.closure)();
|
||||
|
||||
unsafe {
|
||||
(&mut *data.result.get()).write(res);
|
||||
(&mut *data.result.get()).write(Ok(res));
|
||||
}
|
||||
|
||||
(data.stack, 8192)
|
||||
|
@ -7,7 +7,7 @@ extern crate libusr;
|
||||
|
||||
#[no_mangle]
|
||||
fn main() -> i32 {
|
||||
let pid = libusr::sys::sys_fork().unwrap();
|
||||
let pid = unsafe { libusr::sys::sys_fork().unwrap() };
|
||||
|
||||
if let Some(pid) = pid {
|
||||
let mut status = 0;
|
||||
|
@ -27,7 +27,7 @@ fn execute(line: &str) -> Result<ExitCode, Errno> {
|
||||
let mut words = line.split(' ');
|
||||
let cmd = words.next().unwrap();
|
||||
|
||||
if let Some(pid) = sys_fork()? {
|
||||
if let Some(pid) = unsafe { sys_fork()? } {
|
||||
let mut status = 0;
|
||||
sys_waitpid(pid, &mut status)?;
|
||||
Ok(ExitCode::from(status))
|
||||
|
Loading…
x
Reference in New Issue
Block a user