Пример #1
0
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);
}
Пример #2
0
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);
	}
}
Пример #3
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);
}
Пример #4
0
/*!	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;
}