1 / 30

CPS110: Implementing threads on a uni-processor

CPS110: Implementing threads on a uni-processor. Landon Cox January 29, 2008. Recap and looking ahead. Applications. Threads, synchronization primitives. Atomic Load-Store, Interrupt enable- disable, Atomic Test-Set. OS. Where we’ve been. Where we’re going. Hardware.

ginny
Download Presentation

CPS110: Implementing threads on a uni-processor

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. CPS110: Implementing threads on a uni-processor Landon Cox January 29, 2008

  2. Recap and looking ahead Applications Threads, synchronization primitives Atomic Load-Store, Interrupt enable- disable, Atomic Test-Set OS Where we’ve been Where we’re going Hardware

  3. Recall, thread interactions • Threads can access shared data • Use locks, monitors, and semaphores • What we’ve done so far • Threads also share hardware • CPU (uni-processor) • Memory

  4. Hardware, OS interfaces Thread lectures up to this point Applications Job 1 Job 2 Job 3 CPU, Mem CPU, Mem CPU, Mem OS Memory CPU Hardware Memory lectures Remaining thread lectures

  5. 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

  6. Threads that aren’t running • What is a non-running thread? • thread=“sequence of executing instructions” • non-running thread=“paused execution” • Must save thread’s private state • To re-run, re-load private state • Want thread to start where it left off

  7. Private vs global thread state • What state is private to each thread? • Code (like lines of a play) • PC (where actor is in his/her script) • Stack, SP (actor’s mindset) • What state is shared? • Global variables, heap • (props on set)

  8. Thread control block (TCB) • What needs to access threads’ private data? • The CPU • This info is stored in the PC, SP, other registers • The OS needs pointers to non-running threads’ data • Thread control block (TCB) • Container for non-running thread’s private data • Values of PC, code, SP, stack, registers

  9. Thread control block Address Space TCB1 PC SP registers TCB2 PC SP registers TCB3 PC SP registers Ready queue Code Code Code Stack Stack Stack Thread 1 running CPU PC SP registers

  10. Thread control block Address Space TCB2 PC SP registers TCB3 PC SP registers Ready queue Code Stack Stack Stack Thread 1 running CPU PC SP registers

  11. Thread states • Running • Currently using the CPU • Ready • Ready to run, but waiting for the CPU • Blocked • Stuck in lock (), wait () or down ()

  12. Switching threads • What needs to happen to switch threads? • Thread returns control to OS • For example, via the “yield” call • OS chooses next thread to run • OS saves state of current thread • To its thread control block • OS loads context of next thread • From its thread control block • Run the next thread Project 1: swapcontext

  13. 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?

  14. 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 • Interrupts lead to pre-emption (a forced yield) • Common interrupt: timer interrupt

  15. 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

  16. 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

  17. 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 Instruction address 100 store PC in TCB 101 switch to next thread

  18. 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

  19. 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

  20. Example thread switching Thread 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)” switch to next thread (swapcontext) print “end yield (thread %d)” Thread 1 output Thread 2 output -------------------------------------------- start thread 1 start 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. Programmers must assume pre-emptions, so this output is not guaranteed.

  21. Thread states Running Thread is scheduled Thread calls Lock or wait (or makes I/O request) Thread is Pre-empted (or yields) Ready Blocked ? Another thread calls unlock or signal (or I/O completes)

  22. Creating a new thread • Also called “forking” a thread • Idea: create initial state, put on ready queue • Allocate, initialize a new TCB • Allocate a new stack • 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 • Add thread to ready queue

  23. Course administration • Second UTA • Jason Lee • Office hours: Thursday, 4:30-6:30, Teer lab • Lots of questions on newsgroup • Great resource

  24. Course administration • Project 1 disk scheduler (1d) • How to use concurrency primitives • Disk scheduler should be done or almost done • Two/seven groups are done with 1d • Project 1 thread library (1t) • How concurrency primitives actually work • Best way to learn something is to build it! (no such thing as magic) • Should be able to start after class • Time management is really, really important (start soon!!) • Happy answer any Project 1 questions

  25. Creating a new thread Parent call return Parent thread_create (parent work) Child (child work)

  26. Thread join • How can the parent wait for child to finish? Parent join thread_create (parent work) Child (child work)

  27. Thread join child () { print “child works” } • 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 parent () { create child thread print “parent works” yield () print “parent continues” } parent works child works parent continues child works parent works parent continues

  28. Thread join • Will this work? • No. Child can call signal first. • Would this work with semaphores? • Yes • No missed signals (increment sem value) parent () { create child thread lock print “parent works” wait print “parent continues” unlock } child () { lock print “child works” signal unlock } 2 1 3 parent works child works parent continues child works parent works parent continues

  29. How can we solve this? • Pair off for a couple of minutes parent () { childDone = 0 create child thread print “parent works” lock while (!childDone) { wait } print “parent continues” unlock } child () { print “child works” lock childDone = 1 signal unlock } parent works child works parent continues child works parent works parent continues

  30. Thread join • Many libraries supply “join” operation • Makes this a lot easier parent () { childDone = 0 create child thread print “parent works” join with child print “parent continues” } child () { print “child works” }

More Related