slides on thr slides on threads eads borr borrowed by
play

Slides on thr Slides on threads eads borr borrowed by Chase owed - PowerPoint PPT Presentation

Slides on thr Slides on threads eads borr borrowed by Chase owed by Chase Landon Cox Landon Cox Thr Thread states ead states Running Thread is Thread calls scheduled Lock or wait Thread is (or makes I/O request) Pre-empted (or yields) ?


  1. Slides on thr Slides on threads eads � borr borrowed by Chase owed by Chase Landon Cox Landon Cox

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

  3. Pr Project 1 (test cases) oject 1 (test cases) ead library test suite too Remember to work on your thr Remember to work on your thread library test suite too • For each of your test cases For each of your test cases • No inputs (e.g., no input files, no command-line args) • All output to stdout (i.e., use cout) • Do not call start_preemption() • Diff output of test case w/ your library vs. w/ thread.o • Writing test cases riting test cases • Read through spec spec • • Write test cases to stress each required part • E.g., lock() blocks if lock is already held • Pre-emption is off, so use yield() to create the right interleavings Read through your code your code • • Write test cases to exercise all lines of code • E.g. each clause of an if/else statement Micr Micro-tests ar o-tests are better for debugging than macr e better for debugging than macro-tests o-tests •

  4. Pr Project 1 (garbage collection) oject 1 (garbage collection) • Garbage collecting thr Garbage collecting threads eads // simple network server ¡ while (1) { int s = socket.accept (); thread_create (handle_request, s); } • Do not want to run out of memory • What needs to be (C++) “deleted”? What needs to be (C++) “deleted”? • Any state associated with the thread (e.g., stack, TCB)

  5. Pr Project 1 (garbage collection) oject 1 (garbage collection) • Two key questions: wo key questions: • When can a stack be deleted and by whom? • When can a stack be deleted? When can a stack be deleted? • Only after the thread has finished its “work” • Work = function passed to thread_create, thread_libinit • Who definitely cannot delete a thr Who definitely cannot delete a thread’ ead’s stack? s stack? • The thread itself! • Try deleting the stack you are running on … • So which thr So which thread should delete the stack? ead should delete the stack?

  6. Pr Project 1 (garbage collection) oject 1 (garbage collection) • Hint: don’ Hint: don’t use t use uc_link uc_link • Only use set/swapcontext to jump to threads • Anyone want to guess why? Anyone want to guess why? • What can you say about state of interrupts? What can you say about state of interrupts? • Interrupts are enabled inside “work” function • After it exits, interrupts must be disabled • Tricky to guarantee this using uc_link • Can get an interrupt while switching to uc_link

  7. Pr Project 1 (garbage collection) oject 1 (garbage collection) • What makes What makes swapcontext swapcontext simpler? simpler? • uc_link loads threads outside of your lib • Calls to swapcontext are explicit • “Keep everything in front of you” • Any other Pr Any other Project 1 questions? oject 1 questions?

  8. Using interrupt disable-enable Using interrupt disable-enable • Disable-enable on a Disable-enable on a uni uni-pr -processor ocessor • Assume atomic (can use atomic load/store) • How do thr How do threads get switched out (2 ways)? eads get switched out (2 ways)? • Internal events (yield, I/O request) • External events (interrupts, e.g., timers) • Easy to pr Easy to prevent inter event internal events nal events • Use disable/enable to pr Use disable/enable to prevent exter event external events nal events

  9. Lock implementation #1 Lock implementation #1 • Disable interrupts, busy-waiting Disable interrupts, busy-waiting unlock () { lock () { disable interrupts disable interrupts value = FREE while (value != FREE) { enable interrupts enable interrupts } disable interrupts } value = BUSY enable interrupts } Why is it ok for lock code to disable interrupts? It’s in the trusted kernel (we have to trust something).

  10. Lock implementation #1 Lock implementation #1 • Disable interrupts, busy-waiting Disable interrupts, busy-waiting unlock () { lock () { disable interrupts disable interrupts value = FREE while (value != FREE) { enable interrupts enable interrupts } disable interrupts } value = BUSY enable interrupts } Do we need to disable interrupts in unlock? Only if “value = FREE” is multiple instructions (safer)

  11. Lock implementation #1 Lock implementation #1 • Disable interrupts, busy-waiting Disable interrupts, busy-waiting unlock () { lock () { disable interrupts disable interrupts value = FREE while (value != FREE) { enable interrupts enable interrupts } disable interrupts } value = BUSY enable interrupts } Why enable-disable in lock loop body? Otherwise, no one else will run (including unlockers)

  12. Using r Using read-modify-write instructions ead-modify-write instructions • Disabling interrupts Disabling interrupts • Ok for uni-processor, breaks on multi-processor • Why? • Could use atomic load-stor Could use atomic load-store to make a lock e to make a lock • Inefficient, lots of busy-waiting • Har Hardwar dware people to the r e people to the rescue! escue!

  13. Using r Using read-modify-write instructions ead-modify-write instructions • Most moder Most modern pr n processor ar ocessor architectur chitectures es • Provide an atomic read-modify-write instruction • Atomically Atomically • Read value from memory into register • Write new value to memory • Implementation details Implementation details • Lock memory location at the memory controller

  14. Lock implementation #3 Lock implementation #3 • Interrupt disable, no busy-waiting Interrupt disable, no busy-waiting lock () { disable interrupts if (value == FREE) { value = BUSY // lock acquire } else { add thread to queue of threads waiting for lock switch to next ready thread // don’t add to ready queue } enable interrupts } unlock () { disable interrupts value = FREE if anyone on queue of threads waiting for lock { take waiting thread off queue, put on ready queue value = BUSY } enable interrupts }

  15. Lock implementation #3 Lock implementation #3 lock () { disable interrupts if (value == FREE) { value = BUSY // lock acquire } else { add thread to queue of threads waiting for lock switch to next ready thread // don’t add to ready queue This is This is } enable interrupts called a called a } “hand-off” “hand-of f” unlock () { disable interrupts lock. lock. value = FREE if anyone on queue of threads waiting for lock { take waiting thread off queue, put on ready queue value = BUSY } enable interrupts } Who gets the lock after someone calls unlock? Who gets the lock after someone calls unlock?

  16. Lock implementation #3 Lock implementation #3 lock () { disable interrupts if (value == FREE) { value = BUSY // lock acquire } else { add thread to queue of threads waiting for lock switch to next ready thread // don’t add to ready queue This is This is } enable interrupts called a called a } “hand-off” “hand-of f” unlock () { disable interrupts lock. lock. value = FREE if anyone on queue of threads waiting for lock { take waiting thread off queue, put on ready queue value = BUSY } enable interrupts } Who might get the lock if it wer Who might get the lock if it weren’ en’t handed-of t handed-off f directly? (i.e., if value wer dir ectly? (i.e., if value weren’ en’t set BUSY in unlock) t set BUSY in unlock)

  17. Lock implementation #3 Lock implementation #3 lock () { disable interrupts if (value == FREE) { value = BUSY // lock acquire } else { add thread to queue of threads waiting for lock switch to next ready thread // don’t add to ready queue This is This is } enable interrupts called a called a } “hand-off” “hand-of f” unlock () { disable interrupts lock. lock. value = FREE if anyone on queue of threads waiting for lock { take waiting thread off queue, put on ready queue value = BUSY } enable interrupts } What kind of or What kind of ordering of lock acquisition guarantees dering of lock acquisition guarantees does the hand-of does the hand-off lock pr f lock provide? ovide?

  18. Lock implementation #3 Lock implementation #3 lock () { disable interrupts if (value == FREE) { value = BUSY // lock acquire } else { add thread to queue of threads waiting for lock switch to next ready thread // don’t add to ready queue This is This is } enable interrupts called a called a } “hand-off” “hand-of f” unlock () { disable interrupts lock. lock. value = FREE if anyone on queue of threads waiting for lock { take waiting thread off queue, put on ready queue value = BUSY } enable interrupts } What does this mean? Are we saving the PC? What does this mean? Ar e we saving the PC?

  19. Lock implementation #3 Lock implementation #3 lock () { disable interrupts if (value == FREE) { value = BUSY // lock acquire } else { lockqueue.push(&current_thread->ucontext); swapcontext(&current_thread->ucontext, This is This is &new_thread->ucontext)); } called a called a enable interrupts } “hand-of “hand-off” f” unlock () { lock. lock. disable interrupts value = FREE if anyone on queue of threads waiting for lock { take waiting thread off queue, put on ready queue value = BUSY } enable interrupts } No, just adding a pointer to the TCB/context. No, just adding a pointer to the TCB/context.

Recommend


More recommend