Пример #1
0
/*
 * 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");)
}
Пример #2
0
/*
 * 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

    }