CS代写 Operating Systems – CSCI 402

Operating Systems – CSCI 402
Intel x86: Subroutine Code (2)
local variables (8 bytes)
saved registers (empty)
ebp
eip
args
sub:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
movl $1, -4(%ebp)
movl $0, -8(%ebp)
movl -4(%ebp), %ecx
movl -8(%ebp), %eax
beginloop:
cmpl 12(%ebp), %eax
jge endloop
imull 8(%ebp), %ecx
addl $1, %eax
jmp beginloop
endloop:
movl %ecx, -4(%ebp)
movl -4(%ebp), %eax
movl %ebp, %esp
popl %ebp
ret
set up
esp
stack frame for sub()
int sub(int x, int y) {
// computes x^y
int i;
int result = 1;
for (i=0; iSP = SP;
CurrentThread = next_thread;
SP = CurrentThread->SP;
return; }
TCB(A) CurrentThread
CPU
TCB(B)
Operating Systems – CSCI 402
saved context
SP ?
saved context SP
EBP ESP
?
?
?mutex_lock
Stack(A)
thread A calls switch() to switch to thread B
thread B¡¯s TCB has the exact context of thread B right before thread B was last suspended
context information in thread A¡¯s TCB is out-dated
Stack(B)
61
321 0
Copyright ý . Systems – CSCI 402
Switching Between Threads
void switch(thread_t *next_thread) {
CurrentThread->SP = SP;
CurrentThread = next_thread;
SP = CurrentThread->SP;
return; }
switch:
;enter switch, creating new stack frame
pushl %ebp ;push FP
movl %esp,%ebp ;set FP to point to new frame
pushl %esi ;save esi register
movl CurrentThread,%esi ;load address of caller¡¯s TCB
movl %esp,SP(%esi) ;save SP in control block
movl 8(%ebp),CurrentThread ;store target TCB address
;into CurrentThread
movl CurrentThread,%esi ;put new TCB address into esi
movl SP(%esi),%esp ;restore target thread¡¯s SP
;we¡¯re now in the context of the target thread!
popl %esi ;restore target thread¡¯s esi register
popl %ebp ;pop target threadss FP
ret ;return to caller within target thread
62
321 0
Copyright ý . Between Threads
void switch(thread_t *next_thread) {
CurrentThread->SP = SP;
CurrentThread = next_thread;
SP = CurrentThread->SP;
return; }
TCB(A) CurrentThread
CPU
TCB(B)
Operating Systems – CSCI 402
saved context SP ?
?
?
?mutex_lock
Stack(A)
why is switch() called?
may be because thread A called pthread_mutex_lock() and the mutex is not available
321 0
saved context SP
EBP ESP
Stack(B)
63
Copyright ý . Between Threads
void switch(thread_t *next_thread) {
CurrentThread->SP = SP;
CurrentThread = next_thread;
SP = CurrentThread->SP;
return; }
TCB(A) CurrentThread
CPU
TCB(B)
Operating Systems – CSCI 402
saved context SP ?
saved context SP
EBP ESP
?
?
switch
?mutex_lock
Stack(A)
on entry into switch(), the caller¡¯s registers are saved!
Stack(B)
64
321 0
Copyright ý . Between Threads
void switch(thread_t *next_thread) {
CurrentThread->SP = SP;
CurrentThread = next_thread;
SP = CurrentThread->SP;
return; }
TCB(A) CurrentThread
CPU
TCB(B)
Operating Systems – CSCI 402
saved context SP ?
saved context
SP
EBP ESP
?
?
switch
?mutex_lock
Stack(A)
then the current stack pointer is saved into current thread¡¯s thread control block
Stack(B)
65
321 0
Copyright ý . Between Threads
void switch(thread_t *next_thread) {
CurrentThread->SP = SP;
CurrentThread = next_thread;
SP = CurrentThread->SP;
return; }
TCB(A) CurrentThread
CPU
TCB(B)
Operating Systems – CSCI 402
saved context SP
?
?
switch
?mutex_lock
Stack(A)
then the current stack pointer is saved into current thread¡¯s thread control block
saved context
SP
EBP ESP
Stack(B)
Copyright ý . Cheng
66
321 0

Switching Between Threads
void switch(thread_t *next_thread) {
CurrentThread->SP = SP;
CurrentThread = next_thread;
SP = CurrentThread->SP;
return; }
TCB(A) CurrentThread
CPU
TCB(B)
Operating Systems – CSCI 402
saved context
SP
saved context SP
EBP ESP
?
?
switch
?mutex_lock
Stack(A)
the target thread becomes the current thread
Stack(B)
67
321 0
Copyright ý . Between Threads
void switch(thread_t *next_thread) {
CurrentThread->SP = SP;
CurrentThread = next_thread;
SP = CurrentThread->SP;
return; }
TCB(A) CurrentThread
CPU
TCB(B)
Operating Systems – CSCI 402
saved context
SP
saved context SP
EBP ESP
?
?
switch
?mutex_lock
Stack(A)
the target thread becomes the current thread
Stack(B)
68
321 0
Copyright ý . Between Threads
void switch(thread_t *next_thread) {
CurrentThread->SP = SP;
CurrentThread = next_thread;
SP = CurrentThread->SP;
return; }
TCB(A) CurrentThread
CPU
TCB(B)
Operating Systems – CSCI 402
saved context
SP
?
?
switch
?mutex_lock
Stack(A)
fetch the target thread¡¯s stack pointer (esp for x86) from its thread control block and loads it into the actual stack pointer
321 0
saved context
SP
EBP ESP
Stack(B)
69
Copyright ý . Between Threads
void switch(thread_t *next_thread) {
CurrentThread->SP = SP;
CurrentThread = next_thread;
SP = CurrentThread->SP;
return; }
TCB(A) CurrentThread
CPU
TCB(B)
Operating Systems – CSCI 402
saved context SP
switch
?
switch
?mutex_lock
Stack(A)
fetch the target thread¡¯s stack pointer (esp for x86) from its thread control block and loads it into the actual stack pointer
hmm… which thread executes this? does it matter? what about EIP?
321 0
70
saved context
SP
EBP ESP
Stack(B)
Copyright ý . Between Threads
void switch(thread_t *next_thread) {
CurrentThread->SP = SP;
CurrentThread = next_thread;
SP = CurrentThread->SP;
return; }
TCB(A) CurrentThread
CPU
TCB(B)
Operating Systems – CSCI 402
saved context
SP
switch
?
switch
?mutex_lock
Stack(A)
on return from switch(), the registers (ebp and eip for x86) are restored into the current thread, which is the target thread!
which thread executes return? does it matter? what about EIP?
321 0
71
saved context
SP
EBP ESP
Stack(B)
Copyright ý . Between Threads
void switch(thread_t *next_thread) {
CurrentThread->SP = SP;
CurrentThread = next_thread;
SP = CurrentThread->SP;
return; }
TCB(A) CurrentThread
CPU
TCB(B)
Operating Systems – CSCI 402
saved context
SP
?
switch
?mutex_lock
Stack(A)
on return from switch(), the registers (ebp and eip for x86) are restored into the current thread, which is the target thread!
which thread executes return? does it matter? what about EIP?
321 0
72
saved context
SP
EBP ESP
Stack(B)
Copyright ý . Between Threads
void switch(thread_t *next_thread) {
CurrentThread->SP = SP;
CurrentThread = next_thread;
SP = CurrentThread->SP;
return; }
TCB(A) CurrentThread
CPU
TCB(B)
Operating Systems – CSCI 402
saved context
SP
?
switch
?mutex_lock
Stack(A)
if thread control blocks were user-space data structures, threads were switched without getting the kernel involved!
Note: SP field inside TCB(B) no longer tracks ESP in CPU Copyright ý . Cheng
321 0
73
saved context
SP
EBP ESP
Stack(B)

Operating Systems – CSCI 402
Switching Between Threads
void switch(thread_t *next_thread) {
CurrentThread->SP = SP;
CurrentThread = next_thread;
SP = CurrentThread->SP;
return; }
Note: one very interesting thing happened in this call
usually, a single thread executes the entire procedure call with switch(), at the beginning of the procedure call, one thread is executing
half way through the procedure call, another thread starts to execute
so, one thread enters the switch() call, and a different thread leaves the switch() call!
but from whose perspective?!
74
321 0
Copyright ý . Systems – CSCI 402
Switching Between Threads
void switch(thread_t *next_thread) {
CurrentThread->SP = SP;
CurrentThread = next_thread;
SP = CurrentThread->SP;
return; }
With switch(), one thread enters the switch() call, and a different thread leaves the switch() call!
that¡¯s from the system¡¯s perspective
from the calling thread¡¯s perspective, it fell asleep in switch() from the next_thread¡¯s perspective, it woke up in switch()
it fell asleep a while back and now woke up somehow
from the CPU¡¯s perspective
“I did what?! What¡¯s a thread?”
thread is just an abstraction, CPU doesn¡¯t really know about threads
75
321 0
Copyright ý . Systems – CSCI 402
Switching Between Threads
void switch(thread_t *next_thread) {
CurrentThread->SP = SP;
CurrentThread = next_thread;
SP = CurrentThread->SP;
return; }
This is an elegant way of switching threads
all threads come here to switch to another thread
This code is incomplete
what if next_thread is NULL?
it saves some of the CPU registers, but we need to save all of the CPU registers
will revisit in Ch 5
76
321 0
Copyright ý . Cheng

pushl %esi ;save esi register }
movl CurrentThread,%esi ;load address of caller¡¯s TCB
movl %esp,SP(%esi) ;save SP in control block
movl 8(%ebp),CurrentThread ;store target TCB address
;into CurrentThread
movl CurrentThread,%esi ;put new TCB address into esi
movl SP(%esi),%esp ;restore target thread¡¯s SP
;we¡¯re now in the context of the target thread!
popl %esi ;restore target thread¡¯s esi register
popl %ebp ;pop target threadss FP
ret ;return to caller within target thread
The above is hand-written and not compiler generated can easily change it to save more registers
Operating Systems – CSCI 402
… in x86 Assembler
switch:
void switch(thread_t *next_thread) { ;enter switch, creating new stack frame
pushl %ebp ;push FP
movl %esp,%ebp ;set FP to poSiPn=tCutrorenteTwhrefard-a>mSeP;
CurrentThread->SP = SP;
CurrentThread = next_thread;
return;
77
321 0
Copyright ý . Systems – CSCI 402
switch:
save %sp, -64, %sp
t 3
st %sp, [%g0+SP]
mov %i0, %g0
ld [%g0+SP], %sp
ret
restore
! Push a new stack frame.
! Trap into the OS to force
! window overflow.
! Save CurrentThread¡¯s SP in
! control block.
! Set CurrentThread to be
! target thread.
! Set SP to that of target thread
! return to caller (in target
! thread¡¯s context).
! Pop frame off stack (in delay
! slot).
… in SPARC Assembler
78
321 0
Copyright ý . Systems – CSCI 402
3.1 Context Switching
Procedures
Threads & Coroutines Systems Calls Interrupts
79
321 0
Copyright ý . Systems – CSCI 402
System Calls
A system call involves the transfer of control from user code to system/kernel code and back
there is no thread switching!
although there was a context switch
depending on the OS implementation (and as far as this class is concerned), this can view this as a user thread change status and becomes a kernel thread
and executes in priviledged mode and executing operating-system code
effectively, it¡¯s part of the OS
in reality, more complex than just changing status
it then changed back to a user thread eventually
80
321 0
Copyright ý . Systems – CSCI 402
System Calls
Most systems provide threads with two stacks
one for use in user mode
and one for use in kernel mode (as far as this class is concerned)
in some systems (not common these days), one kernel stack
is shared by all threads in the same user process (Ch 5)
therefore, when a thread performs a system call and switches from user mode to kernel mode
it switches to use its kernel-mode stack
the kernel cannot use the user-space stack because it cannot trust the user process
what if the user process has almost used up the stack space?
81
321 0
Copyright ý . Calls
A trap is a type of “software interrupt” interrupt handler will invoke trap handler
prog( ) { …
write(fd, buffer, size);
… }}
User
Kernel
intr_handler(intr_code) {

if (intr_code == SYSCALL)
syscall_handler( );
… }
syscall_handler(trap_code) {

if (trap_code == write_code)
write_handler( );
… }
trap(write_code);

