X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=bertos%2Fkern%2Fproc_p.h;h=56c810819b56964d2d16c83fe29075fbde8f3e5b;hb=d1b1e979862ca866eaee324e0363d57bf5a0e13b;hp=a5c7dbe3120ef6ff134039ecd4adca68c63e52f0;hpb=04188ad75e2fb6ec7d681649c1b4a171d7c9f5a3;p=bertos.git diff --git a/bertos/kern/proc_p.h b/bertos/kern/proc_p.h index a5c7dbe3..56c81081 100644 --- a/bertos/kern/proc_p.h +++ b/bertos/kern/proc_p.h @@ -48,12 +48,47 @@ #include /* for cpu_stack_t */ #include // IRQ_ASSERT_DISABLED() -#if CONFIG_KERN_PREEMPT - #include // XXX -#endif - #include // struct Process +/* + * 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. @@ -64,19 +99,32 @@ /** Track running processes. */ -extern REGISTER Process *CurrentProcess; +extern REGISTER Process *current_process; /** * Track ready processes. * * Access to this list must be performed with interrupts disabled */ -extern REGISTER List ProcReadyList; +extern REGISTER List proc_ready_list; #if CONFIG_KERN_PRI - #define SCHED_ENQUEUE_INTERNAL(proc) LIST_ENQUEUE(&ProcReadyList, &(proc)->link) + #define prio_next() (LIST_EMPTY(&proc_ready_list) ? INT_MIN : \ + ((PriNode *)LIST_HEAD(&proc_ready_list))->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) + #define SCHED_ENQUEUE_HEAD_INTERNAL(proc) \ + LIST_ENQUEUE_HEAD(&proc_ready_list, &(proc)->link) #else - #define SCHED_ENQUEUE_INTERNAL(proc) ADDTAIL(&ProcReadyList, &(proc)->link) + #define prio_next() 0 + #define prio_proc(proc) 0 + #define prio_curr() 0 + + #define SCHED_ENQUEUE_INTERNAL(proc) ADDTAIL(&proc_ready_list, &(proc)->link) + #define SCHED_ENQUEUE_HEAD_INTERNAL(proc) ADDHEAD(&proc_ready_list, &(proc)->link) #endif /** @@ -90,10 +138,17 @@ extern REGISTER List ProcReadyList; */ #define SCHED_ENQUEUE(proc) do { \ IRQ_ASSERT_DISABLED(); \ - LIST_ASSERT_VALID(&ProcReadyList); \ + LIST_ASSERT_VALID(&proc_ready_list); \ SCHED_ENQUEUE_INTERNAL(proc); \ } while (0) +#define SCHED_ENQUEUE_HEAD(proc) do { \ + IRQ_ASSERT_DISABLED(); \ + LIST_ASSERT_VALID(&proc_ready_list); \ + SCHED_ENQUEUE_HEAD_INTERNAL(proc); \ + } while (0) + + #if CONFIG_KERN_PRI /** * Changes the priority of an already enqueued process. @@ -108,10 +163,10 @@ extern REGISTER List ProcReadyList; INLINE void sched_reenqueue(struct Process *proc) { IRQ_ASSERT_DISABLED(); - LIST_ASSERT_VALID(&ProcReadyList); + LIST_ASSERT_VALID(&proc_ready_list); Node *n; PriNode *pos = NULL; - FOREACH_NODE(n, &ProcReadyList) + FOREACH_NODE(n, &proc_ready_list) { if (n == &proc->link.link) { @@ -125,18 +180,25 @@ INLINE void sched_reenqueue(struct Process *proc) if (pos) { REMOVE(&proc->link.link); - LIST_ENQUEUE(&ProcReadyList, &proc->link); + LIST_ENQUEUE(&proc_ready_list, &proc->link); } } #endif //CONFIG_KERN_PRI -/// Schedule another process *without* adding the current one to the ready list. +/* Process trampoline */ +void proc_entry(void); + +/* Schedule another process *without* adding the current one to the ready list. */ void proc_switch(void); -#if CONFIG_KERN_PREEMPT -void proc_entry(void (*user_entry)(void)); -void preempt_init(void); -#endif +/* 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 */