+void proc_preempt(UNUSED_ARG(void *, param))
+{
+ if (proc_allowed())
+ {
+ IRQ_DISABLE;
+
+ #if CONFIG_KERN_PRI
+ Process *rival = (Process *)LIST_HEAD(&ProcReadyList);
+ if (rival && rival->link.pri >= CurrentProcess->link.pri)
+ {
+ #endif
+
+ TRACEMSG("preempting %p:%s", CurrentProcess, proc_currentName());
+
+// FIXME: this still breaks havoc, probably because of some reentrancy issue
+#if 0
+ SCHED_ENQUEUE(CurrentProcess);
+ proc_schedule();
+#endif
+ #if CONFIG_KERN_PRI
+ }
+ #endif
+
+ IRQ_ENABLE;
+ }
+
+ timer_setDelay(&preempt_timer, CONFIG_KERN_QUANTUM);
+ timer_add(&preempt_timer);
+}
+
+void proc_switch(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 */
+ IRQ_ASSERT_ENABLED();
+ ASSERT(proc_allowed());
+
+ // Will invoke proc_switch() in interrupt context
+ kill(0, SIGUSR1);
+}
+
+void proc_yield(void)