forked from rcore-os/zCore
object: move exceptionate into Task trait
This commit is contained in:
parent
62bd8a5139
commit
98c064d0fe
|
@ -186,7 +186,7 @@ fn spawn(thread: Arc<Thread>) {
|
|||
.await;
|
||||
};
|
||||
Exception::create(thread.clone(), ExceptionType::ThreadStarting, None)
|
||||
.handle_with_exceptionates(false, Some(thread.proc().get_debug_exceptionate()), false)
|
||||
.handle_with_exceptionates(false, Some(thread.proc().debug_exceptionate()), false)
|
||||
.await;
|
||||
loop {
|
||||
let mut cx = thread.wait_for_run().await;
|
||||
|
@ -270,7 +270,7 @@ fn spawn(thread: Arc<Thread>) {
|
|||
let end_exception = Exception::create(thread.clone(), ExceptionType::ThreadExiting, None);
|
||||
let handled = thread
|
||||
.proc()
|
||||
.get_debug_exceptionate()
|
||||
.debug_exceptionate()
|
||||
.send_exception(&end_exception);
|
||||
if let Ok(future) = handled {
|
||||
thread.dying_run(future).await.ok();
|
||||
|
|
|
@ -23,7 +23,7 @@ define_count_helper!(Vcpu);
|
|||
|
||||
impl Vcpu {
|
||||
pub fn new(guest: Arc<Guest>, entry: u64, thread: Arc<Thread>) -> ZxResult<Arc<Self>> {
|
||||
if thread.get_flags().contains(ThreadFlag::VCPU) {
|
||||
if thread.flags().contains(ThreadFlag::VCPU) {
|
||||
return Err(ZxError::BAD_STATE);
|
||||
}
|
||||
let inner = Mutex::new(VcpuInner::new(entry, guest.rvm_guest())?);
|
||||
|
|
|
@ -475,20 +475,20 @@ impl<'a> Iterator for ExceptionateIterator<'a> {
|
|||
} else {
|
||||
ExceptionateIteratorState::Thread
|
||||
};
|
||||
return Some(proc.get_debug_exceptionate());
|
||||
return Some(proc.debug_exceptionate());
|
||||
}
|
||||
ExceptionateIteratorState::Thread => {
|
||||
self.state = ExceptionateIteratorState::Process;
|
||||
return Some(self.exception.thread.get_exceptionate());
|
||||
return Some(self.exception.thread.exceptionate());
|
||||
}
|
||||
ExceptionateIteratorState::Process => {
|
||||
let proc = self.exception.thread.proc();
|
||||
self.state = ExceptionateIteratorState::Debug(true);
|
||||
return Some(proc.get_exceptionate());
|
||||
return Some(proc.exceptionate());
|
||||
}
|
||||
ExceptionateIteratorState::Job(job) => {
|
||||
let parent = job.parent();
|
||||
let result = job.get_exceptionate();
|
||||
let result = job.exceptionate();
|
||||
self.state = parent.map_or(
|
||||
ExceptionateIteratorState::Finished,
|
||||
ExceptionateIteratorState::Job,
|
||||
|
@ -516,7 +516,7 @@ impl JobDebuggerIterator {
|
|||
impl Iterator for JobDebuggerIterator {
|
||||
type Item = Arc<Exceptionate>;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let result = self.job.as_ref().map(|job| job.get_debug_exceptionate());
|
||||
let result = self.job.as_ref().map(|job| job.debug_exceptionate());
|
||||
self.job = self.job.as_ref().and_then(|job| job.parent());
|
||||
result
|
||||
}
|
||||
|
@ -536,11 +536,11 @@ mod tests {
|
|||
let exception = Exception::create(thread.clone(), ExceptionType::Synth, None);
|
||||
let iterator = ExceptionateIterator::new(&exception);
|
||||
let expected = [
|
||||
proc.get_debug_exceptionate(),
|
||||
thread.get_exceptionate(),
|
||||
proc.get_exceptionate(),
|
||||
job.get_exceptionate(),
|
||||
parent_job.get_exceptionate(),
|
||||
proc.debug_exceptionate(),
|
||||
thread.exceptionate(),
|
||||
proc.exceptionate(),
|
||||
job.exceptionate(),
|
||||
parent_job.exceptionate(),
|
||||
];
|
||||
for (actual, expected) in iterator.zip(expected.iter()) {
|
||||
assert!(Arc::ptr_eq(&actual, expected));
|
||||
|
@ -558,12 +558,12 @@ mod tests {
|
|||
exception.inner.lock().second_chance = true;
|
||||
let iterator = ExceptionateIterator::new(&exception);
|
||||
let expected = [
|
||||
proc.get_debug_exceptionate(),
|
||||
thread.get_exceptionate(),
|
||||
proc.get_exceptionate(),
|
||||
proc.get_debug_exceptionate(),
|
||||
job.get_exceptionate(),
|
||||
parent_job.get_exceptionate(),
|
||||
proc.debug_exceptionate(),
|
||||
thread.exceptionate(),
|
||||
proc.exceptionate(),
|
||||
proc.debug_exceptionate(),
|
||||
job.exceptionate(),
|
||||
parent_job.exceptionate(),
|
||||
];
|
||||
for (actual, expected) in iterator.zip(expected.iter()) {
|
||||
assert!(Arc::ptr_eq(&actual, expected));
|
||||
|
@ -579,9 +579,9 @@ mod tests {
|
|||
|
||||
let iterator = JobDebuggerIterator::new(child_job.clone());
|
||||
let expected = [
|
||||
child_job.get_debug_exceptionate(),
|
||||
job.get_debug_exceptionate(),
|
||||
parent_job.get_debug_exceptionate(),
|
||||
child_job.debug_exceptionate(),
|
||||
job.debug_exceptionate(),
|
||||
parent_job.debug_exceptionate(),
|
||||
];
|
||||
for (actual, expected) in iterator.zip(expected.iter()) {
|
||||
assert!(Arc::ptr_eq(&actual, expected));
|
||||
|
@ -639,22 +639,22 @@ mod tests {
|
|||
};
|
||||
|
||||
// proc debug should get the exception first
|
||||
create_handler(&proc.get_debug_exceptionate(), true, false, 0);
|
||||
create_handler(&proc.debug_exceptionate(), true, false, 0);
|
||||
// thread should get the exception next
|
||||
create_handler(&thread.get_exceptionate(), true, false, 1);
|
||||
create_handler(&thread.exceptionate(), true, false, 1);
|
||||
// here we omit proc to test that we can handle the case that there is none handler
|
||||
// job should get the exception and handle it next
|
||||
create_handler(&job.get_exceptionate(), true, true, 3);
|
||||
create_handler(&job.exceptionate(), true, true, 3);
|
||||
// since exception is handled we should not get it from parent job
|
||||
create_handler(&parent_job.get_exceptionate(), false, false, 4);
|
||||
create_handler(&parent_job.exceptionate(), false, false, 4);
|
||||
|
||||
exception.handle(false).await;
|
||||
|
||||
// terminate handlers by shutdown the related exceptionates
|
||||
thread.get_exceptionate().shutdown();
|
||||
proc.get_debug_exceptionate().shutdown();
|
||||
job.get_exceptionate().shutdown();
|
||||
parent_job.get_exceptionate().shutdown();
|
||||
thread.exceptionate().shutdown();
|
||||
proc.debug_exceptionate().shutdown();
|
||||
job.exceptionate().shutdown();
|
||||
parent_job.exceptionate().shutdown();
|
||||
|
||||
// test for the order: proc debug -> thread -> job
|
||||
assert_eq!(handled_order.lock().clone(), vec![0, 1, 3]);
|
||||
|
|
|
@ -198,16 +198,6 @@ impl Job {
|
|||
}
|
||||
}
|
||||
|
||||
/// Get the exceptionate of this job.
|
||||
pub fn get_exceptionate(&self) -> Arc<Exceptionate> {
|
||||
self.exceptionate.clone()
|
||||
}
|
||||
|
||||
/// Get the debug exceptionate of this job.
|
||||
pub fn get_debug_exceptionate(&self) -> Arc<Exceptionate> {
|
||||
self.debug_exceptionate.clone()
|
||||
}
|
||||
|
||||
/// Get KoIDs of Processes.
|
||||
pub fn process_ids(&self) -> Vec<KoID> {
|
||||
self.inner.lock().processes.iter().map(|p| p.id()).collect()
|
||||
|
@ -229,9 +219,21 @@ impl Job {
|
|||
self.inner.lock().is_empty()
|
||||
}
|
||||
|
||||
/// The job finally terminates.
|
||||
fn terminate(&self) {
|
||||
self.exceptionate.shutdown();
|
||||
self.debug_exceptionate.shutdown();
|
||||
self.base.signal_set(Signal::JOB_TERMINATED);
|
||||
if let Some(parent) = self.parent.as_ref() {
|
||||
parent.remove_child(&self.inner.lock().self_ref)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Task for Job {
|
||||
/// Kill the job. The job do not terminate immediately when killed.
|
||||
/// It will terminate after all its children and processes are terminated.
|
||||
pub fn kill(&self) {
|
||||
fn kill(&self) {
|
||||
let (children, processes) = {
|
||||
let mut inner = self.inner.lock();
|
||||
if inner.killed {
|
||||
|
@ -254,14 +256,20 @@ impl Job {
|
|||
}
|
||||
}
|
||||
|
||||
/// The job finally terminates.
|
||||
fn terminate(&self) {
|
||||
self.exceptionate.shutdown();
|
||||
self.debug_exceptionate.shutdown();
|
||||
self.base.signal_set(Signal::JOB_TERMINATED);
|
||||
if let Some(parent) = self.parent.as_ref() {
|
||||
parent.remove_child(&self.inner.lock().self_ref)
|
||||
}
|
||||
fn suspend(&self) {
|
||||
panic!("job do not support suspend");
|
||||
}
|
||||
|
||||
fn resume(&self) {
|
||||
panic!("job do not support resume");
|
||||
}
|
||||
|
||||
fn exceptionate(&self) -> Arc<Exceptionate> {
|
||||
self.exceptionate.clone()
|
||||
}
|
||||
|
||||
fn debug_exceptionate(&self) -> Arc<Exceptionate> {
|
||||
self.debug_exceptionate.clone()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
//! Objects for Task Management.
|
||||
|
||||
use super::*;
|
||||
use alloc::sync::Arc;
|
||||
|
||||
mod exception;
|
||||
mod job;
|
||||
|
@ -26,6 +27,12 @@ pub trait Task: Sync + Send {
|
|||
|
||||
/// Resume the task
|
||||
fn resume(&self);
|
||||
|
||||
/// Get the exceptionate.
|
||||
fn exceptionate(&self) -> Arc<Exceptionate>;
|
||||
|
||||
/// Get the debug exceptionate.
|
||||
fn debug_exceptionate(&self) -> Arc<Exceptionate>;
|
||||
}
|
||||
|
||||
/// The return code set when a task is killed via zx_task_kill().
|
||||
|
|
|
@ -492,16 +492,6 @@ impl Process {
|
|||
self.inner.lock().get_cancel_token(handle_value)
|
||||
}
|
||||
|
||||
/// Get the exceptionate of this process.
|
||||
pub fn get_exceptionate(&self) -> Arc<Exceptionate> {
|
||||
self.exceptionate.clone()
|
||||
}
|
||||
|
||||
/// Get the debug exceptionate of this process.
|
||||
pub fn get_debug_exceptionate(&self) -> Arc<Exceptionate> {
|
||||
self.debug_exceptionate.clone()
|
||||
}
|
||||
|
||||
/// Get KoIDs of Threads.
|
||||
pub fn thread_ids(&self) -> Vec<KoID> {
|
||||
self.inner.lock().threads.iter().map(|t| t.id()).collect()
|
||||
|
@ -526,6 +516,14 @@ impl Task for Process {
|
|||
thread.resume();
|
||||
}
|
||||
}
|
||||
|
||||
fn exceptionate(&self) -> Arc<Exceptionate> {
|
||||
self.exceptionate.clone()
|
||||
}
|
||||
|
||||
fn debug_exceptionate(&self) -> Arc<Exceptionate> {
|
||||
self.debug_exceptionate.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl ProcessInner {
|
||||
|
|
|
@ -131,30 +131,34 @@ struct ThreadInner {
|
|||
}
|
||||
|
||||
impl ThreadInner {
|
||||
pub fn get_state(&self) -> ThreadState {
|
||||
fn get_state(&self) -> ThreadState {
|
||||
if self.suspend_count == 0 || self.state == ThreadState::BlockedException {
|
||||
self.state
|
||||
} else {
|
||||
ThreadState::Suspended
|
||||
}
|
||||
}
|
||||
|
||||
fn update_signal(&self, base: &KObjectBase) {
|
||||
if self.state == ThreadState::Dead {
|
||||
base.signal_clear(Signal::THREAD_RUNNING);
|
||||
base.signal_clear(Signal::THREAD_SUSPENDED);
|
||||
base.signal_set(Signal::THREAD_TERMINATED)
|
||||
base.signal_change(
|
||||
Signal::THREAD_RUNNING | Signal::THREAD_SUSPENDED,
|
||||
Signal::THREAD_TERMINATED,
|
||||
);
|
||||
} else if self.state == ThreadState::New || self.state == ThreadState::Dying {
|
||||
base.signal_clear(Signal::THREAD_RUNNING);
|
||||
base.signal_clear(Signal::THREAD_SUSPENDED);
|
||||
base.signal_clear(Signal::THREAD_TERMINATED)
|
||||
base.signal_clear(
|
||||
Signal::THREAD_RUNNING | Signal::THREAD_SUSPENDED | Signal::THREAD_TERMINATED,
|
||||
);
|
||||
} else if self.suspend_count == 0 || self.state == ThreadState::BlockedException {
|
||||
base.signal_set(Signal::THREAD_RUNNING);
|
||||
base.signal_clear(Signal::THREAD_SUSPENDED);
|
||||
base.signal_clear(Signal::THREAD_TERMINATED)
|
||||
base.signal_change(
|
||||
Signal::THREAD_TERMINATED | Signal::THREAD_SUSPENDED,
|
||||
Signal::THREAD_RUNNING,
|
||||
);
|
||||
} else {
|
||||
base.signal_clear(Signal::THREAD_RUNNING);
|
||||
base.signal_set(Signal::THREAD_SUSPENDED);
|
||||
base.signal_clear(Signal::THREAD_TERMINATED)
|
||||
base.signal_change(
|
||||
Signal::THREAD_RUNNING | Signal::THREAD_TERMINATED,
|
||||
Signal::THREAD_SUSPENDED,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -476,11 +480,6 @@ impl Thread {
|
|||
self.inner.lock().get_state()
|
||||
}
|
||||
|
||||
/// Get the exceptionate.
|
||||
pub fn get_exceptionate(&self) -> Arc<Exceptionate> {
|
||||
self.exceptionate.clone()
|
||||
}
|
||||
|
||||
/// Add the parameter to the time this thread has run on cpu.
|
||||
pub fn time_add(&self, time: u128) {
|
||||
self.inner.lock().time += time;
|
||||
|
@ -502,15 +501,12 @@ impl Thread {
|
|||
}
|
||||
|
||||
/// Get the thread's flags.
|
||||
pub fn get_flags(&self) -> ThreadFlag {
|
||||
pub fn flags(&self) -> ThreadFlag {
|
||||
self.inner.lock().flags
|
||||
}
|
||||
|
||||
/// Apply `f` to the thread's flags.
|
||||
pub fn update_flags<F>(&self, f: F)
|
||||
where
|
||||
F: FnOnce(&mut ThreadFlag),
|
||||
{
|
||||
pub fn update_flags(&self, f: impl FnOnce(&mut ThreadFlag)) {
|
||||
f(&mut self.inner.lock().flags)
|
||||
}
|
||||
}
|
||||
|
@ -545,6 +541,14 @@ impl Task for Thread {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn exceptionate(&self) -> Arc<Exceptionate> {
|
||||
self.exceptionate.clone()
|
||||
}
|
||||
|
||||
fn debug_exceptionate(&self) -> Arc<Exceptionate> {
|
||||
panic!("thread do not have debug exceptionate");
|
||||
}
|
||||
}
|
||||
|
||||
/// `into_result` returns `Self` if the type parameter is already a `ZxResult`,
|
||||
|
@ -631,7 +635,7 @@ mod tests {
|
|||
let root_job = Job::root();
|
||||
let proc = Process::create(&root_job, "proc").expect("failed to create process");
|
||||
let thread = Thread::create(&proc, "thread").expect("failed to create thread");
|
||||
assert_eq!(thread.get_flags(), ThreadFlag::empty());
|
||||
assert_eq!(thread.flags(), ThreadFlag::empty());
|
||||
|
||||
let thread: Arc<dyn KernelObject> = thread;
|
||||
assert_eq!(thread.related_koid(), proc.id());
|
||||
|
|
|
@ -25,20 +25,20 @@ impl Syscall<'_> {
|
|||
return Err(ZxError::ACCESS_DENIED);
|
||||
}
|
||||
match option {
|
||||
ExceptionChannelOption::None => job.get_exceptionate(),
|
||||
ExceptionChannelOption::Debugger => job.get_debug_exceptionate(),
|
||||
ExceptionChannelOption::None => job.exceptionate(),
|
||||
ExceptionChannelOption::Debugger => job.debug_exceptionate(),
|
||||
}
|
||||
} else if let Ok(process) = task.clone().downcast_arc::<Process>() {
|
||||
if !rights.contains(Rights::ENUMERATE) {
|
||||
return Err(ZxError::ACCESS_DENIED);
|
||||
}
|
||||
match option {
|
||||
ExceptionChannelOption::None => process.get_exceptionate(),
|
||||
ExceptionChannelOption::Debugger => process.get_debug_exceptionate(),
|
||||
ExceptionChannelOption::None => process.exceptionate(),
|
||||
ExceptionChannelOption::Debugger => process.debug_exceptionate(),
|
||||
}
|
||||
} else if let Ok(thread) = task.clone().downcast_arc::<Thread>() {
|
||||
match option {
|
||||
ExceptionChannelOption::None => thread.get_exceptionate(),
|
||||
ExceptionChannelOption::None => thread.exceptionate(),
|
||||
ExceptionChannelOption::Debugger => return Err(ZxError::INVALID_ARGS),
|
||||
}
|
||||
} else {
|
||||
|
|
Loading…
Reference in New Issue