+ if (!preempt_forbid_cnt)
+ {
+ IRQ_DISABLE;
+ TRACEMSG("preempting %p:%s", CurrentProcess, proc_currentName());
+#if 0
+ SCHED_ENQUEUE(CurrentProcess);
+ proc_preempt();
+#endif
+ IRQ_ENABLE;
+ }
+
+ timer_setDelay(&preempt_timer, CONFIG_KERN_QUANTUM);
+ timer_add(&preempt_timer);
+}
+
+void proc_schedule(void)
+{
+ ATOMIC(LIST_ASSERT_VALID(&ProcReadyList));
+ TRACEMSG("%p:%s", CurrentProcess, proc_currentName());
+ ATOMIC(LIST_ASSERT_VALID(&ProcReadyList));
+
+ /* Sleeping with IRQs disabled or preemption forbidden is illegal */
+ ASSERT_IRQ_ENABLED();
+ ASSERT(preempt_forbid_cnt == 0);
+
+ // Will invoke proc_preempt() in interrupt context
+ kill(0, SIGUSR1);
+}
+
+void proc_yield(void)
+{
+ TRACEMSG("%p:%s", CurrentProcess, proc_currentName());
+
+ IRQ_DISABLE;
+ SCHED_ENQUEUE(CurrentProcess);
+ IRQ_ENABLE;
+
+ proc_schedule();
+}
+
+void proc_entry(void (*user_entry)(void))
+{
+ user_entry();
+ proc_exit();
+}
+
+void preempt_init(void)
+{
+ MOD_CHECK(irq);
+ MOD_CHECK(timer);
+
+ irq_register(SIGUSR1, proc_preempt);
+
+ timer_setSoftint(&preempt_timer, proc_preempt_timer, NULL);
+ timer_setDelay(&preempt_timer, CONFIG_KERN_QUANTUM);
+ timer_add(&preempt_timer);
+
+ idle_init();