Adapt the BToolchainSearch dialog to the new dir structure.
[bertos.git] / bertos / kern / preempt.c
index f77dd85eff1c632bbd73adf1053b350140cfc1ca..bdb6d3c9e716b543529b464167b8ecc04a6a0751 100644 (file)
@@ -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)