/* All cores end up calling this whenever there is nothing left to do or they * don't know explicitly what to do. Non-zero cores call it when they are done * booting. Other cases include after getting a DEATH IPI. * * All cores attempt to run the context of any owning proc. Barring that, they * halt and wake up when interrupted, do any work on their work queue, then halt * again. In between, the ksched gets a chance to tell it to do something else, * or perhaps to halt in another manner. */ static void __attribute__((noreturn)) __smp_idle(void *arg) { struct per_cpu_info *pcpui = &per_cpu_info[core_id()]; pcpui->cur_kthread->flags = KTH_DEFAULT_FLAGS; while (1) { /* This might wake a kthread (the gp ktask), so be sure to run * PRKM after reporting the quiescent state. */ rcu_report_qs(); /* If this runs an RKM, we'll call smp_idle from the top. */ process_routine_kmsg(); try_run_proc(); cpu_bored(); /* call out to the ksched */ /* cpu_halt() atomically turns on interrupts and halts the core. * Important to do this, since we could have a RKM come in via * an interrupt right while PRKM is returning, and we wouldn't * catch it. When it returns, IRQs are back off. */ __set_cpu_state(pcpui, CPU_STATE_IDLE); cpu_halt(); __set_cpu_state(pcpui, CPU_STATE_KERNEL); } assert(0); }
/* All cores end up calling this whenever there is nothing left to do or they * don't know explicitly what to do. Non-zero cores call it when they are done * booting. Other cases include after getting a DEATH IPI. * * All cores attempt to run the context of any owning proc. Barring that, they * halt and wake up when interrupted, do any work on their work queue, then halt * again. In between, the ksched gets a chance to tell it to do something else, * or perhaps to halt in another manner. */ static void __attribute__((noinline, noreturn)) __smp_idle(void) { struct per_cpu_info *pcpui = &per_cpu_info[core_id()]; disable_irq(); /* might not be needed - need to look at KMSGs closely */ clear_rkmsg(pcpui); pcpui->cur_kthread->flags = KTH_DEFAULT_FLAGS; enable_irq(); /* one-shot change to get any IRQs before we halt later */ while (1) { disable_irq(); process_routine_kmsg(); try_run_proc(); cpu_bored(); /* call out to the ksched */ /* cpu_halt() atomically turns on interrupts and halts the core. * Important to do this, since we could have a RKM come in via an * interrupt right while PRKM is returning, and we wouldn't catch * it. */ __set_cpu_state(pcpui, CPU_STATE_IDLE); cpu_halt(); /* interrupts are back on now (given our current semantics) */ } assert(0); }