Context Switch..An initial investigtion on ARM processor

Modern operating system offer multitasking and multiprocessing. Even we have multiprocessor based systems. All of these require a Scheduler to manage and ever wondered how fast and smoothly all these are managed by Scheduler so that we don't even notice even a glitch. 
The answer lies in the core of Scheduler - Context Switch
Let's take a small example of scheduler code from SLOS;

task t=0,t';

scheduler()
{
    t' = t+1;
    if t' = MAX_NUM_OF_TASK then
        t' = 0;
    end;

    contextSwitch(t,t');
}

See what is scheduler without a little function at the end of it.  Now lets see this code in little more detail. The current task PCB t, is set to 0 during initialization. When periodic tick occurs, next task t' is calculated from the task list. If the task reaches the MAX then t' is reset to Zero. It's a simple round robin scheduling. Once the task is selected, it need to be run. That where our context switching happens.
ContextSwitch() mainly does two tasks:-
    1. Saving the current context, t
    2. Loading the next context, t'
Ahh, we know this basic but lets go in little more detail now.

Save the current context, t

All the task execute in user mode so the user mode registers need to be saved.
1. save r0 - r3 & r14 from the stack which belong to the current task.
2. r13 points to the PCB of current task t. 
3. store all the registers from r0- r14 and this occur in a single instruction.
4. store spsr and return lr.
Here is what happens,

Offset15Regs   EQU   15*4

LDMFD  r13!,{r0-r3,r12,r14}
LDR        r13,=PCB_t
LDR        r13,[r13]
SUB        r13,r13,#Offset15Regs
STMIA   r13,{r0-r14}^
MRS       r0, spsr
STMDB r13,{r0-r14}

Load the next context, t'

1. load r13 at offset -60 from start of new PCB.
2. load spsr and lr first and then load rest r0-r14
3. IRQ stack is restored from PCB_IRQStack.
4. new task, t' is assumed after copying the address held in r14 into pc and updating cpsr.
Here is the code for this,

LDR        r13,=PCB_t'
LDR        r13,[r13]
SUB        r13,r13,#Offset15Regs
LDMDB r13,{r0-r14}
MSR       spsr_cxsf, r0
LDMIA  r13,{r0-r14}^
LDR       r13,+PCB_IRQStack
LDR       r13,[r13]
MOVS   ps,r14


Now the Context Switch is complete!!!


1 comment:

  1. I can see you saving registers in PCB_t - #Offset15Regs (60 bytes), is that means your process stack starts with cpu registers and then PCB_t !? Can you explain how your stack ptr and PCB_t layout looks like ?

    ReplyDelete