proc: change proc_yield() behaviour.
[bertos.git] / bertos / kern / coop.c
index 1b2e1bb9bc42497a193d12e736642f8155b67250..c5cab0ed2e4475ab1d192f897921edd139d4e1b0 100644 (file)
  */
 void coop_yield(void);
 void coop_switch(void);
+void coop_wakeup(Process *proc);
 
-void coop_switch(void)
+static void coop_switchTo(Process *proc)
 {
-       IRQ_ASSERT_ENABLED();
+       Process *old_process = current_process;
+
+       SCHED_ENQUEUE(current_process);
+       current_process = proc;
+       proc_switchTo(current_process, old_process);
+}
 
+/**
+ * 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 coop_switch(void)
+{
        ATOMIC(proc_schedule());
 }
 
+/**
+ * Immediately wakeup a process, dispatching it to the CPU.
+ */
+void coop_wakeup(Process *proc)
+{
+       ASSERT(proc_preemptAllowed());
+       ASSERT(current_process);
+       IRQ_ASSERT_DISABLED();
+
+       if (prio_proc(proc) >= prio_curr())
+               coop_switchTo(proc);
+       else
+               SCHED_ENQUEUE_HEAD(proc);
+}
+
 /**
  * Co-operative context switch
  */
 void coop_yield(void)
 {
-       ATOMIC(SCHED_ENQUEUE(current_process));
-       coop_switch();
+       Process *proc;
+
+       IRQ_DISABLE;
+       proc = (struct Process *)list_remHead(&proc_ready_list);
+       if (proc)
+               coop_switchTo(proc);
+       IRQ_ENABLE;
 }