430 likes | 445 Views
Process Synchronization. Chapter 8. Background. In a multi-programmed OS, processes/threads often need to share resources: printers, files, data in memory, etc. Concurrent access to shared resources may result in inconsistent/improper operation.
E N D
Process Synchronization Chapter 8 A. Berrached:CMS:UHD
Background • In a multi-programmed OS, processes/threads often need to share resources: printers, files, data in memory, etc. • Concurrent access to shared resources may result in inconsistent/improper operation. • OS must provide mechanisms to ensure orderly execution of cooperating processes A. Berrached:CMS:UHD
Example • An application with two processes P1 and P2 that share data. shared float balance; ---------------- Process P1: balance = balance + amount1 --------------- Process P2: balance = balance - amount2 A. Berrached:CMS:UHD
Example-Cont. Process P1: Process P2: a1: LOAD R1, balance b1: MOV R2, amount1 c1: ADD R1, R2 d1: STORE R1, balance a2: LOAD R1, balance b2: MOV R2, amount2 c2: SUB R1, R2 d2: STORE R1, balance • Assume initial values: balance = 100, amount1= 20 and amount2 = 50. • What is the expected balance after P1 and P2 are executed? • What if the processor executes the following sequence: • a1, b1, a2, b2, c2, d2, c1, d1 A. Berrached:CMS:UHD
Critical Section Problem A. Berrached:CMS:UHD
Example--Cont. • In the previous example • In P1, the statement balance = balance + amount1 is a critical section • In P2, the statement balance = balance - amount2 is a critical section A. Berrached:CMS:UHD
Solution to Critical Section Problem 1. Mutual Exclusion: at most one process is in its critical section at any time. 2. Progress: If no process is executing its critical section, a process that wishes to enter can get in. Only those processes that are not in the remainder section can participate in the decision to determine which process enters its critical section next. 3. Bounded Waiting: No process is postponed indefinitely. There must be a bound on the number of times that other process are allowed to get in after a process has made a request to get in. A. Berrached:CMS:UHD
Initial Attempt • Two processes: P0 and P1 • The general structure for each process Pi : repeat Entry section critical section exit section remainder section until false; A. Berrached:CMS:UHD
Disabling Interrupts to Implement the Critical Section repeat disableInterrupts(); Critical Section enableInterrupts(); remainder Section until flase; Process P1: Process P0: repeat disableInterrupts(); Critical Section enableInterrupts(); remainder Section until flase; A. Berrached:CMS:UHD
Disabling Interrupts to Implement the Critical Section float amt0; .... disableInterrupts(); balance = balance + amt0 enableInterrupts(); shared float balance; Process P1: Process P0: float amt1; …... disableInterrupts(); balance = balance - amt1 enableInterrupts(); A. Berrached:CMS:UHD
Algorithm 0 float amt0; …… while (lock ==TRUE) ; lock = TRUE; balance = balance + amt0; lock = FALSE; Shared boolean lock = FALSE; shared float balance; Process P0: Process P1: float amt1 ……. while (lock ==TRUE) ; lock = TRUE; balance = balance + amt1; lock = FALSE; A. Berrached:CMS:UHD
Algorithm 1 shared boolean turn = 0 // turn is either 0 or 1 Process P0: Process P1: Repeat while (turn == 1) ; Critical Section turn = 1; Remainder Section until flase; Repeat while (turn == 0) ; Critical Section turn = 0; Remainder Section until flase; A. Berrached:CMS:UHD
Algorithm 1 shared boolean turn = 0 // turn is either 0or 1 Process Pi: repeat while (turn == j) ; Critical Section turn = j; Remainder Section until flase; • Satisfies mutual exclusion • does not satisfy the progress requirement: the two processes must alternate trough the Critical section. A. Berrached:CMS:UHD
Algorithm 2 Shared boolean Flag[0..1] = {false, false} Process Pi: repeat Flag[i] = true; while (Flag[j] == true) ; Critical Section Flag[i] = false; Remainder Section until flase; • Flag[i] = true ==> process want to get into critical section A. Berrached:CMS:UHD
Algorithm 3 Shared boolean Flag[0..1] = {false, false} boolean turn = 0; Process Pi: repeat Flag[i] = true; turn = j; while (Flag[j] and turn==j) ; Critical Section Flag[i] = false; Remainder Section until flase; • Turn = i ==> process i can enter its critical section • Flag[i] = true ==> process want to get into critical section • Solves the critical section problem for two processes A. Berrached:CMS:UHD
Mutual Exclusion with Test & Set • The test & set instruction is a machine level instruction that tests and sets a variable atomically. The instruction can be defined as follows: boolean test_and_set (boolean * target) {// sets target to True and returns its old value boolean OldValue; OldValue = *target; *target = True; return OldValue; } A. Berrached:CMS:UHD
Example boolean X = False; boolean temp; temp = test_and_set(& X); What are the values of temp and X ? • Temp = False • X = True A. Berrached:CMS:UHD
Mutual Exclusion with Test & Set • The main characteristic of the Test&Set instruction is that it is executed atomically--I.e. as one un-interruptable instruction. • Thus if two Test&Set instructions are executed simultaneously (each on a different CPU), they will be executed sequentially in some arbitrary order. A. Berrached:CMS:UHD
How Test & Set is used for Mutual Exclusion shared boolean lock = False; …… while ( Test&Set(&lock) == True ) { NULL}; // spin lock < Critical Section> lock = FALSE; // atomic <remainder section> • Satisfies Mutual Exclusion condition • Does not satisfy bounded waiting condition • While a process is in its critical section , all other processes which want to execute their critical sections continuously execute the while loop ==> waist of computing power. A. Berrached:CMS:UHD
Semaphores • A semaphore is a synchronization mechanism that does not require busy waiting. • A semaphore is an integer that can only be accessed through one of two atomic operations: wait() and signal(). • Wait(S) • { • while (S<= 0) • {NULL} ; • S = S -1; • } Signal(S) { S = S +1; } A. Berrached:CMS:UHD
Example: Critical Section for n Processes shared semaphore Mutex=1; …… wait(Mutex) <critical section> signal(Mutex); <remainder section> • Does not satisfy bounded waiting condition • Still has busy waiting A. Berrached:CMS:UHD
Semaphores as General Synchronization Tools A. Berrached:CMS:UHD
Blocking/Active Semaphore class semaphore { private: int value; L is a list of process Ids // L may be organized as a FIFO list public: initialize( InitialValue) { value = InitialValue; L is an empty list; } // CONTINUE ON NEXT SLIDE A. Berrached:CMS:UHD
Blocking/Active Semaphore (Cont.) wait( ) { value = value -1; if ( value < 0) { add the PID of this process to L; // L may be organized as a FIFO queue block this process; } } // CONTINUE ON NEXT SLIDE A. Berrached:CMS:UHD
Blocking/Active Semaphore (Cont.) signal ( ) { value = value + 1; if (value <= 0) { remove a process P from L; // may be done on a // FCFS basis wakeup(P); } } } // end of class semaphore A. Berrached:CMS:UHD
Producer-Consumer Problem • A Producer process/thread produces data items that are consumed by another process/thread (the Consumer). • Each item produced by the producer needs to be consumed by the consumer. • Shared memory is used to have the producer pass data items to consumer A. Berrached:CMS:UHD
Producer-Consumer Problem • Assume threads use one shared variable X Shared itemType X; producer() { Repeat …. Compute next item NextP; …. X = NextP; … until false consumer() { Repeat …. NextC = X; // Consume …. Use NextC ...; … until false A. Berrached:CMS:UHD
Producer-Consumer Problem • Assume threads use one shared variable X Shared itemType X; Shared semaphore P = 0; producer() { Repeat …. Compute next item NextP; …. X = NextP; signal(P); … until false consumer() { Repeat …. wait(P); NextC = X; // Consume …. Use NextC ...; … until false A. Berrached:CMS:UHD
Producer-Consumer Problem • Assume threads use one shared variable X Shared itemType X; Shared semaphore P = 0, C = 1; producer() { Repeat …. Compute next item NextP; …. wait(C); X = NextP; signal(P); … until false consumer() { Repeat …. wait(P); NextC = X; // Consume signal(C); …. Use NextC ...; … until false A. Berrached:CMS:UHD
Producer-Consumer Problem • Assume threads use a buffer of size N Shared itemType buff[N]; producer() { int in = 0; Repeat …. Compute next item NextP; …. Buff[in] = NextP; in = (in+1) % N; … until false consumer() { int out= 0; Repeat …. NextC =buff[out]; // Consume out = (out+1) % N; …. Use NextC ...; … until false A. Berrached:CMS:UHD
Producer-Consumer Problem • Previous solution does not prevent consumer from consuming from empty buffer • Does not prevent producer from inserting a new item into a full buffer. A. Berrached:CMS:UHD
Producer-Consumer Problem • Assume threads use a buffer of size N Shared itemType buff[N]; int counter=0; producer() { int in = 0; Repeat …. Compute next item NextP; …. while (counter >=N) NULL ; Buff[in] = NextP; in = (in+1) % N; ++counter; … until false consumer() { int out= 0; Repeat …. while (counter <=0) NULL; NextC =buff[out]; // Consume out = (out+1) % N; --counter; …. Use NextC ...; … until false A. Berrached:CMS:UHD
Producer-Consumer Problem Critic of Previous Solution: • race condition may occur on access to shared variable counter • If one producer & one consumer, access to shared buff does not cause any race conditions (why ?) • If multiple producers & consumers, access to shared buff may cause race condition. A. Berrached:CMS:UHD
1 Producer & 1 Consumer Shared semaphore full_slots=0, empty_slots=N; Shared itemType buff[N]; producer() { int in = 0; Repeat …. Compute next item NextP; …. wait(empty_slots); Buff[in] = NextP; in = (in+1) % N; signal(full_slots); … until false consumer() { int out= 0; Repeat …. wait(full_slots); NextC =buff[out]; // Consume out = (out+1) % N; signal(empty_slots); …. Use NextC ...; … until false A. Berrached:CMS:UHD
Multiple Producers & Consumers Shared semaphore full_slots=0, empty_slots=N, Cmutex, Pmutex=1; Shared itemType buff[N]; producer() { int in = 0; Repeat …. Compute next item NextP; …. wait(empty_slots); wait(Pmutex); Buff[in] = NextP; in = (in+1) % N; signal(Pmutex); signal(full_slots); … until false consumer() { int out= 0; Repeat …. wait(full_slots); wait(Cmutex); NextC =buff[out]; // Consume out = (out+1) % N; signal(Cmutex); signal(empty_slots); …. Use NextC ...; … until false A. Berrached:CMS:UHD
Reader-Writer Problem • Suppose a resource is to be shared among a community of processes of two types: readers & writers. • A reader process can share the resource with any number of other readers but not with a writer • A writer must have exclusive access to the resource A. Berrached:CMS:UHD
Readers First Solution Algorithm ideas: • no reader should wait unless a writer is using the resource • as long as a reader is using the resource, a writer who wishes to use the resource must wait • 1st reader must check to make sure no writer is using the resource • all subsequent readers do not have to wait provided at least one process is reading A. Berrached:CMS:UHD
Readers First Solution Cont. Shared semaphore WriterBlock = 1, Mutex=1; shared int readersCount = 0; Writer( ) { while (true) { <other stuff> wait(WriterBlock); <writing is performed> signal(WriterBlock); …. } } A. Berrached:CMS:UHD
Readers First Solution cont. reader( ) { while (true) { <other stuff> wait(Mutex); readersCount ++; if (readersCount == 1) wait(WriterBlock); signal(Mutex); <reading is performed> wait(Mutex); readersCount--; if (readersCount == 0) signal(WriterBlock); signal(Mutex); } } A. Berrached:CMS:UHD
Dining-Philosophers Problem • Five philosophers sitting at a table. Each has bowl of rice in front of him/her. • There are five chopsticks, two at left and right of each philosopher, as shown above. • A philosopher’s life consists of thinking and eating. • A philosopher needs both left and right chopsticks to be able to eat. • A chopstick can be used by only one philosopher at a time. A. Berrached:CMS:UHD
Dining-Philosophers Problem • There are five philosopher processes numbered 0 through 4. Between each pair of philosophers is a chopstick. The chopsticks are also numbered 0 through 4, so that CStickiis between philosophers i and i-1 (all arithmetic on Cstick numbers and philosopher numbers is modulo 5 so CStick 0 is between philosophers 4 and 0, and Cstick 1 is between philo. 0 and 1). A. Berrached:CMS:UHD
Dining-Philosophers Problem Semaphore CStrick[5] (all initialized to 1) Philosopher i: while (true) { THINK(); wait(CStick[i]); // pick left chop stick wait(CStick[(i+1)%5]; // pick right chop stick EAT(); signal(CStick[i]); signal(CStick[(i+1)%5]); } • Algorithm has the potential of deadlock A. Berrached:CMS:UHD
Dining-Philosophers Problem Semaphore CStrick[5] (all initialized to 1) Philosopher i: while (true) { THINK( ); if (i%2 == 0){ // if even numbered wait(CStick[i]); // pick left chop stick wait(CStick[(i+1)%5]; // pick right chop stick } else {// if odd numbered wait(CStick[(i+1)%5]; // pick right chop stick wait(CStick[i]); // pick left chop stick } EAT( ); signal(CStick[i]); signal(CStick[(i+1)%5]); } A. Berrached:CMS:UHD