X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=bertos%2Fkern%2Fpreempt.c;h=4b5e66c3d2261b67874b645c79e0351f7e8d1805;hb=aea9c54dbb7ea4b957f675ffee7266e0432cfd42;hp=2f44164b20174382c48355b08842fe2e314b5e51;hpb=6fa2660c8ba089bbf8a1d711f46f882604ff9a6c;p=bertos.git diff --git a/bertos/kern/preempt.c b/bertos/kern/preempt.c index 2f44164b..4b5e66c3 100644 --- a/bertos/kern/preempt.c +++ b/bertos/kern/preempt.c @@ -91,7 +91,6 @@ #include #include -#include // idle_proc #include // CPU_IDLE #include // IRQ_DISABLE()... #include @@ -103,14 +102,6 @@ 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; @@ -130,6 +121,7 @@ void preempt_yield(void); int preempt_needPreempt(void); void preempt_preempt(void); void preempt_switch(void); +void preempt_wakeup(Process *proc); void preempt_init(void); /** @@ -137,39 +129,8 @@ void preempt_init(void); */ static void preempt_schedule(void) { - Process *old_process = current_process; - - IRQ_ASSERT_DISABLED(); - - /* Poll on the ready queue for the first ready process */ - LIST_ASSERT_VALID(&proc_ready_list); - current_process = (Process *)list_remHead(&proc_ready_list); - if (UNLIKELY(!current_process)) - current_process = idle_proc; _proc_quantum = CONFIG_KERN_QUANTUM; - /* - * Optimization: don't switch contexts when the active process has not - * changed. - */ - if (LIKELY(old_process != current_process)) - { - cpu_stack_t *dummy; - - /* - * Save context of old process and switch to new process. If - * there is no old process, we save the old stack pointer into - * a dummy variable that we ignore. In fact, this happens only - * when the old process has just exited. - * - * \todo Instead of physically clearing the process at exit - * time, a zombie list should be created. - */ - asm_switch_context(¤t_process->stack, - old_process ? &old_process->stack : &dummy); - } - - /* This RET resumes the execution on the new process */ - LOG_INFO("resuming %p:%s\n", current_process, proc_currentName()); + proc_schedule(); } /** @@ -181,6 +142,8 @@ int preempt_needPreempt(void) return 0; if (!proc_preemptAllowed()) return 0; + if (LIST_EMPTY(&proc_ready_list)) + return 0; return _proc_quantum ? prio_next() > prio_curr() : prio_next() >= prio_curr(); } @@ -196,8 +159,7 @@ void preempt_preempt(void) /* 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 */ - if (current_process != idle_proc) - SCHED_ENQUEUE(current_process); + SCHED_ENQUEUE(current_process); preempt_schedule(); } @@ -212,11 +174,32 @@ void preempt_preempt(void) void preempt_switch(void) { ASSERT(proc_preemptAllowed()); - IRQ_ASSERT_ENABLED(); ATOMIC(preempt_schedule()); } +/** + * Immediately wakeup a process, dispatching it to the CPU. + */ +void preempt_wakeup(Process *proc) +{ + ASSERT(proc_preemptAllowed()); + ASSERT(current_process); + IRQ_ASSERT_DISABLED(); + + if (prio_proc(proc) >= prio_curr()) + { + Process *old_process = current_process; + + SCHED_ENQUEUE(current_process); + _proc_quantum = CONFIG_KERN_QUANTUM; + current_process = proc; + proc_switchTo(current_process, old_process); + } + else + SCHED_ENQUEUE_HEAD(proc); +} + /** * Voluntarily release the CPU. */ @@ -239,6 +222,5 @@ void preempt_yield(void) void preempt_init(void) { - idle_init(); MOD_INIT(preempt); }