Docsity
Docsity

Prepare for your exams
Prepare for your exams

Study with the several resources on Docsity


Earn points to download
Earn points to download

Earn points by helping other students or get them with a premium plan


Guidelines and tips
Guidelines and tips

Critical Section Problem Solutions: Mutual Exclusion, Bounded Waiting, and Progress, Study notes of Operating Systems

Various solutions to the critical section problem in concurrency control, focusing on mutual exclusion, bounded waiting, and progress. The solutions include peterson's algorithm, dekker's algorithm, and lamport's bakery algorithm. The document also discusses the importance of atomic operations and disabling interrupts.

Typology: Study notes

Pre 2010

Uploaded on 09/17/2009

koofers-user-sth
koofers-user-sth 🇺🇸

10 documents

1 / 7

Toggle sidebar

Related documents


Partial preview of the text

Download Critical Section Problem Solutions: Mutual Exclusion, Bounded Waiting, and Progress and more Study notes Operating Systems in PDF only on Docsity! Maria Hybinette, UGA CSCI 4730 Operating Systems Synchronization Part 1 Maria Hybinette, UGA 2 Chapter 6: Process Synchronization ! Why is synchronization needed? ! Definitions: » What are race conditions? » What are critical sections? » What are atomic operations? ! How are locks implemented? Maria Hybinette, UGA 3 Why does cooperation require synchronization? (Review) ! Example: Two threads: Maria and Tucker share an account with shared variable ‘balance’ in memory. ! Code to deposit(): ! Both Maria & Tucker deposits money into account: » Initialization: balance = 100 » Maria: deposit( 200 ) » Tucker: deposit( 10 ) void deposit( int amount ) { balance = balance + amount; } deposit: load RegisterA, balance add RegisterA, amount store RegisterA, balance ! Compiled to assembly: Which variables are shared? Which private? Maria Hybinette, UGA 4 Example Execution 1. Initialization: balance = 100 2. Maria: deposit( 200 ) 3. Tucker: deposit( 10 ) deposit: load RegisterA, balance add RegisterA, amount store RegisterA, balance deposit (Maria): load RegisterA, 100 add RegisterA, 200 store RegisterA, balance deposit (Tucker): load RegisterA, 300 add RegisterA, 10 store RegisterA, balance T im e Memory: balance = 100 RegisterA = 01003 3 1 1 Maria Hybinette, UGA 5 Concurrency ! What happens if M & T deposit concurrently? » Assume any interleaving is possible » No assumption about scheduler » Observation: When a thread is interrupted content of registers are saved (and restored) by interrupt handlers. deposit (Maria): load RegisterA, balance add RegisterA, 200 store RegisterA, balance deposit (Tucker): load RegisterA, balance add RegisterA, 10 store RegisterA, balance T im e 1. Memory: balance = 100 RegisterA = 0 1. Memory: balance = 100 RegisterA = 0 2 100 2 100 3 3 3 1 4 3 4 1 deposit: load RegisterA, balance add RegisterA, amount store RegisterA, balance Maria Hybinette, UGA 6 Aside: What program data is shared? ! Local variables are not shared (private) » Each thread has its own stack » Local variables are allocated on private stack » Weird Bugs: Never pass, share or store a pointer to a local variable on another threads stack ! Global variables and static objects are shared » Stored in the static data segment, accessible by any threads ! Dynamic objects and other heap objects are shared » Allocated from heap with malloc/free or new/delete Maria Hybinette, UGA 7 Race Condition ! Results depends on order of execution » Result in non-deterministic bugs, hard to fine! – Deterministic : Input alone determines results, i.e., the same inputs always produce the same results ! Intermittent - time depended `bug’ a small change may hide the real bug (e.g., print statements can hide the real bug because the slow down processing and impact the timing of the threads). Maria Hybinette, UGA 8 How to avoid race conditions ! Idea: Prohibit one or more threads from reading and writing shared data at the same time! ! Provide Mutual Exclusion ! Critical Section: Part of program where shared memory is accessed void credit( int amount ) { int x = 5; printf( “Adding money” ); balance = balance + amount; } void debit( int amount ) { int i; balance = balance - amount; for( i = 0; i < 5; i++ ); } Critical Section Maria Hybinette, UGA 9 Critical Sections ! Problem: Avoiding race conditions (i.e., provide mutual exclusion) is not sufficient for having threads cooperate correctly and efficiently » What about if no one gets into the critical section even if several threads wants to get in? » What about if someone waits outside the critical section and never gets a turn? Maria Hybinette, UGA 10 Mutual Exclusion Process Maria Process Tucker Time Maria enters her critical section Maria leaves her critical section Tucker attempts to enter his critical section Tucker is blocked, and waits Tucker enters his critical section Tucker leaves his critical section void deposit( int amount ) { balance = balance + amount; } Maria Hybinette, UGA 11 Critical Section Problem: Properties Required Properties: ! Mutual Exclusion: » Only one thread in critical section at a time ! Progress (e.g., someone gets the CS): » Not block others out: if there are requests to enter the CS must allow one to proceed (e.g., no deadlocks). » Must not depend on threads outside critical section – If no one is in CS then must let someone in. ! Bounded waiting (starvation-free): » Must eventually allow each waiting thread to enter Maria Hybinette, UGA 12 Critical Section Problem: Properties Required “Proper”ties : ! Mutual Exclusion ! Progress (someone gets the CS) ! Bounded waiting (starvation-free) Desirable Properties: ! Efficient: » Don’t consume substantial resources while waiting. Do not busy wait (i.e., spin wait) ! Fair: » Don’t make some processes wait longer than others ! Simple: Should be easy to reason about and use Maria Hybinette, UGA 25 Attempt 3: Check then Lock ! Problems: » No Mutual Exclusion ! Lesson: Process lock’s the critical section AFTER the process has checked it is available but before it enters the section. ! Idea: Lock the section first! then lock NoCheck then Lock NoNoYesStrict Alteration Bounded Waiting No Starvation No Shared Lock Variable Progress someone gets the CS Mutual Exclusion Pace limited to slowest process Maria Hybinette, UGA 26 Attempt 4: Lock then Check ! Idea: Each thread has its own lock; lock indexed by tid (0, 1). Check other’s needs ! Does this work? Mutual exclusion? Progress (someone gets the CS if empty, no deadlock)? Bounded Waiting (no starvation)? boolean lock[2] = {false, false} // shared void deposit( int amount ) { lock[tid] = true; while( lock[1-tid] == true ) {} /* wait */ ; balance += amount; // critical section lock[tid] = false; } Entry CS: CS: Exit CS: Maria Hybinette, UGA 27 boolean lock[2] = {false, false} // shared void deposit( int amount ) { lock[tid] = true; while( lock[1-tid] == true ) {} /* wait */; balance += amount; // critical section lock[tid] = false; } Attempt 4: Lock then Check Mutual Exclusion? ! Maria’s View: Once Maria sets her lock: » Tucker cannot enter until Maria is done » Tucker already in CS, then Maria blocks until Tucker leaves the CS ! Tucker’s View: Same thing ! So yes Mutual Exclusion Time 0: Process Maria 1: Process Tucker Maria Hybinette, UGA 28 boolean lock[2] = {false, false} // shared void deposit( int amount ) { lock[tid] = true; while( lock[1-tid] == true ) {} /* wait */; balance += amount; // critical section lock[tid] = false; } Attempt 4: Lock then Check ! Mutual Exclusion: Yes ! Deadlocks: Each thread waits for the other. Each one thinks that the other is in the critical section Time 0: Process Maria 1: Process Tucker Maria waits for Tucker Tucker waits for Maria Maria Hybinette, UGA 29 Attempt 4: Lock then Check ! Problems: » No one gets the critical section! » Each thread ‘insisted’ on its right to get the CS and did not back off from this position. ! Lesson: Again a ‘state’ problem, a thread misunderstood the state of the other thread ! Idea: Allow a thread to back off to give the other a chance to enter its critical section. No (deadlock)YesLock then Check NoCheck then Lock NoNoYesStrict Alteration Bounded Waiting No Starvation No Shared Lock Variable Progress someone gets the CS Mutual Exclusion Pace limited to slowest process Maria Hybinette, UGA 30 Attempt 5: Defer, back-off lock ! Idea: Add an delay boolean lock[2] = {false, false} // shared void deposit( int amount ) { lock[tid] = true; while( lock[1-tid] == true ) { lock[tid] = false; delay; lock[tid] = true; } balance += amount; // critical section lock[tid] = false; } Entry CS: CS: Exit CS: Maria Hybinette, UGA 31 boolean lock[2] = {false, false} void deposit( int amount ) { lock[tid] = true; while( lock[1-tid] == true ) lock[tid] = false; delay; lock[tid] = true; balance += amount; //critical section lock[tid] = false; } Attempt 5: Deferral ! Mutual Exclusion: Yes ! Live Lock: sequence can be broken if you are lucky! » Not really a deadlock (guaranteed not to be able to proceed) » Not starvation - threads starves when a process repeatedly loose to the other threads, here both loose Time 0: Process Maria 1: Process Tucker OK: after you OK I go! OK I go! You go! OK: after you OK: after you Maria Hybinette, UGA 32 Attempt 5: Deferral ! Problems: Not really No (not deadlock) YesDeferral No (deadlock)YesLock then Check NoCheck then Lock NoNoYesStrict Alteration Bounded Waiting No Starvation No Shared Lock Variable Progress someone gets the CS Mutual Exclusion Pace limited to slowest process Maria Hybinette, UGA 33 Lessons ! We need to be able to observe the state of both processes » Lock not enough ! We most impose an order to avoid this ‘mutual courtesy’; i.e., after you-after you ! Idea: » use turn variable to avoid mutual courtesy – Indicates who has the right to insist on entering his critical section. Maria Hybinette, UGA 34 Attempt 6: Careful Turns ! Take ‘careful’ turns boolean lock[2] = {false, false} // shared int turn = 0; // shared variable void deposit( int amount ) { lock[tid] = true; while( lock[1-tid] == true ) // check other { if( turn == 1-tid ) // other turn to insist lock[tid] = false; // then I defer while( turn == 1 - tid ) {}; lock[tid] = true; } balance += amount; // critical section turn = 1 - tid; lock[tid] = false; } Maria Hybinette, UGA 35 Dekker’s Algorithm ! Mutual Exclusion: Two threads cannot be in the critical region simultaneously. Suppose they are then for each point of view: » P0 : – 1. lock[0] = true – 2. lock[1] = false » P1 : – 3. lock[1] = true – 4. lock[0] = false ! P0 enters CS no later than P1 » t2 < t4 (so P0 check lock[1] is false before entering its CS) » t2 ? t3 – after 3. lock[1] = true it remains true so t2 < t3 » So: t1 < t2 < t3 < t4 » But lock[0] cannot become false until P0 exits and we assumed that both P0 and P1 were in the CS at the same time. Thus it is impossible to have checked flag at t4. boolean lock[2] = {false, false} int turn = 0; void deposit( int amount ) { lock[tid] = true; while( lock[1-tid] == true ) { if( turn == 1-tid ) lock[tid] = false; while( turn == 1 - tid ){}; lock[tid] = true; } balance += amount; // CS turn = 1 - tid; lock[tid] = false; } Maria Hybinette, UGA 36 Attempt 6: Dekker’s Algorithm ! Take ‘careful’ turns boolean lock[2] = {false, false} // shared int turn = 0; // shared variable void deposit( int amount ) { lock[tid] = true; while( lock[1-tid] == true ) // check other { if( turn == 1-tid ) // other turn to insist lock[tid] = false; // then I defer while( turn == 1 - tid ) {}; lock[tid] = true; } balance += amount; // critical section turn = 1 - tid; lock[tid] = false; } Maria Hybinette, UGA 37 Attempt 7: Peterson’s Algorithm ! Idea: also combines turn and separate locks ! When 2 processes enters simultaneously, setting turn to the other releases the ‘other’ process from the while loop (one write will be last). ! Mutual Exclusion: Key Observation: turn cannot be both 0 and 1 at the same time boolean lock[2] = {false, false} // shared int turn = 0; // shared variable void deposit( int amount ) { lock[tid] = true; turn = 1-tid; while( lock[1-tid] == true && turn == 1-tid ) {}; balance += amount; // critical section lock[tid] = false; } Maria Hybinette, UGA 38 Peterson’s Algorithm Intuition ! Mutual exclusion: Enter critical section if and only if » Other thread does not want to enter » Other thread wants to enter, but your turn ! Progress: Both threads cannot wait forever at while() loop » Completes if other process does not want to enter » Other process (matching turn) will eventually finish ! Bounded waiting » Each process waits at most one critical section boolean lock[2] = {false, false} // shared int turn = 0; // shared variable void deposit( int amount ) { lock[tid] = true; turn = 1-tid; while( lock[1-tid] == true && turn == 1-tid ) {}; balance += amount; // critical section lock[tid] = false; } Maria Hybinette, UGA 39 Summary: Software Solutions YesYesYesPeterson YesYesYesDekker Not really No (not deadlock) YesDeferral No (deadlock)YesLock then Check NoCheck then Lock NoNoYesStrict Alteration Bounded Waiting No Starvation No Shared Lock Variable Progress someone gets the CS Mutual Exclusion Pace limited to slowest process Simpler Maria Hybinette, UGA 40 Lamport’s Bakery Algorithm ! Idea: Bakery -- each thread picks next highest ticket (may have ties) ! Enter critical section when have lowest ticket ! Data Structures (size N): » choosing[i] : true iff Pi in the entry protocol » number[i] : value of ‘ticket’, one more than max » Threads may share the same number ! Ticket is a pair: ( number[tid], i ) ! Lexicographical order: » (a, b) < (c, d) : if( a < c) or if( a == c AND b < d ) » (number[j],j) < (number[tid],tid)) Maria Hybinette, UGA 41 Bakery Algorithm choosing[tid] = true; number[tid] = max( number[0], … , number[n-1] ) + 1; choosing[tid] = false; for(j = 0; j < n; j++) { while( choosing[j] ){}; // wait until j is done choosing // wait until number[j] = 0 (not interested) or // my number is the lowest while( number[j]!= 0 && ( (number[j],j) < (number[tid],tid)) ); } balance += amount; number[tid] = 0; ! Pick next highest ticket (may have ties) ! Enter CS when my ticket is the lowest Maria Hybinette, UGA 42 Baker’s Algorithm Intuition ! Mutual exclusion: » Only enters CS if thread has smallest number ! Progress: » Entry is guaranteed, so deadlock is not possible ! Bounded waiting » Threads that re-enter CS will have a higher number than threads that are already waiting, so fairness is ensured (no starvation) choosing[tid] = true; number[tid] = max( number[0], … , number[n-1] ) + 1; choosing[tid] = false; for(j = 0; j < n; j++) while( choosing[j] ){}; // wait until j is done choosing // wait until number[j] = 0 (not interested) or me smallest number while( number[j]!= 0 && ( (number[j],j) < (number[tid],tid)) ); balance += amount; number[tid] = 0;
Docsity logo



Copyright © 2024 Ladybird Srl - Via Leonardo da Vinci 16, 10126, Torino, Italy - VAT 10816460017 - All rights reserved