Skip to content

Commit

Permalink
split Thread to CurrentThread, refactor exception
Browse files Browse the repository at this point in the history
  • Loading branch information
wangrunji0408 committed Aug 14, 2020
1 parent 33d4836 commit abe4792
Show file tree
Hide file tree
Showing 10 changed files with 215 additions and 192 deletions.
4 changes: 2 additions & 2 deletions linux-loader/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ pub fn run(args: Vec<String>, envs: Vec<String>, rootfs: Arc<dyn FileSystem>) ->
/// - enter user mode
/// - handle trap/interrupt/syscall according to the return value
/// - return the context to the user thread
fn spawn(thread: Arc<Thread>) {
fn spawn(thread: CurrentThread) {
let vmtoken = thread.proc().vmar().table_phys();
let future = async move {
loop {
Expand Down Expand Up @@ -102,7 +102,7 @@ fn spawn(thread: Arc<Thread>) {
}

/// syscall handler entry: create a struct `syscall: Syscall`, and call `syscall.syscall()`
async fn handle_syscall(thread: &Arc<Thread>, regs: &mut GeneralRegs) -> bool {
async fn handle_syscall(thread: &CurrentThread, regs: &mut GeneralRegs) -> bool {
trace!("syscall: {:#x?}", regs);
let num = regs.rax as u32;
let args = [regs.rdi, regs.rsi, regs.rdx, regs.r10, regs.r8, regs.r9];
Expand Down
8 changes: 7 additions & 1 deletion linux-object/src/thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use alloc::sync::Arc;
use kernel_hal::user::{Out, UserOutPtr, UserPtr};
use kernel_hal::VirtAddr;
use spin::{Mutex, MutexGuard};
use zircon_object::task::{Process, Thread};
use zircon_object::task::{CurrentThread, Process, Thread};
use zircon_object::ZxResult;

/// Thread extension for linux
Expand All @@ -16,6 +16,10 @@ pub trait ThreadExt {
fn lock_linux(&self) -> MutexGuard<'_, LinuxThread>;
/// Set pointer to thread ID.
fn set_tid_address(&self, tidptr: UserOutPtr<i32>);
}

/// CurrentThread extension for linux
pub trait CurrentThreadExt {
/// exit linux thread
fn exit_linux(&self, exit_code: i32);
}
Expand All @@ -39,7 +43,9 @@ impl ThreadExt for Thread {
fn set_tid_address(&self, tidptr: UserPtr<i32, Out>) {
self.lock_linux().clear_child_tid = tidptr;
}
}

impl CurrentThreadExt for CurrentThread {
/// Exit current thread for Linux.
fn exit_linux(&self, _exit_code: i32) {
let mut linux_thread = self.lock_linux();
Expand Down
4 changes: 2 additions & 2 deletions linux-syscall/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,13 @@ mod vm;
/// The struct of Syscall which stores the information about making a syscall
pub struct Syscall<'a> {
/// the thread making a syscall
pub thread: &'a Arc<Thread>,
pub thread: &'a CurrentThread,
/// the entry of current syscall
pub syscall_entry: VirtAddr,
/// store the regs statues
pub regs: &'a mut GeneralRegs,
/// the spawn function in linux-loader
pub spawn_fn: fn(thread: Arc<Thread>),
pub spawn_fn: fn(thread: CurrentThread),
/// Set `true` to exit current task.
pub exit: bool,
}
Expand Down
2 changes: 1 addition & 1 deletion linux-syscall/src/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use bitflags::bitflags;
use core::fmt::Debug;
use linux_object::fs::INodeExt;
use linux_object::loader::LinuxElfLoader;
use linux_object::thread::ThreadExt;
use linux_object::thread::{CurrentThreadExt, ThreadExt};

impl Syscall<'_> {
/// Fork the current process. Return the child's PID.
Expand Down
25 changes: 10 additions & 15 deletions zircon-loader/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,22 +172,17 @@ kcounter!(EXCEPTIONS_USER, "exceptions.user");
kcounter!(EXCEPTIONS_TIMER, "exceptions.timer");
kcounter!(EXCEPTIONS_PGFAULT, "exceptions.pgfault");

fn spawn(thread: Arc<Thread>) {
fn spawn(thread: CurrentThread) {
let vmtoken = thread.proc().vmar().table_phys();
let future = async move {
kernel_hal::Thread::set_tid(thread.id(), thread.proc().id());
if thread.is_first_thread() {
Exception::create(&thread, ExceptionType::ProcessStarting, None)
.handle_with_exceptionates(
false,
JobDebuggerIterator::new(thread.proc().job()),
true,
)
.await;
let exception = Exception::create(&thread, ExceptionType::ProcessStarting, None);
thread.wait_for_exception_handling(exception).await;
};
Exception::create(&thread, ExceptionType::ThreadStarting, None)
.handle_with_exceptionates(false, Some(thread.proc().debug_exceptionate()), false)
.await;
let exception = Exception::create(&thread, ExceptionType::ThreadStarting, None);
thread.wait_for_exception_handling(exception).await;

loop {
let mut cx = thread.wait_for_run().await;
if thread.state() == ThreadState::Dying {
Expand Down Expand Up @@ -243,7 +238,7 @@ fn spawn(thread: Arc<Thread>) {
error!("Page Fault from user mode: {:#x?}", cx);
let exception =
Exception::create(&thread, ExceptionType::FatalPageFault, Some(&cx));
exception.handle(true).await;
thread.wait_for_exception_handling(exception).await;
}
}
0x8 => {
Expand All @@ -259,7 +254,7 @@ fn spawn(thread: Arc<Thread>) {
};
error!("User mode exception: {:?} {:#x?}", type_, cx);
let exception = Exception::create(&thread, type_, Some(&cx));
exception.handle(true).await;
thread.wait_for_exception_handling(exception).await;
}
}
thread.end_running(cx);
Expand All @@ -277,7 +272,7 @@ fn spawn(thread: Arc<Thread>) {
kernel_hal::Thread::spawn(Box::pin(future), vmtoken);
}

async fn handle_syscall(thread: &Arc<Thread>, regs: &mut GeneralRegs) {
async fn handle_syscall(thread: &CurrentThread, regs: &mut GeneralRegs) {
#[cfg(target_arch = "x86_64")]
let num = regs.rax as u32;
#[cfg(target_arch = "aarch64")]
Expand Down Expand Up @@ -305,7 +300,7 @@ async fn handle_syscall(thread: &Arc<Thread>, regs: &mut GeneralRegs) {
];
let mut syscall = Syscall {
regs,
thread: thread.clone(),
thread,
spawn_fn: spawn,
};
let ret = syscall.syscall(num, args).await as usize;
Expand Down
54 changes: 30 additions & 24 deletions zircon-object/src/task/exception.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use {
super::*, crate::ipc::*, crate::object::*, alloc::sync::Arc, alloc::vec, alloc::vec::Vec,
core::mem::size_of, futures::channel::oneshot, futures::pin_mut, kernel_hal::UserContext,
spin::Mutex,
core::mem::size_of, futures::channel::oneshot, kernel_hal::UserContext, spin::Mutex,
};

/// Kernel-owned exception channel endpoint.
Expand Down Expand Up @@ -197,6 +196,12 @@ pub enum ExceptionType {
ProcessStarting = 0x8308,
}

impl ExceptionType {
fn is_fatal(self) -> bool {
(self as u32) < 0x1000
}
}

/// Type of the exception channel
#[repr(u32)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
Expand Down Expand Up @@ -341,31 +346,32 @@ impl Exception {
///
/// Note that it's possible that this may returns before exception was send to any exception channel.
/// This happens only when the thread is killed before we send the exception.
pub async fn handle(self: &Arc<Self>, fatal: bool) {
self.handle_with_exceptionates(fatal, ExceptionateIterator::new(self), false)
.await
}

/// Same as `handle`, but use a customized iterator.
///
/// If `first_only` is true, this will only send exception to the first one that received the exception
/// even when the exception is not handled.
pub async fn handle_with_exceptionates(
self: &Arc<Self>,
fatal: bool,
exceptionates: impl IntoIterator<Item = Arc<Exceptionate>>,
first_only: bool,
) {
let future = self.handle_internal(exceptionates, first_only);
pin_mut!(future);
let result = self.thread.wait_for_exception(future, self.clone()).await;
if result == Err(ZxError::NEXT) && fatal {
pub(super) async fn handle(self: &Arc<Self>) {
let result = match self.type_ {
ExceptionType::ProcessStarting => {
self.handle_with(JobDebuggerIterator::new(self.thread.proc().job()), true)
.await
}
ExceptionType::ThreadStarting | ExceptionType::ThreadExiting => {
self.handle_with(Some(self.thread.proc().debug_exceptionate()), false)
.await
}
_ => {
self.handle_with(ExceptionateIterator::new(self), false)
.await
}
};
if result == Err(ZxError::NEXT) && self.type_.is_fatal() {
// Nobody handled the exception, kill myself
self.thread.proc().exit(TASK_RETCODE_SYSCALL_KILL);
}
}

async fn handle_internal(
/// Handle the exception with a customized iterator.
///
/// If `first_only` is true, this will only send exception to the first one that received the exception
/// even when the exception is not handled.
async fn handle_with(
self: &Arc<Self>,
exceptionates: impl IntoIterator<Item = Arc<Exceptionate>>,
first_only: bool,
Expand Down Expand Up @@ -479,13 +485,13 @@ impl<'a> Iterator for ExceptionateIterator<'a> {
}

/// This is only used by ProcessStarting exceptions
pub struct JobDebuggerIterator {
struct JobDebuggerIterator {
job: Option<Arc<Job>>,
}

impl JobDebuggerIterator {
/// Create a new JobDebuggerIterator
pub fn new(job: Arc<Job>) -> Self {
fn new(job: Arc<Job>) -> Self {
JobDebuggerIterator { job: Some(job) }
}
}
Expand Down
3 changes: 1 addition & 2 deletions zircon-object/src/task/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,6 @@ impl Process {
name: &str,
ext: impl Any + Send + Sync,
) -> ZxResult<Arc<Self>> {
// TODO: _options -> options
let proc = Arc::new(Process {
base: KObjectBase::with_name(name),
_counter: CountHelper::new(),
Expand Down Expand Up @@ -145,7 +144,7 @@ impl Process {
stack: usize,
arg1: Option<Handle>,
arg2: usize,
spawn_fn: fn(thread: Arc<Thread>),
spawn_fn: fn(thread: CurrentThread),
) -> ZxResult {
let handle_value;
{
Expand Down
Loading

0 comments on commit abe4792

Please sign in to comment.