/** * Give the control of the CPU to another process. * * \note Assume the current process has been already added to a wait queue. * * \warning This should be considered an internal kernel function, even if it * is allowed, usage from application code is strongly discouraged. */ void proc_switch(void) { ASSERT(proc_preemptAllowed()); ATOMIC( preempt_reset_quantum(); proc_schedule(); );
/** * Send the signals \a sigs to the process \a proc and immeditaly dispatch it * for execution. * * The process will be awoken if it was waiting for any of them and immediately * dispatched for execution. * * \note This function can't be called from IRQ context, use sig_post() * instead. */ void sig_send(Process *proc, sigmask_t sigs) { ASSERT_USER_CONTEXT(); IRQ_ASSERT_ENABLED(); ASSERT(proc_preemptAllowed()); __sig_signal(proc, sigs, true); }
/** * Check if we need to schedule another task */ bool proc_needPreempt(void) { if (UNLIKELY(current_process == NULL)) return false; if (!proc_preemptAllowed()) return false; if (LIST_EMPTY(&proc_ready_list)) return false; return preempt_quantum() ? prio_next() > prio_curr() : prio_next() >= prio_curr(); }
/** * Enqueue a process in the zombie list. */ static void proc_addZombie(Process *proc) { Node *node; #if CONFIG_KERN_PREEMPT ASSERT(!proc_preemptAllowed()); #endif #if CONFIG_KERN_PRI node = &(proc)->link.link; #else node = &(proc)->link; #endif LIST_ASSERT_VALID(&zombie_list); ADDTAIL(&zombie_list, node); }
/** * Sleep until any of the signals in \a sigs occurs. * \return the signal(s) that have awoken the process. */ sigmask_t sig_wait(sigmask_t sigs) { sigmask_t result; /* Sleeping with IRQs disabled or preemption forbidden is illegal */ IRQ_ASSERT_ENABLED(); ASSERT(proc_preemptAllowed()); /* * This is subtle: there's a race condition where a concurrent process * or an interrupt may call sig_send()/sig_post() to set a bit in * Process.sig_recv just after we have checked for it, but before we've * set Process.sig_wait to let them know we want to be awaken. * * In this case, we'd deadlock with the signal bit already set and the * process never being reinserted into the ready list. */ IRQ_DISABLE; /* Loop until we get at least one of the signals */ while (!(result = current_process->sig_recv & sigs)) { /* * Tell "them" that we want to be awaken when any of these * signals arrives. */ current_process->sig_wait = sigs; /* Go to sleep and proc_switch() to another process. */ proc_switch(); /* * When we come back here, the wait mask must have been * cleared by someone through sig_send()/sig_post(), and at * least one of the signals we were expecting must have been * delivered to us. */ ASSERT(!current_process->sig_wait); ASSERT(current_process->sig_recv & sigs); } /* Signals found: clear them and return */ current_process->sig_recv &= ~sigs; IRQ_ENABLE; return result; }