X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=bertos%2Fkern%2Fproc_p.h;h=56c810819b56964d2d16c83fe29075fbde8f3e5b;hb=d1b1e979862ca866eaee324e0363d57bf5a0e13b;hp=f1b5aa34805503296c4954ea248cf17186fecdb1;hpb=32d1445272120a254d77ce8d1af1f527da7a2c17;p=bertos.git diff --git a/bertos/kern/proc_p.h b/bertos/kern/proc_p.h index f1b5aa34..56c81081 100644 --- a/bertos/kern/proc_p.h +++ b/bertos/kern/proc_p.h @@ -49,8 +49,46 @@ #include // IRQ_ASSERT_DISABLED() #include // struct Process -#include // idle_proc +/* + * Check if the process context switch can be performed directly by the + * architecture-dependent asm_switch_context() or if it must be delayed + * because we're in the middle of an ISR. + * + * Return true if asm_switch_context() can be executed, false + * otherwise. + * + * NOTE: if an architecture does not implement IRQ_RUNNING() this function + * always returns true. + */ +#define CONTEXT_SWITCH_FROM_ISR() (!IRQ_RUNNING()) + +#ifndef asm_switch_context +/** + * 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); +#endif + +/* + * Save context of old process and switch to new process. + */ +INLINE void proc_switchTo(Process *next, Process *prev) +{ + cpu_stack_t *dummy; + + if (UNLIKELY(next == prev)) + return; + /* + * 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. + */ + asm_switch_context(&next->stack, prev ? &prev->stack : &dummy); +} /** * \name Flags for Process.flags. @@ -71,9 +109,10 @@ extern REGISTER Process *current_process; extern REGISTER List proc_ready_list; #if CONFIG_KERN_PRI - #define prio_next() (LIST_EMPTY(&proc_ready_list) ? idle_proc->link.pri : \ + #define prio_next() (LIST_EMPTY(&proc_ready_list) ? INT_MIN : \ ((PriNode *)LIST_HEAD(&proc_ready_list))->pri) - #define prio_curr() (current_process->link.pri) + #define prio_proc(proc) (proc->link.pri) + #define prio_curr() prio_proc(current_process) #define SCHED_ENQUEUE_INTERNAL(proc) \ LIST_ENQUEUE(&proc_ready_list, &(proc)->link) @@ -81,6 +120,7 @@ extern REGISTER List proc_ready_list; LIST_ENQUEUE_HEAD(&proc_ready_list, &(proc)->link) #else #define prio_next() 0 + #define prio_proc(proc) 0 #define prio_curr() 0 #define SCHED_ENQUEUE_INTERNAL(proc) ADDTAIL(&proc_ready_list, &(proc)->link) @@ -145,10 +185,21 @@ INLINE void sched_reenqueue(struct Process *proc) } #endif //CONFIG_KERN_PRI -/// Schedule another process *without* adding the current one to the ready list. -void proc_switch(void); +/* Process trampoline */ void proc_entry(void); +/* Schedule another process *without* adding the current one to the ready list. */ +void proc_switch(void); + +/* Low level scheduling routine. */ +void proc_schedule(void); + +/* Low level context switch routine. */ +void proc_switchTo(Process *next, Process *prev); + +/* Initialize a scheduler class. */ +void proc_schedInit(void); + #if CONFIG_KERN_MONITOR /** Initialize the monitor */ void monitor_init(void);