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(); } } }
/*! 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; }