fix: enter signal handler AFTER syscall abort

This commit is contained in:
2021-12-01 12:37:49 +02:00
parent a577b2dcc4
commit bd3d4e964d
3 changed files with 51 additions and 4 deletions
+34 -2
View File
@@ -146,6 +146,33 @@ impl Process {
PROCESSES.lock().get(&pid).cloned()
}
fn find1(a: u32) -> Option<usize> {
for i in 0..32 {
if a & (1 << i) != 0 {
return Some(i);
}
}
None
}
/// Handles all pending signals (when returning from aborted syscall)
pub fn handle_pending_signals(&self) {
let mut lock = self.inner.lock();
let ttbr0 = lock.space.as_mut().unwrap().address_phys() | ((lock.id.asid() as usize) << 48);
let main_thread = Thread::get(lock.threads[0]).unwrap();
drop(lock);
loop {
let state = self.signal_state.load(Ordering::Acquire);
if let Some(signal) = Self::find1(state).map(|e| Signal::try_from(e as u32).unwrap()) {
self.signal_state.fetch_and(!(1 << (signal as u32)), Ordering::Release);
main_thread.clone().enter_signal(signal, ttbr0);
} else {
break;
}
}
}
/// Sets a pending signal for a process
pub fn set_signal(&self, signal: Signal) {
let mut lock = self.inner.lock();
@@ -162,7 +189,7 @@ impl Process {
main_thread.enter_signal(signal, ttbr0);
}
ThreadState::Waiting => {
main_thread.clone().setup_signal(signal, ttbr0);
self.signal_state.fetch_or(1 << (signal as u32), Ordering::Release);
main_thread.interrupt_wait(true);
}
ThreadState::Ready => {
@@ -180,6 +207,7 @@ impl Process {
pub fn enter_fault_signal(&self, thread: ThreadRef, signal: Signal) {
let mut lock = self.inner.lock();
let ttbr0 = lock.space.as_mut().unwrap().address_phys() | ((lock.id.asid() as usize) << 48);
drop(lock);
thread.enter_signal(signal, ttbr0);
}
@@ -249,7 +277,11 @@ impl Process {
lock.state = ProcessState::Finished;
for &tid in lock.threads.iter() {
Thread::get(tid).unwrap().terminate(status);
let thread = Thread::get(tid).unwrap();
if thread.state() == ThreadState::Waiting {
todo!()
}
thread.terminate(status);
SCHED.dequeue(tid);
}
+5
View File
@@ -61,6 +61,11 @@ impl Thread {
SCHED.current_thread()
}
/// Returns `true` if the thread is currently executing a signal handler context
pub fn is_handling_signal(&self) -> bool {
self.signal_pending.load(Ordering::Acquire) != 0
}
/// Returns a reference to thread `tid`, if it exists
#[inline]
pub fn get(tid: Tid) -> Option<ThreadRef> {
+12 -2
View File
@@ -56,8 +56,7 @@ fn find_at_node<T: DerefMut<Target = ProcessIo>>(
}
}
/// Main system call dispatcher function
pub fn syscall(num: SystemCall, args: &[usize]) -> Result<usize, Errno> {
fn _syscall(num: SystemCall, args: &[usize]) -> Result<usize, Errno> {
match num {
// I/O
SystemCall::Read => {
@@ -449,3 +448,14 @@ pub fn syscall(num: SystemCall, args: &[usize]) -> Result<usize, Errno> {
SystemCall::Fork => unreachable!(),
}
}
/// Main system call dispatcher function
pub fn syscall(num: SystemCall, args: &[usize]) -> Result<usize, Errno> {
let thread = Thread::current();
let process = thread.owner().unwrap();
let result = _syscall(num, args);
if !thread.is_handling_signal() {
process.handle_pending_signals();
}
result
}