diff --git a/headers/private/kernel/ksignal.h b/headers/private/kernel/ksignal.h index 38c34d6e50..b5e729d304 100644 --- a/headers/private/kernel/ksignal.h +++ b/headers/private/kernel/ksignal.h @@ -14,6 +14,10 @@ #define SIGNAL_TO_MASK(signal) (1LL << (signal - 1)) +// additional send_signal_etc() flag +#define SIGNAL_FLAG_TEAMS_LOCKED (0x10000) + // interrupts are disabled and team lock is held + #ifdef __cplusplus extern "C" { @@ -22,6 +26,7 @@ extern "C" { extern bool handle_signals(struct thread *thread); extern bool is_kill_signal_pending(void); extern int has_signals_pending(void *_thread); +extern bool is_signal_blocked(int signal); extern int sigaction_etc(thread_id threadID, int signal, const struct sigaction *newAction, struct sigaction *oldAction); diff --git a/src/system/kernel/signal.cpp b/src/system/kernel/signal.cpp index f0d7c395be..21b64dbed8 100644 --- a/src/system/kernel/signal.cpp +++ b/src/system/kernel/signal.cpp @@ -265,6 +265,14 @@ is_kill_signal_pending(void) } +bool +is_signal_blocked(int signal) +{ + return (atomic_get(&thread_get_current_thread()->sig_block_mask) + & SIGNAL_TO_MASK(signal)) != 0; +} + + /*! Tries to interrupt a thread waiting for a semaphore or a condition variable. Interrupts must be disabled, the thread lock be held. Note, that the thread lock may temporarily be released. @@ -360,12 +368,13 @@ send_signal_etc(pid_t id, uint signal, uint32 flags) { status_t status = B_BAD_THREAD_ID; struct thread *thread; - cpu_status state; + cpu_status state = 0; if (signal < 0 || signal > MAX_SIGNO) return B_BAD_VALUE; - state = disable_interrupts(); + if ((flags & SIGNAL_FLAG_TEAMS_LOCKED) == 0) + state = disable_interrupts(); if (id > 0) { // send a signal to the specified thread @@ -388,7 +397,8 @@ send_signal_etc(pid_t id, uint signal, uint32 flags) } else id = -id; - GRAB_TEAM_LOCK(); + if ((flags & SIGNAL_FLAG_TEAMS_LOCKED) == 0) + GRAB_TEAM_LOCK(); group = team_get_process_group_locked(NULL, id); if (group != NULL) { @@ -413,17 +423,21 @@ send_signal_etc(pid_t id, uint signal, uint32 flags) } } - RELEASE_TEAM_LOCK(); + if ((flags & SIGNAL_FLAG_TEAMS_LOCKED) == 0) + RELEASE_TEAM_LOCK(); + GRAB_THREAD_LOCK(); } // ToDo: maybe the scheduler should only be invoked if there is reason to do it? // (ie. deliver_signal() moved some threads in the running queue?) - if ((flags & B_DO_NOT_RESCHEDULE) == 0) + if ((flags & (B_DO_NOT_RESCHEDULE | SIGNAL_FLAG_TEAMS_LOCKED)) == 0) scheduler_reschedule(); RELEASE_THREAD_LOCK(); - restore_interrupts(state); + + if ((flags & SIGNAL_FLAG_TEAMS_LOCKED) == 0) + restore_interrupts(state); return status; }