# UNDF: UNDF-2026-000000335 --- a/lib/wasix/src/os/task/thread.rs +++ b/lib/wasix/src/os/task/thread.rs @@ -238,7 +238,9 @@ pub struct WasiThreadInner { pub(crate) status: Arc, /// Signals are used to indicate certain states to the thread - signals: Mutex<(Vec, Vec)>, + /// Using a u64 bitmask instead of Vec — Signal values are 1..=31, + /// so bit N represents signal N. O(1) insert, O(1) contains, O(1) test. + signals: Mutex<(u64, Vec)>, } @@ -268,7 +270,7 @@ impl WasiThreadInner { status: Arc::new(OwnedTaskStatus::new(TaskStatus::Pending)), - signals: Mutex::new((Vec::new(), Vec::new())), + signals: Mutex::new((0u64, Vec::new())), } } @@ -345,10 +347,8 @@ impl WasiThread { let mut guard = self.state.signals.lock().unwrap(); - if !guard.0.contains(&signal) { - guard.0.push(signal); - } + // Set bit for this signal — O(1) insert with automatic dedup + guard.0 |= 1u64 << (signal as u32); guard.1.drain(..).for_each(|w| w.wake()); } @@ -358,10 +358,10 @@ impl WasiThread { pub fn has_signal(&self, signals: &[Signal]) -> bool { let guard = self.state.signals.lock().unwrap(); - for s in guard.0.iter() { - if signals.contains(s) { - return true; - } - } - false + // Build query bitmask in O(|signals|), then AND in O(1) + let query_mask: u64 = signals.iter().fold(0u64, |m, s| m | (1u64 << (*s as u32))); + guard.0 & query_mask != 0 } @@ -390,7 +390,7 @@ impl WasiThread { pub fn pop_signals_or_subscribe(&self, waker: &Waker) -> Option> { let mut guard = self.state.signals.lock().unwrap(); - if guard.0.is_empty() { + if guard.0 == 0 { // ... } // Convert bitmask back to Vec for consumption - Some(std::mem::take(&mut guard.0)) + let mask = std::mem::replace(&mut guard.0, 0u64); + Some((0u32..64).filter(|b| mask & (1u64 << b) != 0) + .filter_map(|b| Signal::try_from(b as i32).ok()) + .collect()) }