Apply RwLock to the sig_queues of Process and Thread

The new RwLock has better performance than SgxMutex and SgxRwLock.
This commit is contained in:
He Sun 2020-06-28 16:37:40 +08:00
parent 83637d7938
commit 4f965fd8db
11 changed files with 31 additions and 22 deletions

@ -38,8 +38,8 @@ pub fn broadcast_interrupts() -> Result<usize> {
let should_interrupt_thread = |thread: &&ThreadRef| -> bool { let should_interrupt_thread = |thread: &&ThreadRef| -> bool {
// TODO: check Thread::sig_mask to reduce false positives // TODO: check Thread::sig_mask to reduce false positives
thread.process().is_forced_to_exit() thread.process().is_forced_to_exit()
|| !thread.sig_queues().lock().unwrap().empty() || !thread.sig_queues().read().unwrap().empty()
|| !thread.process().sig_queues().lock().unwrap().empty() || !thread.process().sig_queues().read().unwrap().empty()
}; };
let num_signaled_threads = crate::process::table::get_all_threads() let num_signaled_threads = crate::process::table::get_all_threads()

@ -17,6 +17,7 @@ pub use crate::error::Result;
pub use crate::error::*; pub use crate::error::*;
pub use crate::fs::{File, FileDesc, FileRef}; pub use crate::fs::{File, FileDesc, FileRef};
pub use crate::process::{pid_t, uid_t}; pub use crate::process::{pid_t, uid_t};
pub use crate::util::sync::RwLock;
macro_rules! debug_trace { macro_rules! debug_trace {
() => { () => {

@ -130,6 +130,6 @@ fn exit_process(thread: &ThreadRef, term_status: TermStatus) {
fn send_sigchld_to(parent: &Arc<Process>) { fn send_sigchld_to(parent: &Arc<Process>) {
let signal = Box::new(KernelSignal::new(SigNum::from(SIGCHLD))); let signal = Box::new(KernelSignal::new(SigNum::from(SIGCHLD)));
let mut sig_queues = parent.sig_queues().lock().unwrap(); let mut sig_queues = parent.sig_queues().write().unwrap();
sig_queues.enqueue(signal); sig_queues.enqueue(signal);
} }

@ -100,7 +100,7 @@ impl ProcessBuilder {
let parent = self.parent.take().map(|parent| SgxRwLock::new(parent)); let parent = self.parent.take().map(|parent| SgxRwLock::new(parent));
let inner = SgxMutex::new(ProcessInner::new()); let inner = SgxMutex::new(ProcessInner::new());
let sig_dispositions = SgxRwLock::new(SigDispositions::new()); let sig_dispositions = SgxRwLock::new(SigDispositions::new());
let sig_queues = SgxMutex::new(SigQueues::new()); let sig_queues = RwLock::new(SigQueues::new());
let forced_exit_status = ForcedExitStatus::new(); let forced_exit_status = ForcedExitStatus::new();
Arc::new(Process { Arc::new(Process {
pid, pid,

@ -20,7 +20,7 @@ pub struct Process {
inner: SgxMutex<ProcessInner>, inner: SgxMutex<ProcessInner>,
// Signal // Signal
sig_dispositions: SgxRwLock<SigDispositions>, sig_dispositions: SgxRwLock<SigDispositions>,
sig_queues: SgxMutex<SigQueues>, sig_queues: RwLock<SigQueues>,
forced_exit_status: ForcedExitStatus, forced_exit_status: ForcedExitStatus,
} }
@ -100,7 +100,7 @@ impl Process {
} }
/// Get the signal queues for process-directed signals. /// Get the signal queues for process-directed signals.
pub fn sig_queues(&self) -> &SgxMutex<SigQueues> { pub fn sig_queues(&self) -> &RwLock<SigQueues> {
&self.sig_queues &self.sig_queues
} }

@ -107,7 +107,7 @@ impl ThreadBuilder {
let sched = self.sched.unwrap_or_default(); let sched = self.sched.unwrap_or_default();
let rlimits = self.rlimits.unwrap_or_default(); let rlimits = self.rlimits.unwrap_or_default();
let name = SgxRwLock::new(self.name.unwrap_or_default()); let name = SgxRwLock::new(self.name.unwrap_or_default());
let sig_queues = SgxMutex::new(SigQueues::new()); let sig_queues = RwLock::new(SigQueues::new());
let sig_mask = SgxRwLock::new(SigSet::new_empty()); let sig_mask = SgxRwLock::new(SigSet::new_empty());
let sig_tmp_mask = SgxRwLock::new(SigSet::new_empty()); let sig_tmp_mask = SgxRwLock::new(SigSet::new_empty());
let sig_stack = SgxMutex::new(None); let sig_stack = SgxMutex::new(None);

@ -36,7 +36,7 @@ pub struct Thread {
sched: SchedAgentRef, sched: SchedAgentRef,
rlimits: ResourceLimitsRef, rlimits: ResourceLimitsRef,
// Signal // Signal
sig_queues: SgxMutex<SigQueues>, sig_queues: RwLock<SigQueues>,
sig_mask: SgxRwLock<SigSet>, sig_mask: SgxRwLock<SigSet>,
sig_tmp_mask: SgxRwLock<SigSet>, sig_tmp_mask: SgxRwLock<SigSet>,
sig_stack: SgxMutex<Option<SigStack>>, sig_stack: SgxMutex<Option<SigStack>>,
@ -81,7 +81,7 @@ impl Thread {
} }
/// Get the signal queues for thread-directed signals. /// Get the signal queues for thread-directed signals.
pub fn sig_queues(&self) -> &SgxMutex<SigQueues> { pub fn sig_queues(&self) -> &RwLock<SigQueues> {
&self.sig_queues &self.sig_queues
} }

@ -16,7 +16,7 @@ pub fn do_kill(filter: ProcessFilter, signum: SigNum) -> Result<()> {
} }
let signal = Box::new(UserSignal::new(signum, UserSignalKind::Kill, pid, uid)); let signal = Box::new(UserSignal::new(signum, UserSignalKind::Kill, pid, uid));
let mut sig_queues = process.sig_queues().lock().unwrap(); let mut sig_queues = process.sig_queues().write().unwrap();
sig_queues.enqueue(signal); sig_queues.enqueue(signal);
} }
Ok(()) Ok(())
@ -42,7 +42,7 @@ pub fn do_kill_from_outside_enclave(filter: ProcessFilter, signum: SigNum) -> Re
continue; continue;
} }
let mut sig_queues = process.sig_queues().lock().unwrap(); let mut sig_queues = process.sig_queues().write().unwrap();
sig_queues.enqueue(signal.clone()); sig_queues.enqueue(signal.clone());
} }
Ok(()) Ok(())
@ -97,7 +97,7 @@ pub fn do_tgkill(pid: Option<pid_t>, tid: pid_t, signum: SigNum) -> Result<()> {
src_uid, src_uid,
)) ))
}; };
let mut sig_queues = thread.sig_queues().lock().unwrap(); let mut sig_queues = thread.sig_queues().write().unwrap();
sig_queues.enqueue(signal); sig_queues.enqueue(signal);
Ok(()) Ok(())
} }

