Page 1 of 1

Scheduler Issues [Solved]

Posted: Sun Jan 18, 2015 1:57 pm
by jvc
Hello,

I have been working on a scheduler and am running into a page fault issue.
I have a yield function, shown below, that is called by the PIT handler every 10ms. It is also called within a spinlock. At the moment, when it is called from the spinlock, a page fault occurs on return from the yield function. In this situation, it loads in a task that was yielded normally through the timer, so the page fault is occuring in my irq common function when it attempts to check the registers pushed onto the stack.

Even if I disable interrupts in the spinlock before yielding, the page fault still occurs leading me to believe that it is not a synchronization issue occuring within the yield function itself.

Here is the yield function:

Code: Select all

static volatile uint8_t yield_lock = 0;
void yield()
{
    if (currProc == 0) // Tasking not yet installed
        return;
    if (__sync_lock_test_and_set(&yield_lock, 1))
        return;

    // Reschedule current task if running and NOT idle task
    if (currProc->state == TASK_RUNNING && currProc != kidle_task)
    {
        sched_queueRunnable(currProc);
    }

    //Get next process, or idle if nothing (could very well be the task we just rescheduled ;) )
    list_node_t* nextProcNode = list_dequeue(processReadyQueue);
    process_t* nextProc = 0;
    if (!nextProcNode) // If no ready processes, load idle task
        nextProc = kidle_task;
    else
        nextProc = nextProcNode->data;

    //Debug
    if (nextProc->state != TASK_RUNNING)
        kprintf("Scheduling a non-running task...\n");

    // Save state
    fpu_switch();
    virtmem_switchcontext(nextProc->virtPD); // Don't do function calls after we start stack switch, for safety reasons...

    uint32_t esp, ebp, eip; // Stack context stored, EIP never stored, but is used to jump to idle because it doesn't initially have a stack setup. Also, for forking, not an issue because we can just copy the stack!
    asm volatile ("mov %%esp, %0" : "=r" (esp));
    asm volatile ("mov %%ebp, %0" : "=r" (ebp));

    currProc->thread.eip = 0; // Idle should return here normally now because of context switch
    currProc->thread.esp = esp;
    currProc->thread.ebp = ebp;
    
    //Next Process -- Address space already loaded, fpu handled when fpu instruction executed
    esp = nextProc->thread.esp;
    ebp = nextProc->thread.ebp;
    eip = nextProc->thread.eip;

    currProc = nextProc;

    asm volatile ("mov %0, %%esp" : : "r" (esp) : "%esp");
    asm volatile ("mov %0, %%ebp" : : "r" (ebp));

    if (eip)
    {
        __sync_lock_release(&yield_lock);
        IRQ_RES;
        asm volatile ("mov %0, %%ebx\n"
                      "jmp *%%ebx" : : "r"(eip) : "%ebx");
    }
    __sync_lock_release(&yield_lock);
    return;
}
Jacob

Re: Scheduler Issues

Posted: Sun Jan 18, 2015 2:09 pm
by alexfru
You're not using inline assembly correctly. There might be other issues, but this one alone is sufficient for things to break.

Re: Scheduler Issues

Posted: Sun Jan 18, 2015 2:13 pm
by jvc
In what way am I not using it correctly?

Thanks,
Jacob

Re: Scheduler Issues

Posted: Sun Jan 18, 2015 2:25 pm
by alexfru
For one thing, you are stealing the stack from the compiler. And it's an optimizing compiler, which rearranges things and the order of the actions that you see in the source code is not the same as in the compiled object/binary code. The compiler could've cached some things in registers in ways you're not expecting.

Re: Scheduler Issues

Posted: Sun Jan 18, 2015 2:58 pm
by jvc
Thanks, I think you are probably right, and it is probably best that I redo the scheduler in a better way.

I'm thinking it would be better for all tasking switching to occur within an interrupt. So that the context switch will involve just changing the registers pushed onto the stack. After the interrupt, it will be in the new context with the correct stacks, hopefully..... Anyways, time to move onto other non-computer related things ;)

Jacob

Re: Scheduler Issues [Solved]

Posted: Tue Jan 20, 2015 8:38 pm
by jvc
Hey Thanks Alexfru!

I realized, thanks to you, that my scheduler design was terrible. So I went and completely redesigned it to not use any inline assembly, or messy stack tricks. Seems to work quite well, and it is also running noticeably faster. So thank you! :)

Jacob