static void
notify_loading_app(status_t result, bool suspend)
{
	Team* team = thread_get_current_thread()->team;

	TeamLocker teamLocker(team);

	if (team->loading_info) {
		// there's indeed someone waiting
		struct team_loading_info* loadingInfo = team->loading_info;
		team->loading_info = NULL;

		loadingInfo->result = result;
		loadingInfo->done = true;

		// we're done with the team stuff, get the scheduler lock instead
		teamLocker.Unlock();
		InterruptsSpinLocker schedulerLocker(gSchedulerLock);

		// wake up the waiting thread
		if (loadingInfo->thread->state == B_THREAD_SUSPENDED)
			scheduler_enqueue_in_run_queue(loadingInfo->thread);

		// suspend ourselves, if desired
		if (suspend) {
			thread_get_current_thread()->next_state = B_THREAD_SUSPENDED;
			scheduler_reschedule();
		}
	}
}
Exemple #2
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;
}