CPS110: Implementing threads Landon Cox. Recap and looking ahead Hardware OS Applications Where...
-
Upload
joseph-harmon -
Category
Documents
-
view
220 -
download
2
Transcript of CPS110: Implementing threads Landon Cox. Recap and looking ahead Hardware OS Applications Where...
CPS110: Implementing threads
Landon Cox
Recap and looking ahead
HardwareHardware
OSOS
ApplicationsApplications
Where we’ve been Where we’re
going
Recall, thread interactions
1. Threads can access shared data E.g., use locks, monitors What we’ve done so far
2. Threads also share hardware CPU and memory
For this class, assume uni-processor Single CPU core: one thread runs at a time Unrealistic in the multicore era!
Hardware, OS interfaces
HardwareHardware
OSOS
ApplicationsApplications
MemoryMemory CPUCPU
CPU, MemCPU, Mem
Job 1Job 1CPU, MemCPU, Mem
Job 2Job 2CPU, MemCPU, Mem
Job 3Job 3
Remaining thread lecturesMemory lectures
Thread lectures up to this point
The play analogy
Process is like a play performance Program is like the play’s script One CPU is like a one-man-show
(actor switches between roles)
Threads
Address space
Threads that aren’t running
What is a non-running thread? thread=“stream of executing instructions” non-running thread=“paused execution” Blocked/waiting, or suspended but ready
Must save thread’s private state Leave stack etc. in memory where it lies Save registers to memory Reload registers to resume thread
Private vs global thread state
What state is private to each thread? PC (where actor is in his/her script) Stack, SP (actor’s mindset)
What state is shared? Code (like lines of a play) Global variables, heap (props on set)
Thread control block (TCB)
The software that manages threads and schedules/dispatches them is the thread system or “OS”
OS must maintain data to describe each thread Thread control block (TCB) Container for non-running thread’s private data Values of PC, SP, other registers (“context”) Each thread also has a stack
Other OS data structures (scheduler queues, locks, waiting lists) reference these TCB objects.
Thread control block
CPUCPU
Address SpaceAddress Space
TCB1PCSP
registers
TCB1PCSP
registers
TCB2PCSP
registers
TCB2PCSP
registers
TCB3PCSP
registers
TCB3PCSP
registers
CodeCode
StackStackCodeCode
StackStackCodeCode
StackStack
PCSP
registers
PCSP
registersThread 1 running
Ready queue
Thread states
Running Currently using the CPU
Ready (suspended) Ready to run when CPU is next
available Blocked (waiting or sleeping)
Stuck in lock (), wait () or down ()
Switching threads
What needs to happen to switch threads?1.Thread returns control to OS
For example, via the “yield” call
2.OS chooses next thread to run3.OS saves state of current thread
To its thread control block
4.OS loads context of next thread From its thread control block
5.Run the next thread
Project 1: swapcontext
1. Thread returns control to OS
How does the thread system get control? Voluntary internal events Thread might block inside lock or wait Thread might call into kernel for service
(system call)
Thread might call yield
Are internal events enough?
1. Thread returns control to OS
Involuntary external events (events not initiated by the thread) Hardware interrupts
Transfer control directly to OS interrupt handlers From 104
CPU checks for interrupts while executing Jumps to OS code with interrupt mask set
OS may preempt the running thread (force yield) when an interrupt gives the OS control of its CPU
Common interrupt: timer interrupt
2. Choosing the next thread
If no ready threads, just spin Modern CPUs: execute a “halt” instruction Project 1: exit if no ready threads
Loop switches to thread if one is ready Many ways to prioritize ready threads
Will discuss a little later in the semester
3. Saving state of current thread
What needs to be saved? Registers, PC, SP
What makes this tricky? Self-referential sequence of actions Need registers to save state But you’re trying to save all the
registers Saving the PC is particularly tricky
Saving the PC
Why won’t this work?
Returning thread will execute instruction at 100 And just re-execute the switch Really want to save address 102
100 store PC in TCB101 switch to next thread
Instruction address
4. OS loads the next thread
Where is the thread’s state/context? Thread control block (in memory)
How to load the registers? Use load instructions to grab from
memory How to load the stack?
Stack is already in memory, load SP
5. OS runs the next thread
How to resume thread’s execution? Jump to the saved PC
On whose stack are these steps running? or Who jumps to the saved PC?
The thread that called yield (or was interrupted or called lock/wait)
How does this thread run again? Some other thread must switch to it
Example thread switchingThread 1 print “start thread 1” yield () print “end thread 1”
Thread 2 print “start thread 2” yield () print end thread 2”
yield () print “start yield (thread %d)” swapcontext (tcb1, tcb2) print “end yield (thread %d)”
swapcontext (tcb1, tcb2) save regs to tcb1 load regs from tcb2 // sp points to tcb2’s stack now! jump tcb2.pc // sp must point to tcb1’s stack! return
Thread 1 output Thread 2 output--------------------------------------------start thread 1start yield (thread 1)
start thread 2 start yield (thread 2)
end yield (thread 1)end thread 1
end yield (thread 2) end thread 2
Note: this assumes no pre-emptions.If OS is preemptive, then other interleavings are possible.
Thread states
BlockedBlockedReadyReady
RunningRunning
Thread is scheduled
Thread is Pre-empted(or yields)
Thread callsLock or wait(or makes I/O request)
Another thread calls
unlock or signal (or I/O completes)
??
Creating a new thread
Also called “forking” a thread Idea: create initial state, put on ready queue1.Allocate, initialize a new TCB2.Allocate a new stack3.Make it look like thread was going to call a
function PC points to first instruction in function SP points to new stack Stack contains arguments passed to function Project 1: use makecontext
4.Add thread to ready queue
Creating a new thread
Parentreturncall
Parentthread_create (parent work)
(child work)Child
Thread join
How can the parent wait for child to finish?
ParentParentthread_createthread_create (parent work)(parent work)
(child work)(child work)ChildChild
joinjoin
Thread join
Will this work? Sometimes, assuming
Uni-processor No pre-emptions Child runs after parent
Never, ever assume these things! Yield is like slowing the CPU
Program must work +- any yields
child () { print “child works”}
parent () { create child thread print “parent works” yield () print “parent continues”}
parent workschild worksparent continues
child worksparent worksparent continues
Thread join Will this work?
No. Child can call signal first. Would this work with semaphores?
Yes No missed signals (increment sem value)
child () { lock print “child works” signal unlock}
parent () { create child thread lock print “parent works” wait print “parent continues” unlock} parent works
child worksparent continues
child worksparent worksparent continues
213
How can we solve this?
Pair off for a couple of minuteschild () {
}
parent () {
}
parent workschild worksparent continues
child worksparent worksparent continues