Lecture 12: Peterson’s Solution and Hardware Support
Review: Mutual Exclusion Critical region Disabling interrupts Strict alternation
In this lecture Mutual exclusion solutions Peterson’s solution Hardware support
General structure enter_region(); critical_region(); leave_region();
Peterson’s Solution (1981)
Hardware Support: TSL New Instruction: TSL R, Lock TSL = “Test and Set Lock” R = register, Lock = memory location Atomically (atomic = nothing can interfere) - Read Lock into R - Store a non-zero value into Lock
Mutual Exclusion using TSL /* set lock to non-zero, proceed if it was 0 earlier */ enter_region: TSL Reg, Lock /* set Lock to 1, copy old value of Lock into Reg*/ If (Reg != 0) then /* not the first to set to zero */ Jump enter_region /* try again */ return leave_region: Lock = 0
Alternative to TSL: XCHG /* set lock to non-zero, proceed if it was 0 earlier */ enter_region: Reg = 1 XCHG Reg, Lock /* swap contents of Reg and Lock */ If (Reg != 0) then /* not the first to set to zero */ Jump enter_region /* try again */ return leave_region: Lock = 0
Problem Busy waiting Possible solution: Yield to another thread if unable to lock first time
Eliminate Busy Waiting /* set lock to non-zero, proceed if it was 0 earlier */ enter_region: TSL Reg, Lock /* set Lock to 1, copy old value of Lock into Reg*/ If (Reg != 0) then /* not the first to set to zero */ { thread_yield() ; /* let somebody else run */ Jump enter_region /* try again */ } return leave_region: Lock = 0
Summary of mutual exclusion solutions Software solution Disabling interrupts Single processor only Use in kernel mode Strict alternation Strict ordering Busy waiting Peterson’s solution Hardware solution TSL/XCHG Works on multiprocessors
Avoiding Busy Waiting If a process cannot enter critical region, the process calls sleep() to give up CPU. A process wakes up another process using wakeup()
Review: Mutual Exclusion using TSL /* set lock to non-zero, proceed if it was 0 earlier */ enter_region: TSL Reg, Lock /* set Lock to 1, copy old value of Lock into Reg*/ If (Reg != 0) then /* not the first to set to zero */ Jump enter_region /* try again */ return leave_region: Lock = 0
TSL without busy waiting /* set lock to non-zero, proceed if it was 0 earlier */ enter_region: TSL Reg, Lock /* set Lock to 1, copy old value of Lock into Reg*/ If (Reg != 0) then /* not the first to set to zero */ { sleep() Jump enter_region /* try again */ return leave_region: Lock = 0 wakeup(process_id)