Esempio n. 1
0
/**
 * 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();
	);
Esempio n. 2
0
/**
 * 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);
}
Esempio n. 3
0
/**
 * 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();
}
Esempio n. 4
0
/**
 * 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);
}
Esempio n. 5
0
/**
 * 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;
}