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!!!
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!!!
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