Page 1 of 1

Stack Switching After Task Switch

Posted: Mon Feb 11, 2013 1:00 pm
by DirectXtreme
Hi, please could you please help, I have been stuck on software task switching for a while now. I have managed to get my tasks to switch by using a interrupt and then just save and restore EIP (and other regs). This has proved to work but I noticed that I would get random errors when changing to tasks that call other functions, by random I mean Page Fault, or GPF, or Invalid Opcode. I also noticed that the EIP when the error happens is why off any of my code (ie 0x4c). I assume this has to do with stack corruption as each task does not have its own stack because I have never managed to be able to set ESP on return from a interrupt. I have come up with the idea to get the interrupt to set EIP to an intermediary function which changes that stack pointer then jumps to the real code of the current task. See the code below.

Code: Select all

void TASKING_switch(CPU_REGISTERS *regs)
{
    if(bEnabled) //Have we enabled tasking yet?
    {
        if(task_switched == 1)
        {
            debug_serial_write("Old EIP =");
            debug_serial_write(regs->eip);
            debug_serial_write("\n\r");
	    memcpy(&current_task->Regs, regs, sizeof(CPU_REGISTERS));
	    current_task = current_task->Next;
            if(current_task == 0)
            	current_task = task_list_head;
	}     
	konsole_write("Switching Task\n\r");
	
	memcpy(regs, &current_task->Regs, sizeof(CPU_REGISTERS));
	regs->eip = (DWORD)do_switch;
	task_switched = 1;
    }
}
This called when the interrupt is fired.

Code: Select all

void do_switch(void)
{
  HAL_set_esp(current_task->Regs.esp);	
   jmpPtr jmp = (jmpPtr)current_task->Regs.eip;

   jmp();   
}
This is called when the interrupt returns and should switch the stack, this works, and jump to the EIP of the current task, this also works.

The problem is that when the task comes around for the second time a page fault occurs because due to a read operation at a huge (random) address

I want to work towards solving this problem so I do not expect the code needed to fix this. Any help would be greatly appreciated [-o< [-o< [-o<

Re: Stack Switching After Task Switch

Posted: Mon Feb 11, 2013 1:28 pm
by Combuster
jmp();
Knowing what instructions that generates, that sounds a lot like a stack smash...

Selecting a task might be doable in C. Switching however, can't sanely be done. Prove to yourself that all the registers are left off exactly where they were last time, as well as that the old task is now saved in the same manner as it would have been when it was created new, and you'll notice you'll have a hard time completing that with just having C code for architecture-specific things.


And now, it's time for your guru meditation. And trust me, it's going to be a hell of a ride. :wink:

Re: Stack Switching After Task Switch

Posted: Mon Feb 11, 2013 1:33 pm
by DirectXtreme
That makes sense, I did not think to check what instructions make up a function call. I did notice that my stack values became messed up each time the do_switch was called. Will change this function to pure ASM and post my results.

Thanks :)

Re: Stack Switching After Task Switch

Posted: Sat Feb 16, 2013 12:42 am
by DirectXtreme
Ok, so I now have basic task switching working. ie, the task switched and the stack is also changed. Thank you very much @Combuster, I did as suggested. Will not try and incorporate my page manager with task switching, ie. swap pages as well.