User Stack
Operating Systems – CSCI 402
prog() frame
write( ) { …
Copyright ý . Stack
321 0
82

prog( ) { …
write(fd, buffer, size);
… }}
User
Kernel
intr_handler(intr_code) {

if (intr_code == SYSCALL)
syscall_handler( );
… }
syscall_handler(trap_code) {

if (trap_code == write_code)
write_handler( );
… }
trap(write_code);

User Stack
Operating Systems – CSCI 402
System Calls
A trap is a type of “software interrupt” interrupt handler will invoke trap handler
write() frame
prog() frame
write( ) { …
Copyright ý . Stack
321 0
83

prog( ) { …
write(fd, buffer, size);
… }}
User
Kernel
intr_handler(intr_code) {

if (intr_code == SYSCALL)
syscall_handler( );
… }
syscall_handler(trap_code) {

if (trap_code == write_code)
write_handler( );
… }
trap(write_code);

User Stack
Operating Systems – CSCI 402
System Calls
A trap is a type of “software interrupt” interrupt handler will invoke trap handler
write() frame
prog() frame
write( ) { …
intr_handler() frame
Kernel Stack
321 0
84
Copyright ý . Cheng

prog( ) { …
write(fd, buffer, size);
… }}
User
Kernel
intr_handler(intr_code) {

if (intr_code == SYSCALL)
syscall_handler( );
… }
syscall_handler(trap_code) {

if (trap_code == write_code)
write_handler( );
… }
trap(write_code);