@ -6,8 +6,8 @@ pub fn do_sigpending() -> Result<SigSet> {
let thread = current!(); let thread = current!();
let process = thread.process(); let process = thread.process();
let pending = (thread.sig_queues().lock().unwrap().pending() let pending = (thread.sig_queues().read().unwrap().pending()
| process.sig_queues().lock().unwrap().pending()) | process.sig_queues().read().unwrap().pending())
& *thread.sig_mask().read().unwrap(); & *thread.sig_mask().read().unwrap();
Ok(pending) Ok(pending)
} }

@ -66,12 +66,23 @@ pub fn deliver_signal(cpu_context: &mut CpuContext) {
fn do_deliver_signal(thread: &ThreadRef, process: &ProcessRef, cpu_context: &mut CpuContext) { fn do_deliver_signal(thread: &ThreadRef, process: &ProcessRef, cpu_context: &mut CpuContext) {
loop { loop {
// Dequeue a signal, respecting the signal mask and tmp mask if process.sig_queues().read().unwrap().empty()
let sig_mask = *thread.sig_mask().read().unwrap() | *thread.sig_tmp_mask().read().unwrap(); && thread.sig_queues().read().unwrap().empty()
{
return;
}
let signal = { let signal = {
#[rustfmt::skip] // Dequeue a signal, respecting the signal mask and tmp mask
let signal_opt = process.sig_queues().lock().unwrap().dequeue(&sig_mask) let sig_mask =
.or_else(|| thread.sig_queues().lock().unwrap().dequeue(&sig_mask)); *thread.sig_mask().read().unwrap() | *thread.sig_tmp_mask().read().unwrap();
let signal_opt = process
.sig_queues()
.write()
.unwrap()
.dequeue(&sig_mask)
.or_else(|| thread.sig_queues().write().unwrap().dequeue(&sig_mask));
if signal_opt.is_none() { if signal_opt.is_none() {
return; return;
} }

@ -7,7 +7,6 @@ use crate::prelude::*;
pub struct SigQueues { pub struct SigQueues {
count: usize, count: usize,
has_kill: bool,
std_queues: Vec<Option<Box<dyn Signal>>>, std_queues: Vec<Option<Box<dyn Signal>>>,
rt_queues: Vec<VecDeque<Box<dyn Signal>>>, rt_queues: Vec<VecDeque<Box<dyn Signal>>>,
} }
@ -15,12 +14,10 @@ pub struct SigQueues {
impl SigQueues { impl SigQueues {
pub fn new() -> Self { pub fn new() -> Self {
let count = 0; let count = 0;
let has_kill = false;
let std_queues = (0..COUNT_STD_SIGS).map(|_| None).collect(); let std_queues = (0..COUNT_STD_SIGS).map(|_| None).collect();
let rt_queues = (0..COUNT_RT_SIGS).map(|_| Default::default()).collect(); let rt_queues = (0..COUNT_RT_SIGS).map(|_| Default::default()).collect();
SigQueues { SigQueues {
count, count,
has_kill,
std_queues, std_queues,
rt_queues, rt_queues,
} }