void signal_send(struct thread *t, int num, struct siginfo *info, boolean_t force) { if (info) { info->si_signo = num; } /* If we need to force and the signal is ignored or masked, override this * and set to default action or unblock. POSIX allows us to do this. */ if (force) { t->signal_mask &= ~(1 << num); t->owner->signal_mask &= ~(1 << num); if (t->owner->signal_act[num].sa_handler == SIG_IGN) { t->owner->signal_act[num].sa_handler = SIG_DFT; } } /* Store information on the signal and mark it as pending */ t->pending_signals |= (1 << num); if (info) { memcpy(&t->signal_info[num], info, sizeof(struct siginfo)); } else { memset(&t->signal_info[num], 0, sizeof(struct siginfo)); t->signal_info[num].si_signo = num; } /* Interrupt the thread if it is currently in interruptible sleep */ thread_interrupt(t); }
void *su_allocate(su_state *s, void *p, size_t n) { void *np; if (n) { thread_interrupt(s, IGC); np = s->alloc(p, n); su_assert(s, np != NULL, "Out of memory!"); return np; } else { return s->alloc(p, 0); } }
void su_debug(su_state *s, int mask, su_debugfunc f, void *data) { s->debug_mask = mask; s->debug_cb = f; s->debug_cb_data = data; thread_interrupt(s, IBREAK); }
/*! Delivers the \a signal to the \a thread, but doesn't handle the signal - it just makes sure the thread gets the signal, ie. unblocks it if needed. This function must be called with interrupts disabled and the thread lock held. */ static status_t deliver_signal(struct thread *thread, uint signal, uint32 flags) { if (flags & B_CHECK_PERMISSION) { // ToDo: introduce euid & uid fields to the team and check permission } if (signal == 0) return B_OK; if (thread->team == team_get_kernel_team()) { // Signals to kernel threads will only wake them up if (thread->state == B_THREAD_SUSPENDED) scheduler_enqueue_in_run_queue(thread); return B_OK; } atomic_or(&thread->sig_pending, SIGNAL_TO_MASK(signal)); switch (signal) { case SIGKILL: { // Forward KILLTHR to the main thread of the team struct thread *mainThread = thread->team->main_thread; atomic_or(&mainThread->sig_pending, SIGNAL_TO_MASK(SIGKILLTHR)); // Wake up main thread if (mainThread->state == B_THREAD_SUSPENDED) scheduler_enqueue_in_run_queue(mainThread); else thread_interrupt(mainThread, true); update_thread_signals_flag(mainThread); // Supposed to fall through } case SIGKILLTHR: // Wake up suspended threads and interrupt waiting ones if (thread->state == B_THREAD_SUSPENDED) scheduler_enqueue_in_run_queue(thread); else thread_interrupt(thread, true); break; case SIGCONT: // Wake up thread if it was suspended if (thread->state == B_THREAD_SUSPENDED) scheduler_enqueue_in_run_queue(thread); if ((flags & SIGNAL_FLAG_DONT_RESTART_SYSCALL) != 0) atomic_or(&thread->flags, THREAD_FLAGS_DONT_RESTART_SYSCALL); atomic_and(&thread->sig_pending, ~STOP_SIGNALS); // remove any pending stop signals break; default: if (thread->sig_pending & (~thread->sig_block_mask | SIGNAL_TO_MASK(SIGCHLD))) { // Interrupt thread if it was waiting thread_interrupt(thread, false); } break; } update_thread_signals_flag(thread); return B_OK; }