in libs/core---vm/scheduler.cpp [399:468]
static void mainRunLoop() {
FiberContext *f = NULL;
for (;;) {
if (panicCode)
return;
wakeFibers();
auto now = current_time_ms();
auto fromBeg = false;
if (!f) {
f = allFibers;
fromBeg = true;
}
while (f) {
if (f->wakeTime && now >= (int)f->wakeTime)
f->wakeTime = 0;
if (!f->wakeTime && !f->waitSource)
break;
f = f->next;
}
if (f) {
if (currentFiber != f) {
saveStack();
currentFiber = f;
restoreStack();
}
f->pc = f->resumePC;
f->resumePC = NULL;
if (f->wakeFn) {
auto fn = f->wakeFn;
f->wakeFn = NULL;
f->r0 = fn(f->wakeFnArg);
if (f->wakeTime || f->waitSource)
continue; // we got suspended again
}
exec_loop(f);
if (panicCode)
return;
auto n = f->next;
if (f->resumePC == NULL) {
if (f->foreverPC) {
f->resumePC = f->foreverPC;
f->wakeTime = current_time_ms() + 20;
// restore stack, as setupThread() does it
for (int i = 0; i < 5; ++i) {
if (*--f->sp == TAG_STACK_BOTTOM)
break;
}
if (*f->sp != TAG_STACK_BOTTOM)
target_panic(PANIC_INVALID_IMAGE);
} else {
auto hb = f->handlerBinding;
if (hb) {
auto pev = hb->pending;
if (pev) {
hb->pending = pev->next;
setupThread(hb->action, fromInt(pev->value), hb);
xfree(pev);
} else {
f->handlerBinding->flags &= ~HANDLER_RUNNING;
}
}
disposeFiber(f);
}
}
f = n;
} else if (fromBeg) {
target_yield();
}
}
}