- * \note Thread priority (if enabled by CONFIG_KERN_PRI) defines the order in
- * the \p proc_ready_list and the capability to deschedule a running process. A
- * low-priority thread can't preempt a high-priority thread.
- *
- * A high-priority process can preempt a low-priority process immediately (it
- * will be descheduled and replaced in the interrupt exit point). Processes
- * running at the same priority can be descheduled when they expire the time
- * quantum.
- *
- * \note Sleeping while preemption is disabled fallbacks to a busy-wait sleep.
- * Voluntary preemption when preemption is disabled raises a kernel bug.
- *
- * \author Bernie Innocenti <bernie@codewiz.org>
- * \author Andrea Righi <arighi@develer.com>
- */
-
-#include "cfg/cfg_proc.h"
-
-#include "proc_p.h"
-#include "proc.h"
-
-#include <kern/irq.h>
-#include <kern/monitor.h>
-#include <cpu/frame.h> // CPU_IDLE
-#include <cpu/irq.h> // IRQ_DISABLE()...
-#include <cfg/log.h>
-#include <cfg/module.h>
-#include <cfg/depend.h> // CONFIG_DEPEND()
-
-// Check config dependencies
-CONFIG_DEPEND(CONFIG_KERN_PREEMPT, CONFIG_KERN);
-
-MOD_DEFINE(preempt)
-
-/**
- * CPU dependent context switching routines.
- *
- * Saving and restoring the context on the stack is done by a CPU-dependent
- * support routine which usually needs to be written in assembly.
- */
-EXTERN_C void asm_switch_context(cpu_stack_t **new_sp, cpu_stack_t **save_sp);
-
-/* Global preemption nesting counter */
-cpu_atomic_t preempt_count;
-
-/*
- * The time sharing interval: when a process is scheduled on a CPU it gets an
- * amount of CONFIG_KERN_QUANTUM clock ticks. When these ticks expires and
- * preemption is enabled a new process is selected to run.
- */
-int _proc_quantum;
-
-/**
- * Define function prototypes exported outside.
- *
- * Required to silent gcc "no previous prototype" warnings.
- */
-void preempt_yield(void);
-int preempt_needPreempt(void);
-void preempt_preempt(void);
-void preempt_switch(void);
-void preempt_init(void);
-
-/**
- * Call the scheduler and eventually replace the current running process.
- */
-static void preempt_schedule(void)
-{
- _proc_quantum = CONFIG_KERN_QUANTUM;
- proc_schedule();
-}
-
-/**
- * Check if we need to schedule another task
- */
-int preempt_needPreempt(void)
-{
- if (UNLIKELY(current_process == NULL))
- return 0;
- if (!proc_preemptAllowed())
- return 0;
- return _proc_quantum ? prio_next() > prio_curr() :
- prio_next() >= prio_curr();
-}
-
-/**
- * Preempt the current task.
- */
-void preempt_preempt(void)
-{
- IRQ_ASSERT_DISABLED();
- ASSERT(current_process);
-
- /* Perform the kernel preemption */
- LOG_INFO("preempting %p:%s\n", current_process, proc_currentName());
- /* We are inside a IRQ context, so ATOMIC is not needed here */
- SCHED_ENQUEUE(current_process);
- preempt_schedule();
-}
-
-/**
- * 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 preempt_switch(void)
-{
- ASSERT(proc_preemptAllowed());
- IRQ_ASSERT_ENABLED();
-
- ATOMIC(preempt_schedule());
-}
-
-/**
- * Voluntarily release the CPU.