preempt.c
Go to the documentation of this file.00001 00087 #include "cfg/cfg_proc.h" 00088 00089 #include "proc_p.h" 00090 #include "proc.h" 00091 00092 #include <kern/irq.h> 00093 #include <kern/monitor.h> 00094 #include <cpu/frame.h> // CPU_IDLE 00095 #include <cpu/irq.h> // IRQ_DISABLE()... 00096 #include <cfg/log.h> 00097 #include <cfg/module.h> 00098 #include <cfg/depend.h> // CONFIG_DEPEND() 00099 00100 // Check config dependencies 00101 CONFIG_DEPEND(CONFIG_KERN_PREEMPT, CONFIG_KERN); 00102 00103 MOD_DEFINE(preempt) 00104 00105 /* Global preemption nesting counter */ 00106 cpu_atomic_t preempt_count; 00107 00108 /* 00109 * The time sharing interval: when a process is scheduled on a CPU it gets an 00110 * amount of CONFIG_KERN_QUANTUM clock ticks. When these ticks expires and 00111 * preemption is enabled a new process is selected to run. 00112 */ 00113 int _proc_quantum; 00114 00120 void preempt_yield(void); 00121 int preempt_needPreempt(void); 00122 void preempt_preempt(void); 00123 void preempt_switch(void); 00124 void preempt_wakeup(Process *proc); 00125 void preempt_init(void); 00126 00130 static void preempt_schedule(void) 00131 { 00132 _proc_quantum = CONFIG_KERN_QUANTUM; 00133 proc_schedule(); 00134 } 00135 00139 int preempt_needPreempt(void) 00140 { 00141 if (UNLIKELY(current_process == NULL)) 00142 return 0; 00143 if (!proc_preemptAllowed()) 00144 return 0; 00145 return _proc_quantum ? prio_next() > prio_curr() : 00146 prio_next() >= prio_curr(); 00147 } 00148 00152 void preempt_preempt(void) 00153 { 00154 IRQ_ASSERT_DISABLED(); 00155 ASSERT(current_process); 00156 00157 /* Perform the kernel preemption */ 00158 LOG_INFO("preempting %p:%s\n", current_process, proc_currentName()); 00159 /* We are inside a IRQ context, so ATOMIC is not needed here */ 00160 SCHED_ENQUEUE(current_process); 00161 preempt_schedule(); 00162 } 00163 00172 void preempt_switch(void) 00173 { 00174 ASSERT(proc_preemptAllowed()); 00175 00176 ATOMIC(preempt_schedule()); 00177 } 00178 00182 void preempt_wakeup(Process *proc) 00183 { 00184 ASSERT(proc_preemptAllowed()); 00185 ASSERT(current_process); 00186 IRQ_ASSERT_DISABLED(); 00187 00188 if (prio_proc(proc) >= prio_curr()) 00189 { 00190 Process *old_process = current_process; 00191 00192 SCHED_ENQUEUE(current_process); 00193 _proc_quantum = CONFIG_KERN_QUANTUM; 00194 current_process = proc; 00195 proc_switchTo(current_process, old_process); 00196 } 00197 else 00198 SCHED_ENQUEUE_HEAD(proc); 00199 } 00200 00204 void preempt_yield(void) 00205 { 00206 /* 00207 * Voluntary preemption while preemption is disabled is considered 00208 * illegal, as not very useful in practice. 00209 * 00210 * ASSERT if it happens. 00211 */ 00212 ASSERT(proc_preemptAllowed()); 00213 IRQ_ASSERT_ENABLED(); 00214 00215 ATOMIC( 00216 SCHED_ENQUEUE(current_process); 00217 preempt_schedule(); 00218 ); 00219 } 00220 00221 void preempt_init(void) 00222 { 00223 MOD_INIT(preempt); 00224 }