User Stack
Operating Systems – CSCI 402
System Calls
A trap is a type of “software interrupt” interrupt handler will invoke trap handler
write() frame
prog() frame
write( ) { …
syscall_handler() frame
intr_handler() frame
Kernel Stack
321 0
85
Copyright ý . Systems – CSCI 402
System Calls
A trap is a type of “software interrupt” interrupt handler will invoke trap handler
write() frame
prog() frame
prog( ) { …
write(fd, buffer, size);
… }}
User
Kernel
intr_handler(intr_code) {

if (intr_code == SYSCALL)
syscall_handler( );
… }
syscall_handler(trap_code) {

if (trap_code == write_code)
write_handler( );
… }
trap(write_code);

User Stack
write( ) { …
write_handler() frame
syscall_handler() frame
intr_handler() frame
Kernel Stack
321 0
86
Copyright ý . Cheng

prog( ) { …
write(fd, buffer, size);
… }}
User
Kernel
intr_handler(intr_code) {

if (intr_code == SYSCALL)
syscall_handler( );
… }
syscall_handler(trap_code) {

if (trap_code == write_code)
write_handler( );
… }
trap(write_code);

User Stack
Operating Systems – CSCI 402
System Calls
A trap is a type of “software interrupt” interrupt handler will invoke trap handler
write() frame
prog() frame
write( ) { …
syscall_handler() frame
intr_handler() frame
Kernel Stack
321 0
87
Copyright ý . Cheng

prog( ) { …
write(fd, buffer, size);
… }}
User
Kernel
intr_handler(intr_code) {

if (intr_code == SYSCALL)
syscall_handler( );
… }
syscall_handler(trap_code) {

if (trap_code == write_code)
write_handler( );
… }
trap(write_code);

User Stack
Operating Systems – CSCI 402
System Calls
A trap is a type of “software interrupt” interrupt handler will invoke trap handler
write() frame
prog() frame
write( ) { …
intr_handler() frame
Kernel Stack
321 0
88
Copyright ý . Calls
A trap is a type of “software interrupt” interrupt handler will invoke trap handler
prog( ) { …
write(fd, buffer, size);
… }}
User
Kernel
intr_handler(intr_code) {

if (intr_code == SYSCALL)
syscall_handler( );
… }
syscall_handler(trap_code) {

if (trap_code == write_code)
write_handler( );
… }
trap(write_code);

User Stack
Operating Systems – CSCI 402
write() frame
prog() frame
write( ) { …
Copyright ý . Stack
321 0
89

trap(write_code);

User Stack
Operating Systems – CSCI 402
System Calls
A trap is a type of “software interrupt” interrupt handler will invoke trap handler
prog() frame
prog( ) { …
write(fd, buffer, size);
… }}
User
Kernel
intr_handler(intr_code) {

if (intr_code == SYSCALL)
syscall_handler( );
… }
syscall_handler(trap_code) {

if (trap_code == write_code)
write_handler( );
… }
write( ) { …
Copyright ý . Stack
321 0
90