mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-24 09:53:24 +00:00
Implement atomic signal masks and refactor SigSet
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
6f8978193c
commit
16690bc61b
@ -175,8 +175,10 @@ fn clone_child_thread(parent_context: &UserContext, clone_args: CloneArgs) -> Re
|
|||||||
let sig_mask = {
|
let sig_mask = {
|
||||||
let current_thread = current_thread!();
|
let current_thread = current_thread!();
|
||||||
let current_posix_thread = current_thread.as_posix_thread().unwrap();
|
let current_posix_thread = current_thread.as_posix_thread().unwrap();
|
||||||
let sigmask = current_posix_thread.sig_mask().lock();
|
current_posix_thread
|
||||||
*sigmask
|
.sig_mask()
|
||||||
|
.load(Ordering::Relaxed)
|
||||||
|
.into()
|
||||||
};
|
};
|
||||||
|
|
||||||
let child_tid = allocate_tid();
|
let child_tid = allocate_tid();
|
||||||
@ -258,8 +260,7 @@ fn clone_child_process(
|
|||||||
let child_sig_mask = {
|
let child_sig_mask = {
|
||||||
let current_thread = current_thread!();
|
let current_thread = current_thread!();
|
||||||
let posix_thread = current_thread.as_posix_thread().unwrap();
|
let posix_thread = current_thread.as_posix_thread().unwrap();
|
||||||
let sigmask = posix_thread.sig_mask().lock();
|
posix_thread.sig_mask().load(Ordering::Relaxed).into()
|
||||||
*sigmask
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// inherit parent's nice value
|
// inherit parent's nice value
|
||||||
|
@ -9,7 +9,7 @@ use crate::{
|
|||||||
prelude::*,
|
prelude::*,
|
||||||
process::{
|
process::{
|
||||||
posix_thread::name::ThreadName,
|
posix_thread::name::ThreadName,
|
||||||
signal::{sig_mask::SigMask, sig_queues::SigQueues},
|
signal::{sig_mask::AtomicSigMask, sig_queues::SigQueues},
|
||||||
Credentials, Process,
|
Credentials, Process,
|
||||||
},
|
},
|
||||||
thread::{status::ThreadStatus, task, thread_table, Thread, Tid},
|
thread::{status::ThreadStatus, task, thread_table, Thread, Tid},
|
||||||
@ -28,7 +28,7 @@ pub struct PosixThreadBuilder {
|
|||||||
thread_name: Option<ThreadName>,
|
thread_name: Option<ThreadName>,
|
||||||
set_child_tid: Vaddr,
|
set_child_tid: Vaddr,
|
||||||
clear_child_tid: Vaddr,
|
clear_child_tid: Vaddr,
|
||||||
sig_mask: SigMask,
|
sig_mask: AtomicSigMask,
|
||||||
sig_queues: SigQueues,
|
sig_queues: SigQueues,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ impl PosixThreadBuilder {
|
|||||||
thread_name: None,
|
thread_name: None,
|
||||||
set_child_tid: 0,
|
set_child_tid: 0,
|
||||||
clear_child_tid: 0,
|
clear_child_tid: 0,
|
||||||
sig_mask: SigMask::new_empty(),
|
sig_mask: AtomicSigMask::new_empty(),
|
||||||
sig_queues: SigQueues::new(),
|
sig_queues: SigQueues::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -67,7 +67,7 @@ impl PosixThreadBuilder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sig_mask(mut self, sig_mask: SigMask) -> Self {
|
pub fn sig_mask(mut self, sig_mask: AtomicSigMask) -> Self {
|
||||||
self.sig_mask = sig_mask;
|
self.sig_mask = sig_mask;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -99,7 +99,7 @@ impl PosixThreadBuilder {
|
|||||||
set_child_tid: Mutex::new(set_child_tid),
|
set_child_tid: Mutex::new(set_child_tid),
|
||||||
clear_child_tid: Mutex::new(clear_child_tid),
|
clear_child_tid: Mutex::new(clear_child_tid),
|
||||||
credentials,
|
credentials,
|
||||||
sig_mask: Mutex::new(sig_mask),
|
sig_mask,
|
||||||
sig_queues,
|
sig_queues,
|
||||||
sig_context: Mutex::new(None),
|
sig_context: Mutex::new(None),
|
||||||
sig_stack: Mutex::new(None),
|
sig_stack: Mutex::new(None),
|
||||||
|
@ -2,12 +2,14 @@
|
|||||||
|
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
use core::sync::atomic::Ordering;
|
||||||
|
|
||||||
use aster_rights::{ReadOp, WriteOp};
|
use aster_rights::{ReadOp, WriteOp};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
kill::SignalSenderIds,
|
kill::SignalSenderIds,
|
||||||
signal::{
|
signal::{
|
||||||
sig_mask::{SigMask, SigSet},
|
sig_mask::{AtomicSigMask, SigMask, SigSet},
|
||||||
sig_num::SigNum,
|
sig_num::SigNum,
|
||||||
sig_queues::SigQueues,
|
sig_queues::SigQueues,
|
||||||
signals::Signal,
|
signals::Signal,
|
||||||
@ -55,7 +57,7 @@ pub struct PosixThread {
|
|||||||
|
|
||||||
// Signal
|
// Signal
|
||||||
/// Blocked signals
|
/// Blocked signals
|
||||||
sig_mask: Mutex<SigMask>,
|
sig_mask: AtomicSigMask,
|
||||||
/// Thread-directed sigqueue
|
/// Thread-directed sigqueue
|
||||||
sig_queues: SigQueues,
|
sig_queues: SigQueues,
|
||||||
/// Signal handler ucontext address
|
/// Signal handler ucontext address
|
||||||
@ -90,7 +92,12 @@ impl PosixThread {
|
|||||||
&self.clear_child_tid
|
&self.clear_child_tid
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sig_mask(&self) -> &Mutex<SigMask> {
|
/// Get the reference to the signal mask of the thread.
|
||||||
|
///
|
||||||
|
/// Note that while this function offers mutable access to the signal mask,
|
||||||
|
/// it is not sound for callers other than the current thread to modify the
|
||||||
|
/// signal mask. They may only read the signal mask.
|
||||||
|
pub fn sig_mask(&self) -> &AtomicSigMask {
|
||||||
&self.sig_mask
|
&self.sig_mask
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,14 +108,13 @@ impl PosixThread {
|
|||||||
/// Returns whether the thread has some pending signals
|
/// Returns whether the thread has some pending signals
|
||||||
/// that are not blocked.
|
/// that are not blocked.
|
||||||
pub fn has_pending(&self) -> bool {
|
pub fn has_pending(&self) -> bool {
|
||||||
let blocked = *self.sig_mask().lock();
|
let blocked = self.sig_mask().load(Ordering::Relaxed);
|
||||||
self.sig_queues.has_pending(blocked)
|
self.sig_queues.has_pending(blocked)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether the signal is blocked by the thread.
|
/// Returns whether the signal is blocked by the thread.
|
||||||
pub(in crate::process) fn has_signal_blocked(&self, signal: &dyn Signal) -> bool {
|
pub(in crate::process) fn has_signal_blocked(&self, signal: &dyn Signal) -> bool {
|
||||||
let mask = self.sig_mask.lock();
|
self.sig_mask.contains(signal.num(), Ordering::Relaxed)
|
||||||
mask.contains(signal.num())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks whether the signal can be delivered to the thread.
|
/// Checks whether the signal can be delivered to the thread.
|
||||||
|
@ -9,7 +9,6 @@ use super::{
|
|||||||
signal::{
|
signal::{
|
||||||
constants::SIGCHLD,
|
constants::SIGCHLD,
|
||||||
sig_disposition::SigDispositions,
|
sig_disposition::SigDispositions,
|
||||||
sig_mask::SigMask,
|
|
||||||
sig_num::{AtomicSigNum, SigNum},
|
sig_num::{AtomicSigNum, SigNum},
|
||||||
signals::Signal,
|
signals::Signal,
|
||||||
Pauser,
|
Pauser,
|
||||||
@ -120,12 +119,9 @@ impl Process {
|
|||||||
nice: Nice,
|
nice: Nice,
|
||||||
sig_dispositions: Arc<Mutex<SigDispositions>>,
|
sig_dispositions: Arc<Mutex<SigDispositions>>,
|
||||||
) -> Arc<Self> {
|
) -> Arc<Self> {
|
||||||
let children_pauser = {
|
|
||||||
// SIGCHID does not interrupt pauser. Child process will
|
// SIGCHID does not interrupt pauser. Child process will
|
||||||
// resume paused parent when doing exit.
|
// resume paused parent when doing exit.
|
||||||
let sigmask = SigMask::from(SIGCHLD);
|
let children_pauser = Pauser::new_with_mask(SIGCHLD.into());
|
||||||
Pauser::new_with_mask(sigmask)
|
|
||||||
};
|
|
||||||
|
|
||||||
let prof_clock = ProfClock::new();
|
let prof_clock = ProfClock::new();
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ pub fn handle_pending_signal(
|
|||||||
// We first deal with signal in current thread, then signal in current process.
|
// We first deal with signal in current thread, then signal in current process.
|
||||||
let posix_thread = current_thread.as_posix_thread().unwrap();
|
let posix_thread = current_thread.as_posix_thread().unwrap();
|
||||||
let signal = {
|
let signal = {
|
||||||
let sig_mask = *posix_thread.sig_mask().lock();
|
let sig_mask = posix_thread.sig_mask().load(Ordering::Relaxed);
|
||||||
if let Some(signal) = posix_thread.dequeue_signal(&sig_mask) {
|
if let Some(signal) = posix_thread.dequeue_signal(&sig_mask) {
|
||||||
signal
|
signal
|
||||||
} else {
|
} else {
|
||||||
@ -136,13 +136,15 @@ pub fn handle_user_signal(
|
|||||||
}
|
}
|
||||||
if !flags.contains(SigActionFlags::SA_NODEFER) {
|
if !flags.contains(SigActionFlags::SA_NODEFER) {
|
||||||
// add current signal to mask
|
// add current signal to mask
|
||||||
let current_mask = SigMask::from(sig_num);
|
mask += sig_num;
|
||||||
mask.block(current_mask.as_u64());
|
|
||||||
}
|
}
|
||||||
let current_thread = current_thread!();
|
let current_thread = current_thread!();
|
||||||
let posix_thread = current_thread.as_posix_thread().unwrap();
|
let posix_thread = current_thread.as_posix_thread().unwrap();
|
||||||
// block signals in sigmask when running signal handler
|
// block signals in sigmask when running signal handler
|
||||||
posix_thread.sig_mask().lock().block(mask.as_u64());
|
let old_mask = posix_thread.sig_mask().load(Ordering::Relaxed);
|
||||||
|
posix_thread
|
||||||
|
.sig_mask()
|
||||||
|
.store(old_mask + mask, Ordering::Relaxed);
|
||||||
|
|
||||||
// Set up signal stack.
|
// Set up signal stack.
|
||||||
let mut stack_pointer = if let Some(sp) = use_alternate_signal_stack(posix_thread) {
|
let mut stack_pointer = if let Some(sp) = use_alternate_signal_stack(posix_thread) {
|
||||||
@ -163,7 +165,7 @@ pub fn handle_user_signal(
|
|||||||
// 2. write ucontext_t.
|
// 2. write ucontext_t.
|
||||||
stack_pointer = alloc_aligned_in_user_stack(stack_pointer, mem::size_of::<ucontext_t>(), 16)?;
|
stack_pointer = alloc_aligned_in_user_stack(stack_pointer, mem::size_of::<ucontext_t>(), 16)?;
|
||||||
let mut ucontext = ucontext_t {
|
let mut ucontext = ucontext_t {
|
||||||
uc_sigmask: mask.as_u64(),
|
uc_sigmask: mask.into(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
ucontext
|
ucontext
|
||||||
|
@ -185,13 +185,9 @@ impl<'a> SigObserverRegistrar<'a> {
|
|||||||
|
|
||||||
// Block `sig_mask`.
|
// Block `sig_mask`.
|
||||||
let (old_mask, filter) = {
|
let (old_mask, filter) = {
|
||||||
let mut locked_mask = thread.sig_mask().lock();
|
let old_mask = thread.sig_mask().load(Ordering::Relaxed);
|
||||||
|
let new_mask = old_mask + sig_mask;
|
||||||
let old_mask = *locked_mask;
|
thread.sig_mask().store(new_mask, Ordering::Relaxed);
|
||||||
let new_mask = {
|
|
||||||
locked_mask.block(sig_mask.as_u64());
|
|
||||||
*locked_mask
|
|
||||||
};
|
|
||||||
|
|
||||||
(old_mask, SigEventsFilter::new(new_mask))
|
(old_mask, SigEventsFilter::new(new_mask))
|
||||||
};
|
};
|
||||||
@ -234,7 +230,7 @@ impl<'a> Drop for SigObserverRegistrar<'a> {
|
|||||||
// Restore the state, assuming no one else can modify the current thread's signal mask
|
// Restore the state, assuming no one else can modify the current thread's signal mask
|
||||||
// during the pause.
|
// during the pause.
|
||||||
thread.unregiser_sigqueue_observer(&(Arc::downgrade(observer) as _));
|
thread.unregiser_sigqueue_observer(&(Arc::downgrade(observer) as _));
|
||||||
thread.sig_mask().lock().set(old_mask.as_u64());
|
thread.sig_mask().store(*old_mask, Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ impl TryFrom<sigaction_t> for SigAction {
|
|||||||
SIG_IGN => SigAction::Ign,
|
SIG_IGN => SigAction::Ign,
|
||||||
_ => {
|
_ => {
|
||||||
let flags = SigActionFlags::from_bits_truncate(input.flags);
|
let flags = SigActionFlags::from_bits_truncate(input.flags);
|
||||||
let mask = SigMask::from(input.mask);
|
let mask = input.mask.into();
|
||||||
SigAction::User {
|
SigAction::User {
|
||||||
handler_addr: input.handler_ptr,
|
handler_addr: input.handler_ptr,
|
||||||
flags,
|
flags,
|
||||||
@ -65,7 +65,7 @@ impl SigAction {
|
|||||||
handler_ptr: *handler_addr,
|
handler_ptr: *handler_addr,
|
||||||
flags: flags.as_u32(),
|
flags: flags.as_u32(),
|
||||||
restorer_ptr: *restorer_addr,
|
restorer_ptr: *restorer_addr,
|
||||||
mask: mask.as_u64(),
|
mask: (*mask).into(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,84 +1,220 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
//! Signal sets and atomic masks.
|
||||||
|
//!
|
||||||
|
//! A signal set is a bit-set of signals. A signal mask is a set of signals
|
||||||
|
//! that are blocked from delivery to a thread. An atomic signal mask
|
||||||
|
//! implementation is provided for shared access to signal masks.
|
||||||
|
|
||||||
|
use core::{
|
||||||
|
fmt::LowerHex,
|
||||||
|
ops,
|
||||||
|
sync::atomic::{AtomicU64, Ordering},
|
||||||
|
};
|
||||||
|
|
||||||
use super::{constants::MIN_STD_SIG_NUM, sig_num::SigNum};
|
use super::{constants::MIN_STD_SIG_NUM, sig_num::SigNum};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
/// A signal mask.
|
/// A signal mask.
|
||||||
|
///
|
||||||
|
/// This is an alias to the [`SigSet`]. All the signal in the set are blocked
|
||||||
|
/// from the delivery to a thread.
|
||||||
pub type SigMask = SigSet;
|
pub type SigMask = SigSet;
|
||||||
|
|
||||||
|
/// A bit-set of signals.
|
||||||
|
///
|
||||||
|
/// Because that all the signal numbers are in the range of 1 to 64, casting
|
||||||
|
/// a signal set from `u64` to `SigSet` will always succeed.
|
||||||
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, Pod)]
|
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, Pod)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct SigSet {
|
pub struct SigSet {
|
||||||
bits: u64,
|
bits: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<u64> for SigMask {
|
impl From<SigNum> for SigSet {
|
||||||
|
fn from(signum: SigNum) -> Self {
|
||||||
|
let idx = signum.as_u8() - MIN_STD_SIG_NUM;
|
||||||
|
Self { bits: 1_u64 << idx }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u64> for SigSet {
|
||||||
fn from(bits: u64) -> Self {
|
fn from(bits: u64) -> Self {
|
||||||
SigMask { bits }
|
SigSet { bits }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<SigNum> for SigMask {
|
impl From<SigSet> for u64 {
|
||||||
fn from(sig_num: SigNum) -> Self {
|
fn from(set: SigSet) -> u64 {
|
||||||
let idx = SigMask::num_to_idx(sig_num);
|
set.bits
|
||||||
let bits = 1u64 << idx;
|
|
||||||
SigMask { bits }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SigMask {
|
impl<T: Into<SigSet>> ops::BitAnd<T> for SigSet {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn bitand(self, rhs: T) -> Self {
|
||||||
|
SigSet {
|
||||||
|
bits: self.bits & rhs.into().bits,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Into<SigSet>> ops::BitAndAssign<T> for SigSet {
|
||||||
|
fn bitand_assign(&mut self, rhs: T) {
|
||||||
|
self.bits &= rhs.into().bits;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Into<SigSet>> ops::BitOr<T> for SigSet {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn bitor(self, rhs: T) -> Self {
|
||||||
|
SigSet {
|
||||||
|
bits: self.bits | rhs.into().bits,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Into<SigSet>> ops::BitOrAssign<T> for SigSet {
|
||||||
|
fn bitor_assign(&mut self, rhs: T) {
|
||||||
|
self.bits |= rhs.into().bits;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::suspicious_arithmetic_impl)]
|
||||||
|
impl<T: Into<SigSet>> ops::Add<T> for SigSet {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn add(self, rhs: T) -> Self {
|
||||||
|
SigSet {
|
||||||
|
bits: self.bits | rhs.into().bits,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::suspicious_op_assign_impl)]
|
||||||
|
impl<T: Into<SigSet>> ops::AddAssign<T> for SigSet {
|
||||||
|
fn add_assign(&mut self, rhs: T) {
|
||||||
|
self.bits |= rhs.into().bits;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Into<SigSet>> ops::Sub<T> for SigSet {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn sub(self, rhs: T) -> Self {
|
||||||
|
SigSet {
|
||||||
|
bits: self.bits & !rhs.into().bits,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Into<SigSet>> ops::SubAssign<T> for SigSet {
|
||||||
|
fn sub_assign(&mut self, rhs: T) {
|
||||||
|
self.bits &= !rhs.into().bits;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SigSet {
|
||||||
pub fn new_empty() -> Self {
|
pub fn new_empty() -> Self {
|
||||||
SigMask::from(0u64)
|
SigSet { bits: 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_full() -> Self {
|
pub fn new_full() -> Self {
|
||||||
SigMask::from(!0u64)
|
SigSet { bits: !0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn as_u64(&self) -> u64 {
|
pub const fn is_empty(&self) -> bool {
|
||||||
self.bits
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn empty(&self) -> bool {
|
|
||||||
self.bits == 0
|
self.bits == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn full(&self) -> bool {
|
pub const fn is_full(&self) -> bool {
|
||||||
self.bits == !0
|
self.bits == !0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn block(&mut self, block_sets: u64) {
|
|
||||||
self.bits |= block_sets;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn unblock(&mut self, unblock_sets: u64) {
|
|
||||||
self.bits &= !unblock_sets;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set(&mut self, new_set: u64) {
|
|
||||||
self.bits = new_set;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn count(&self) -> usize {
|
pub fn count(&self) -> usize {
|
||||||
self.bits.count_ones() as usize
|
self.bits.count_ones() as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn contains(&self, signum: SigNum) -> bool {
|
pub fn contains(&self, set: impl Into<Self>) -> bool {
|
||||||
let idx = Self::num_to_idx(signum);
|
let set = set.into();
|
||||||
(self.bits & (1_u64 << idx)) != 0
|
self.bits & set.bits == set.bits
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn num_to_idx(num: SigNum) -> usize {
|
// This is to allow hexadecimally formatting a `SigSet` when debug printing it.
|
||||||
(num.as_u8() - MIN_STD_SIG_NUM) as usize
|
impl LowerHex for SigSet {
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
|
LowerHex::fmt(&self.bits, f) // delegate to u64's implementation
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_signal(&mut self, signum: SigNum) {
|
/// An atomic signal mask.
|
||||||
let idx = Self::num_to_idx(signum);
|
///
|
||||||
self.bits &= !(1_u64 << idx);
|
/// This is an alias to the [`AtomicSigSet`]. All the signal in the set are
|
||||||
|
/// blocked from the delivery to a thread.
|
||||||
|
///
|
||||||
|
/// [`Relaxed`]: core::sync::atomic::Ordering::Relaxed
|
||||||
|
pub type AtomicSigMask = AtomicSigSet;
|
||||||
|
|
||||||
|
/// An atomic signal set.
|
||||||
|
pub struct AtomicSigSet(AtomicU64);
|
||||||
|
|
||||||
|
impl From<SigSet> for AtomicSigSet {
|
||||||
|
fn from(set: SigSet) -> Self {
|
||||||
|
AtomicSigSet(AtomicU64::new(set.bits))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_signal(&mut self, signum: SigNum) {
|
impl AtomicSigSet {
|
||||||
let idx = Self::num_to_idx(signum);
|
pub fn new_empty() -> Self {
|
||||||
self.bits |= 1_u64 << idx;
|
AtomicSigSet(AtomicU64::new(0))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_full() -> Self {
|
||||||
|
AtomicSigSet(AtomicU64::new(!0))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load(&self, ordering: Ordering) -> SigSet {
|
||||||
|
SigSet {
|
||||||
|
bits: self.0.load(ordering),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn store(&self, new_mask: impl Into<SigMask>, ordering: Ordering) {
|
||||||
|
self.0.store(new_mask.into().bits, ordering);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn contains(&self, signals: impl Into<SigSet>, ordering: Ordering) -> bool {
|
||||||
|
SigSet {
|
||||||
|
bits: self.0.load(ordering),
|
||||||
|
}
|
||||||
|
.contains(signals.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Applies an update to the signal set.
|
||||||
|
///
|
||||||
|
/// This is the same as [`AtomicU64::fetch_update`], but the closure `f`
|
||||||
|
/// operates on a [`SigMask`] instead of a `u64`.
|
||||||
|
///
|
||||||
|
/// It would be a bit slow since it would check if the value is written by
|
||||||
|
/// another thread while evaluating the closure `f`. If you are confident
|
||||||
|
/// that there's no such race, don't use this method.
|
||||||
|
pub fn fetch_update<F>(
|
||||||
|
&self,
|
||||||
|
set_order: Ordering,
|
||||||
|
fetch_order: Ordering,
|
||||||
|
mut f: F,
|
||||||
|
) -> core::result::Result<SigMask, SigMask>
|
||||||
|
where
|
||||||
|
F: FnMut(SigMask) -> Option<SigMask>,
|
||||||
|
{
|
||||||
|
self.0
|
||||||
|
.fetch_update(set_order, fetch_order, |bits| {
|
||||||
|
f(SigMask { bits }).map(|set| set.bits)
|
||||||
|
})
|
||||||
|
.map(SigMask::from)
|
||||||
|
.map_err(SigMask::from)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -222,14 +222,14 @@ impl Queues {
|
|||||||
// Process standard signal queues
|
// Process standard signal queues
|
||||||
for (idx, signal) in self.std_queues.iter().enumerate() {
|
for (idx, signal) in self.std_queues.iter().enumerate() {
|
||||||
if signal.is_some() {
|
if signal.is_some() {
|
||||||
pending.add_signal(SigNum::from_u8(idx as u8 + MIN_STD_SIG_NUM));
|
pending += SigNum::from_u8(idx as u8 + MIN_STD_SIG_NUM);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process real-time signal queues
|
// Process real-time signal queues
|
||||||
for (idx, signals) in self.rt_queues.iter().enumerate() {
|
for (idx, signals) in self.rt_queues.iter().enumerate() {
|
||||||
if !signals.is_empty() {
|
if !signals.is_empty() {
|
||||||
pending.add_signal(SigNum::from_u8(idx as u8 + MIN_RT_SIG_NUM));
|
pending += SigNum::from_u8(idx as u8 + MIN_RT_SIG_NUM);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
use core::time::Duration;
|
use core::{sync::atomic::Ordering, time::Duration};
|
||||||
|
|
||||||
use super::SyscallReturn;
|
use super::SyscallReturn;
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -11,7 +11,7 @@ use crate::{
|
|||||||
utils::CreationFlags,
|
utils::CreationFlags,
|
||||||
},
|
},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
process::posix_thread::PosixThreadExt,
|
process::{posix_thread::PosixThreadExt, signal::sig_mask::SigMask},
|
||||||
util::{read_val_from_user, write_val_to_user},
|
util::{read_val_from_user, write_val_to_user},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -148,32 +148,31 @@ pub fn sys_epoll_wait(
|
|||||||
Ok(SyscallReturn::Return(epoll_events.len() as _))
|
Ok(SyscallReturn::Return(epoll_events.len() as _))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_signal_mask(set_ptr: Vaddr) -> Result<u64> {
|
fn set_signal_mask(set_ptr: Vaddr) -> Result<SigMask> {
|
||||||
let new_set: Option<u64> = if set_ptr != 0 {
|
let new_mask: Option<SigMask> = if set_ptr != 0 {
|
||||||
Some(read_val_from_user::<u64>(set_ptr)?)
|
Some(read_val_from_user::<u64>(set_ptr)?.into())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let current_thread = current_thread!();
|
let current_thread = current_thread!();
|
||||||
let posix_thread = current_thread.as_posix_thread().unwrap();
|
let posix_thread = current_thread.as_posix_thread().unwrap();
|
||||||
let mut sig_mask = posix_thread.sig_mask().lock();
|
|
||||||
|
|
||||||
let old_sig_mask_value = sig_mask.as_u64();
|
let old_sig_mask_value = posix_thread.sig_mask().load(Ordering::Relaxed);
|
||||||
|
|
||||||
if let Some(new_set) = new_set {
|
if let Some(new_mask) = new_mask {
|
||||||
sig_mask.set(new_set);
|
posix_thread.sig_mask().store(new_mask, Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(old_sig_mask_value)
|
Ok(old_sig_mask_value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn restore_signal_mask(sig_mask_val: u64) {
|
fn restore_signal_mask(sig_mask_val: SigMask) {
|
||||||
let current_thread = current_thread!();
|
let current_thread = current_thread!();
|
||||||
let posix_thread = current_thread.as_posix_thread().unwrap();
|
let posix_thread = current_thread.as_posix_thread().unwrap();
|
||||||
let mut sig_mask = posix_thread.sig_mask().lock();
|
posix_thread
|
||||||
|
.sig_mask()
|
||||||
sig_mask.set(sig_mask_val);
|
.store(sig_mask_val, Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sys_epoll_pwait(
|
pub fn sys_epoll_pwait(
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
#![allow(unused_variables)]
|
use core::sync::atomic::Ordering;
|
||||||
|
|
||||||
use super::SyscallReturn;
|
use super::SyscallReturn;
|
||||||
use crate::{prelude::*, process::posix_thread::PosixThreadExt, util::write_val_to_user};
|
use crate::{prelude::*, process::posix_thread::PosixThreadExt, util::write_val_to_user};
|
||||||
@ -13,20 +13,20 @@ pub fn sys_rt_sigpending(u_set_ptr: Vaddr, sigset_size: usize) -> Result<Syscall
|
|||||||
if sigset_size != 8 {
|
if sigset_size != 8 {
|
||||||
return_errno_with_message!(Errno::EINVAL, "sigset size is not equal to 8")
|
return_errno_with_message!(Errno::EINVAL, "sigset size is not equal to 8")
|
||||||
}
|
}
|
||||||
do_rt_sigpending(u_set_ptr, sigset_size)?;
|
do_rt_sigpending(u_set_ptr)?;
|
||||||
Ok(SyscallReturn::Return(0))
|
Ok(SyscallReturn::Return(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_rt_sigpending(set_ptr: Vaddr, sigset_size: usize) -> Result<()> {
|
fn do_rt_sigpending(set_ptr: Vaddr) -> Result<()> {
|
||||||
let current_thread = current_thread!();
|
let current_thread = current_thread!();
|
||||||
let posix_thread = current_thread.as_posix_thread().unwrap();
|
let posix_thread = current_thread.as_posix_thread().unwrap();
|
||||||
|
|
||||||
let combined_signals = {
|
let combined_signals = {
|
||||||
let sig_mask_value = posix_thread.sig_mask().lock().as_u64();
|
let sig_mask_value = posix_thread.sig_mask().load(Ordering::Relaxed);
|
||||||
let sig_pending_value = posix_thread.sig_pending().as_u64();
|
let sig_pending_value = posix_thread.sig_pending();
|
||||||
sig_mask_value & sig_pending_value
|
sig_mask_value & sig_pending_value
|
||||||
};
|
};
|
||||||
|
|
||||||
write_val_to_user(set_ptr, &combined_signals)?;
|
write_val_to_user(set_ptr, &u64::from(combined_signals))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
#![allow(unused_variables)]
|
use core::sync::atomic::Ordering;
|
||||||
|
|
||||||
use ostd::mm::VmIo;
|
|
||||||
|
|
||||||
use super::SyscallReturn;
|
use super::SyscallReturn;
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -14,6 +12,7 @@ use crate::{
|
|||||||
sig_mask::SigMask,
|
sig_mask::SigMask,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
util::{read_val_from_user, write_val_to_user},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn sys_rt_sigprocmask(
|
pub fn sys_rt_sigprocmask(
|
||||||
@ -30,42 +29,38 @@ pub fn sys_rt_sigprocmask(
|
|||||||
if sigset_size != 8 {
|
if sigset_size != 8 {
|
||||||
error!("sigset size is not equal to 8");
|
error!("sigset size is not equal to 8");
|
||||||
}
|
}
|
||||||
do_rt_sigprocmask(mask_op, set_ptr, oldset_ptr, sigset_size).unwrap();
|
do_rt_sigprocmask(mask_op, set_ptr, oldset_ptr).unwrap();
|
||||||
Ok(SyscallReturn::Return(0))
|
Ok(SyscallReturn::Return(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_rt_sigprocmask(
|
fn do_rt_sigprocmask(mask_op: MaskOp, set_ptr: Vaddr, oldset_ptr: Vaddr) -> Result<()> {
|
||||||
mask_op: MaskOp,
|
|
||||||
set_ptr: Vaddr,
|
|
||||||
oldset_ptr: Vaddr,
|
|
||||||
sigset_size: usize,
|
|
||||||
) -> Result<()> {
|
|
||||||
let current = current!();
|
|
||||||
let current_thread = current_thread!();
|
let current_thread = current_thread!();
|
||||||
let posix_thread = current_thread.as_posix_thread().unwrap();
|
let posix_thread = current_thread.as_posix_thread().unwrap();
|
||||||
let root_vmar = current.root_vmar();
|
|
||||||
let mut sig_mask = posix_thread.sig_mask().lock();
|
let old_sig_mask_value = posix_thread.sig_mask().load(Ordering::Relaxed);
|
||||||
let old_sig_mask_value = sig_mask.as_u64();
|
|
||||||
debug!("old sig mask value: 0x{:x}", old_sig_mask_value);
|
debug!("old sig mask value: 0x{:x}", old_sig_mask_value);
|
||||||
if oldset_ptr != 0 {
|
if oldset_ptr != 0 {
|
||||||
root_vmar.write_val(oldset_ptr, &old_sig_mask_value)?;
|
write_val_to_user(oldset_ptr, &old_sig_mask_value)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let sig_mask_ref = posix_thread.sig_mask();
|
||||||
if set_ptr != 0 {
|
if set_ptr != 0 {
|
||||||
let new_set = root_vmar.read_val::<u64>(set_ptr)?;
|
let mut read_mask = read_val_from_user::<SigMask>(set_ptr)?;
|
||||||
match mask_op {
|
match mask_op {
|
||||||
MaskOp::Block => {
|
MaskOp::Block => {
|
||||||
let mut new_sig_mask = SigMask::from(new_set);
|
|
||||||
// According to man pages, "it is not possible to block SIGKILL or SIGSTOP.
|
// According to man pages, "it is not possible to block SIGKILL or SIGSTOP.
|
||||||
// Attempts to do so are silently ignored."
|
// Attempts to do so are silently ignored."
|
||||||
new_sig_mask.remove_signal(SIGKILL);
|
read_mask -= SIGKILL;
|
||||||
new_sig_mask.remove_signal(SIGSTOP);
|
read_mask -= SIGSTOP;
|
||||||
sig_mask.block(new_sig_mask.as_u64());
|
sig_mask_ref.store(old_sig_mask_value + read_mask, Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
MaskOp::Unblock => sig_mask.unblock(new_set),
|
MaskOp::Unblock => {
|
||||||
MaskOp::SetMask => sig_mask.set(new_set),
|
sig_mask_ref.store(old_sig_mask_value - read_mask, Ordering::Relaxed)
|
||||||
|
}
|
||||||
|
MaskOp::SetMask => sig_mask_ref.store(read_mask, Ordering::Relaxed),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
debug!("new set = {:x?}", &sig_mask);
|
debug!("new set = {:x?}", sig_mask_ref.load(Ordering::Relaxed));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
use core::sync::atomic::Ordering;
|
||||||
|
|
||||||
use ostd::{cpu::UserContext, user::UserContextApi};
|
use ostd::{cpu::UserContext, user::UserContextApi};
|
||||||
|
|
||||||
use super::SyscallReturn;
|
use super::SyscallReturn;
|
||||||
@ -45,7 +47,10 @@ pub fn sys_rt_sigreturn(context: &mut UserContext) -> Result<SyscallReturn> {
|
|||||||
.copy_to_raw(context.general_regs_mut());
|
.copy_to_raw(context.general_regs_mut());
|
||||||
// unblock sig mask
|
// unblock sig mask
|
||||||
let sig_mask = ucontext.uc_sigmask;
|
let sig_mask = ucontext.uc_sigmask;
|
||||||
posix_thread.sig_mask().lock().unblock(sig_mask);
|
let old_mask = posix_thread.sig_mask().load(Ordering::Relaxed);
|
||||||
|
posix_thread
|
||||||
|
.sig_mask()
|
||||||
|
.store(old_mask - sig_mask, Ordering::Relaxed);
|
||||||
|
|
||||||
Ok(SyscallReturn::NoReturn)
|
Ok(SyscallReturn::NoReturn)
|
||||||
}
|
}
|
||||||
|
@ -26,8 +26,8 @@ pub fn sys_rt_sigsuspend(sigmask_addr: Vaddr, sigmask_size: usize) -> Result<Sys
|
|||||||
let mut mask: SigMask = read_val_from_user(sigmask_addr)?;
|
let mut mask: SigMask = read_val_from_user(sigmask_addr)?;
|
||||||
// It is not possible to block SIGKILL or SIGSTOP,
|
// It is not possible to block SIGKILL or SIGSTOP,
|
||||||
// specifying these signals in mask has no effect.
|
// specifying these signals in mask has no effect.
|
||||||
mask.remove_signal(SIGKILL);
|
mask -= SIGKILL;
|
||||||
mask.remove_signal(SIGSTOP);
|
mask -= SIGSTOP;
|
||||||
mask
|
mask
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user