/* * Leave the interrupt. This function receives the register frame used to leave the supervisor * mode. It reschedules the task if it was asked for. */ void core_ExitInterrupt(CONTEXT *regs) { struct ExecBase *SysBase = *SysBasePtr; char TDNestCnt; D(bug("[Scheduler] core_ExitInterrupt\n")); if (SysBase) { /* Soft interrupt requested? It's high time to do it */ if (SysBase->SysFlags & SFF_SoftInt) { DS(bug("[Scheduler] Causing SoftInt\n")); core_Cause(SysBase); } if (Sleep_Mode) { core_Dispatch(regs); return; } /* If task switching is disabled, leave immediatelly */ TDNestCnt = SysBase->TDNestCnt; /* BYTE is unsigned in Windows so we can't use SysBase->TDNestCnt directly */ DS(bug("[Scheduler] TDNestCnt is %d\n", TDNestCnt)); if (TDNestCnt < 0) { /* * Do not disturb task if it's not necessary. * Reschedule only if switch pending flag is set. Exit otherwise. */ if (SysBase->AttnResched & ARF_AttnSwitch) { DS(bug("[Scheduler] Rescheduling\n")); core_Schedule(regs); } } } DS(else printf("[Scheduler] SysBase is NULL\n");) }
/* * Task dispatcher. Basically it may be the same one no matter what scheduling algorithm is used */ void core_Dispatch(regs_t *regs) { volatile struct ExecBase *SysBase = getSysBase(); struct Task *task; if (SysBase) { wrmsr(rdmsr() & ~MSR_EE); /* * Is the list of ready tasks empty? Well, increment the idle switch cound and halt CPU. * It should be extended by some plugin mechanism which would put CPU and whole machine * into some more sophisticated sleep states (ACPI?) */ while (IsListEmpty(&SysBase->TaskReady)) { // SysBase->IdleCount++; SysBase->AttnResched |= ARF_AttnSwitch; //D(bug("[KRN] TaskReady list empty. Sleeping for a while...\n")); /* Sleep almost forever ;) */ wrmsr(rdmsr() | MSR_EE); asm volatile("sync"); // wrmsr(rdmsr() | MSR_POW); // asm volatile("isync"); if (SysBase->SysFlags & SFF_SoftInt) { core_Cause(SysBase); } } SysBase->DispCount++; /* Get the first task from the TaskReady list, and populate it's settings through Sysbase */ task = (struct Task *)REMHEAD(&SysBase->TaskReady); SysBase->ThisTask = task; SysBase->Elapsed = SysBase->Quantum; SysBase->SysFlags &= ~0x2000; task->tc_State = TS_RUN; SysBase->IDNestCnt = task->tc_IDNestCnt; //D(bug("[KRN] New task = %p (%s)\n", task, task->tc_Node.ln_Name)); /* Handle tasks's flags */ if (task->tc_Flags & TF_EXCEPT) Exception(); /* Store the launch time */ GetIntETask(task)->iet_private1 = mftbu(); if (task->tc_Flags & TF_LAUNCH) { AROS_UFC1(void, task->tc_Launch, AROS_UFCA(struct ExecBase *, SysBase, A6)); } /* Restore the task's state */ regs = task->tc_UnionETask.tc_ETask->et_RegFrame; if (SysBase->IDNestCnt < 0) regs->srr1 |= MSR_EE; /* Copy the fpu, mmx, xmm state */ #warning FIXME: Change to the lazy saving of the FPU state!!!! #warning TODO: No FPU support yet!!!!!!! Yay, it sucks! :-D }