X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=bertos%2Fkern%2Fpreempt.c;h=bdb6d3c9e716b543529b464167b8ecc04a6a0751;hb=d1b1e979862ca866eaee324e0363d57bf5a0e13b;hp=f77dd85eff1c632bbd73adf1053b350140cfc1ca;hpb=938512200c9fbd8e08c88dbdddbdc1f030d3b663;p=bertos.git diff --git a/bertos/kern/preempt.c b/bertos/kern/preempt.c index f77dd85e..bdb6d3c9 100644 --- a/bertos/kern/preempt.c +++ b/bertos/kern/preempt.c @@ -121,8 +121,19 @@ 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); +static void preempt_switchTo(Process *proc) +{ + Process *old_process = current_process; + + SCHED_ENQUEUE(current_process); + _proc_quantum = CONFIG_KERN_QUANTUM; + current_process = proc; + proc_switchTo(current_process, old_process); +} + /** * Call the scheduler and eventually replace the current running process. */ @@ -141,6 +152,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(); } @@ -171,16 +184,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()) + preempt_switchTo(proc); + else + SCHED_ENQUEUE_HEAD(proc); +} + /** * Voluntarily release the CPU. */ void preempt_yield(void) { + Process *proc; + /* * Voluntary preemption while preemption is disabled is considered * illegal, as not very useful in practice. @@ -190,10 +219,11 @@ void preempt_yield(void) ASSERT(proc_preemptAllowed()); IRQ_ASSERT_ENABLED(); - ATOMIC( - SCHED_ENQUEUE(current_process); - preempt_schedule(); - ); + IRQ_DISABLE; + proc = (struct Process *)list_remHead(&proc_ready_list); + if (proc) + preempt_switchTo(proc); + IRQ_ENABLE; } void preempt_init(void)