preempt.c
Go to the documentation of this file.00001
00047 #include "cfg/cfg_proc.h"
00048
00049 #if CONFIG_KERN_PREEMPT
00050
00051 #include "proc_p.h"
00052 #include "proc.h"
00053 #include "idle.h"
00054
00055 #include <kern/irq.h>
00056 #include <kern/monitor.h>
00057 #include <cpu/frame.h>
00058 #include <cpu/irq.h>
00059 #include <drv/timer.h>
00060 #include <cfg/module.h>
00061 #include <cfg/depend.h>
00062
00063
00064 CONFIG_DEPEND(CONFIG_KERN_PREEMPT, CONFIG_KERN && CONFIG_TIMER_EVENTS && CONFIG_KERN_IRQ);
00065
00066 MOD_DEFINE(preempt)
00067
00068
00069 cpu_atomic_t _preempt_forbid_cnt;
00070
00071 static Timer preempt_timer;
00072
00073
00074 void proc_schedule(void)
00075 {
00076 IRQ_DISABLE;
00077
00078 ASSERT(proc_allowed());
00079 LIST_ASSERT_VALID(&ProcReadyList);
00080 CurrentProcess = (struct Process *)list_remHead(&ProcReadyList);
00081 ASSERT2(CurrentProcess, "no idle proc?");
00082
00083 IRQ_ENABLE;
00084
00085 TRACEMSG("launching %p:%s", CurrentProcess, proc_currentName());
00086 }
00087
00088 void proc_preempt(UNUSED_ARG(void *, param))
00089 {
00090 if (proc_allowed())
00091 {
00092 IRQ_DISABLE;
00093
00094 #if CONFIG_KERN_PRI
00095 Process *rival = (Process *)LIST_HEAD(&ProcReadyList);
00096 if (rival && rival->link.pri >= CurrentProcess->link.pri)
00097 {
00098 #endif
00099
00100 TRACEMSG("preempting %p:%s", CurrentProcess, proc_currentName());
00101
00102
00103 #if 0
00104 SCHED_ENQUEUE(CurrentProcess);
00105 proc_schedule();
00106 #endif
00107 #if CONFIG_KERN_PRI
00108 }
00109 #endif
00110
00111 IRQ_ENABLE;
00112 }
00113
00114 timer_setDelay(&preempt_timer, CONFIG_KERN_QUANTUM);
00115 timer_add(&preempt_timer);
00116 }
00117
00118 void proc_switch(void)
00119 {
00120 ATOMIC(LIST_ASSERT_VALID(&ProcReadyList));
00121 TRACEMSG("%p:%s", CurrentProcess, proc_currentName());
00122 ATOMIC(LIST_ASSERT_VALID(&ProcReadyList));
00123
00124
00125 IRQ_ASSERT_ENABLED();
00126 ASSERT(proc_allowed());
00127
00128
00129 kill(0, SIGUSR1);
00130 }
00131
00132 void proc_yield(void)
00133 {
00134 TRACEMSG("%p:%s", CurrentProcess, proc_currentName());
00135
00136 IRQ_DISABLE;
00137 SCHED_ENQUEUE(CurrentProcess);
00138 IRQ_ENABLE;
00139
00140 proc_switch();
00141 }
00142
00143 void proc_entry(void (*user_entry)(void))
00144 {
00145 user_entry();
00146 proc_exit();
00147 }
00148
00149 void preempt_init(void)
00150 {
00151 MOD_CHECK(irq);
00152 MOD_CHECK(timer);
00153
00154 irq_register(SIGUSR1, proc_schedule);
00155
00156 timer_setSoftint(&preempt_timer, proc_preempt, NULL);
00157 timer_setDelay(&preempt_timer, CONFIG_KERN_QUANTUM);
00158 timer_add(&preempt_timer);
00159
00160 idle_init();
00161
00162 MOD_INIT(preempt);
00163 }
00164
00165 #endif // CONFIG_KERN_PREEMPT