1
TOS Arno Puder
TOS Arno Puder 1 Objectives Explain non-preemptive scheduling - - PowerPoint PPT Presentation
TOS Arno Puder 1 Objectives Explain non-preemptive scheduling Explain step-by-step how a context switch works in TOS 2 Status Quo We can create new processes in TOS. New processes are added to the ready queue. The
1
TOS Arno Puder
2
3
4
5
. . . kprintf (“Location A\n”); resign(); kprintf (“Location B\n”); . . . Location A Location B
Output
6
create_process(), there are two processes on the ready queue and process_a has a higher priority
context switch to process_a, because it has the higher priority
resign
void process_a (PROCESS self, PARAM param) { kprintf (“Location C\n”); assert (self == active_proc); while (1); } void kernel_main() { init_process(); init_dispatcher(); create_process (process_a, 5, 0, “Process A”); kprintf (“Location A\n”); resign(); kprintf (“Location B\n”); while (1); } Location A Location C
Output
7
create_process(), there are
two processes on the ready queue and process_a has a higher priority
context to process_a
ready queue and then calls resign()
back to the first process.
were not called, the program would print “Location D” instead of “Location B”
void process_a (PROCESS self, PARAM param) { kprintf (“Location C\n”); remove_ready_queue (self); resign(); kprintf (“Location D\n”); while (1); } void kernel_main() { init_process(); init_dispatcher(); create_process (process_a, 5, 0 “Process A”); kprintf (“Location A\n”); resign(); kprintf (“Location B\n”); while (1); } Location A Location C Location B
Output
8
9
return addr EAX ECX EDX EBX EBP ESI EDI Used stack EIP (RET) %ESP
Stack frame of process 2 Stack frame of process 1
Used stack
10
active_proc->esp = %ESP; active_proc = dispatcher(); %ESP = active_proc->esp;
return addr EAX ECX EDX EBX EBP ESI EDI Used stack EIP (RET)
Stack frame of process 2 Stack frame of process 1
Used stack
EAX ECX EDX EBX EBP ESI EDI %ESP
11
return addr EAX ECX EDX EBX EBP ESI EDI Used stack EIP (RET)
Stack frame of process 2 Stack frame of process 1
Used stack
EAX ECX EDX EBX EBP ESI EDI %ESP
12
return addr Used stack EIP (RET)
Stack frame of process 2 Stack frame of process 1
Used stack
EAX ECX EDX EBX EBP ESI EDI %ESP
13
14
– for a new process we setup the stack (see create_process()) – for process calling resign() we setup the stack (identical to the way we did it for create_process()) before call to dispatch() – now you should be able to connect the dots
15
self func (EAX) (ECX) (EDX) (EBX) (EBP) (ESI) (EDI) Used stack EIP (RET) %ESP
Stack frame of process 2 Stack frame of process 1
param
16
17
active_proc->esp = %ESP; active_proc = dispatcher(); %ESP = active_proc->esp;
18
/* Save the stack pointer to the PCB */ asm ("movl %%esp,%0" : "=r" (active_proc->esp) : ); /* Select a new process to run */ active_proc = dispatcher(); /* Load the stack pointer from the PCB */ asm ("movl %0,%%esp" : : "r" (active_proc->esp));
– The register name %ESP has to be prefixed with another % – The specifier “=r” means “an output parameter that should be placed in an x86 register” – The specifier “r” means “an input parameter that should be placed in an x86 register”
19
20
return addr EAX ECX EDX EBX EBP ESI EDI Used stack return addr %ESP
Stack frame of process 2 Stack frame of process 1
Used stack name: “Process 2” esp: name: “Process 1” esp: PCB PCB active_proc:
21
return addr EAX ECX EDX EBX EBP ESI EDI Used stack return addr %ESP
Stack frame of process 2 Stack frame of process 1
Used stack name: “Process 2” esp: name: “Process 1” esp: PCB PCB active_proc: EAX ECX EDX EBX EBP ESI EDI
22
return addr EAX ECX EDX EBX EBP ESI EDI Used stack return addr %ESP
Stack frame of process 2 Stack frame of process 1
Used stack name: “Process 2” esp: name: “Process 1” esp: PCB PCB active_proc: EAX ECX EDX EBX EBP ESI EDI
23
return addr EAX ECX EDX EBX EBP ESI EDI Used stack return addr %ESP
Stack frame of process 2 Stack frame of process 1
Used stack name: “Process 2” esp: name: “Process 1” esp: PCB PCB active_proc: EAX ECX EDX EBX EBP ESI EDI
24
return addr EAX ECX EDX EBX EBP ESI EDI Used stack return addr %ESP
Stack frame of process 2 Stack frame of process 1
Used stack name: “Process 2” esp: name: “Process 1” esp: PCB PCB active_proc: EAX ECX EDX EBX EBP ESI EDI
25
return addr EAX ECX EDX EBX EBP ESI EDI Used stack return addr %ESP
Stack frame of process 2 Stack frame of process 1
Used stack name: “Process 2” esp: name: “Process 1” esp: PCB PCB active_proc: EAX ECX EDX EBX EBP ESI EDI
26
return addr EAX ECX EDX EBX EBP ESI EDI Used stack return addr %ESP
Stack frame of process 2 Stack frame of process 1
Used stack name: “Process 2” esp: name: “Process 1” esp: PCB PCB active_proc: EAX ECX EDX EBX EBP ESI EDI
27
return addr EAX ECX EDX EBX EBP ESI EDI Used stack return addr %ESP
Stack frame of process 2 Stack frame of process 1
Used stack name: “Process 2” esp: name: “Process 1” esp: PCB PCB active_proc: EAX ECX EDX EBX EBP ESI EDI
28
return addr Used stack return addr %ESP
Stack frame of process 2 Stack frame of process 1
Used stack name: “Process 2” esp: name: “Process 1” esp: PCB PCB active_proc: EAX ECX EDX EBX EBP ESI EDI
29
return addr Used stack return addr %ESP
Stack frame of process 2 Stack frame of process 1
Used stack name: “Process 2” esp: name: “Process 1” esp: PCB PCB active_proc: EAX ECX EDX EBX EBP ESI EDI
30
void resign()
31
– test_resign_1 – test_resign_2 – test_resign_3 – test_resign_4 – test_resign_5 – test_resign_6
32
33
void check_active() { assert(active_proc != NULL); } … active_proc = dispatcher(); check_active();
34
35
/* Save the stack pointer to the PCB */ asm ("movl %%esp,%0" : "=r" (active_proc->esp) : ); /* Select a new process to run */ active_proc = dispatcher(); /* Load the stack pointer from the PCB */ asm ("movl %0,%%esp" : : "r" (active_proc->esp));
void become_zombie() { active_proc->state = STATE_ZOMBIE; while (1); }
resign() this can done more efficiently:
void become_zombie() { active_proc->state = STATE_ZOMBIE; remove_ready_queue(active_proc); resign(); // Never reached while (1); }
36
37
init_pacman() via: int i; for (i = 0; i < num_ghosts; i++) create_process(ghost_proc, 3, 0, "Ghost");
see them yet, because they will not yet get scheduled.
process, you should see one ghost.
created several ghost processes (why?)
38
cooperative multitasking at this point.
control of the CPU by making a call to resign().
according to the following pseudo code:
see several ghosts!
void create_new_ghost() { GHOST ghost; init_ghost(&ghost); while (1) { remove ghost at old position (using remove_cursor()) compute new position of ghost show ghost at new position (using show_cursor()) do a delay resign() } }