diff --git a/kernel/src/proc/process.rs b/kernel/src/proc/process.rs index 2464102..f1e9162 100644 --- a/kernel/src/proc/process.rs +++ b/kernel/src/proc/process.rs @@ -146,6 +146,33 @@ impl Process { PROCESSES.lock().get(&pid).cloned() } + fn find1(a: u32) -> Option { + 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); } diff --git a/kernel/src/proc/thread.rs b/kernel/src/proc/thread.rs index 5fdeecf..ec79803 100644 --- a/kernel/src/proc/thread.rs +++ b/kernel/src/proc/thread.rs @@ -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 { diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index ca7e1fd..d638274 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -56,8 +56,7 @@ fn find_at_node>( } } -/// Main system call dispatcher function -pub fn syscall(num: SystemCall, args: &[usize]) -> Result { +fn _syscall(num: SystemCall, args: &[usize]) -> Result { match num { // I/O SystemCall::Read => { @@ -449,3 +448,14 @@ pub fn syscall(num: SystemCall, args: &[usize]) -> Result { SystemCall::Fork => unreachable!(), } } + +/// Main system call dispatcher function +pub fn syscall(num: SystemCall, args: &[usize]) -> Result { + let thread = Thread::current(); + let process = thread.owner().unwrap(); + let result = _syscall(num, args); + if !thread.is_handling_signal() { + process.handle_pending_signals(); + } + result +}