Outline • Basic Synchronization Principles Interacting Processes • Independent process – Cannot affect or be affected by the other processes in the system – Does not share any data with other processes • Interacting process – Can affect or be affected by the other processes – Shares data with other processes – We focus on interacting processes through physically or logically shared memory 5/29/2016 COP4610 2 Bounded-Buffer 5/29/2016 COP4610 3 Bounded-Buffer – cont. • Shared data typedef struct { ...... } item; item buffer[n]; int in, out, counter; in =0; out=0; counter = 0; 5/29/2016 COP4610 4 Bounded Buffer – cont. • Producer process repeat … produce an item in nextp … while counter == n do no-op; buffer [in] = nextp; in = (in + 1) % n; counter ++; until false; 5/29/2016 COP4610 5 Bounded-Buffer - cont. • Consumer process repeat while counter == 0 do no-op; nextc = buffer [out]; out = (out + 1) % n; counter--; … consume the item in nextc … until false; 5/29/2016 COP4610 6 Bounded-Buffer - cont. • If we let producer and consumer processes run concurrently, we may have wrong result – Note the simple-thread program – Each thread is working properly – However, the total balance is not kept 5/29/2016 COP4610 7 Bounded-Buffer - cont. • Suppose we have one producer and one consumer, the variable counter is 5 – Producer: counter = counter +1 P1: load counter, r1 P2: add r1, #1, r2 P3: store r2, counter – Consumer: counter = counter - 1 C1: load counter, r1 C2: add r1, #-1, r2 C3: store r2, counter 5/29/2016 COP4610 8 Bounded-Buffer - cont. • A particular execution sequence – P1: load counter, r1 – P2: add r1, #1, r2 --- Context switch ---– C1: load counter, r1 – C2: add r1, #-1, r2 – C3: store r2, counter --- Context switch ---– P3: store r2, counter – What is the value of counter? 5/29/2016 COP4610 9 Bounded-Buffer - cont. • A particular execution sequence – C1: load counter, r1 – C2: add r1, #-1, r2 --- Context switch ---– P1: load counter, r1 – P2: add r1, #1, r2 – P3: store r2, counter --- Context switch ---– C3: store r2, counter – What is the value of counter this time? 5/29/2016 COP4610 10 Bounded-Buffer - cont. • A particular execution sequence – C1: load counter, r1 – C2: add r1, #-1, r2 – C3: store r2, counter --- Context switch ---– P1: load counter, r1 – P2: add r1, #1, r2 – P3: store r2, counter --- Context switch ---– What is the value of counter this time? 5/29/2016 COP4610 11 Race Condition • Race condition – When several processes access and manipulate the same data concurrently, there is a race among the processes – The outcome of the execution depends on the particular order in which the access takes place – This is called a race condition 5/29/2016 COP4610 12 Traffic Intersections 5/29/2016 COP4610 13 Race condition updating a variable 5/29/2016 COP4610 14 Race condition timing chart 5/29/2016 COP4610 15 Updating A Shared Variable shared double balance; Code for p1 Code for p2 . . . balance = balance + amount; . . . . . . balance = balance - amount; . . . balance+=amount balance-=amount balance 5/29/2016 COP4610 16 Updating A Shared Variable – cont. Execution of p1 … load R1, balance load R2, amount Execution of p2 Timer interrupt … load load sub store … R1, R2, R1, R1, balance amount R2 balance Timer interrupt add R1, R2 store R1, balance … 5/29/2016 COP4610 17 Simultaneous editing of a file 5/29/2016 COP4610 18 Race condition Order 1 edit-a write-a Order 2 Order 3 edit-a edit-a edit-b edit-b write-a write b Order 4 write-b write-a Order 5 edit-b write-b edit-a edit-a write-a 5/29/2016 edit-b write-b Order 6 edit-b edit-b edit-a write-b write-a write-a write-b COP4610 19 The Critical-Section Problem • n processes all competing to use some shared data • Each process has code segments, called critical section, in which the shared data is accessed. • Problem – ensure that when one process is executing in its critical section, no other process is allowed to execute in its critical section, called mutual exclusion 5/29/2016 COP4610 20 The Critical-Section Problem – cont. • Structure of process Pi repeat entry section critical section exit section reminder section until false; 5/29/2016 COP4610 21 Requirements for Critical-Section Solutions • Mutual Exclusion. – If process Pi is executing in its critical section, then no other processes can be executing in their critical sections. • Progress – If no process is executing in its critical section and there exist some processes that wish to enter their critical section, then the selection of the processes that will enter the critical section next cannot be postponed indefinitely. • Bounded Waiting – A bound must exist on the number of times that other processes are allowed to enter their critical sections after a process has made a request to enter its critical section and before that request is granted. 5/29/2016 COP4610 22 Solution through Disabling Interrupts • In a uni-processor system, an interrupt causes the race condition – The scheduler can be called in the interrupt handler, resulting in context switch and data inconsistency 5/29/2016 COP4610 23 Solution through Disabling Interrupts – cont. • Process Pi repeat disableInterrupts(); //entry section critical section enableInterrupts(); //exit section reminder section until false; 5/29/2016 COP4610 24 Solution through Disabling Interrupts – cont. 5/29/2016 COP4610 25 Solution through Disabling Interrupts – cont. • This solution may affect the behavior of the I/O system – Interrupts can be disabled for an arbitrarily long time • The interrupts can be disabled permanently if the program contains an infinite loop in its critical section – User programs are not allowed to enable and disable interrupts directly • However, if the operating system can provide system calls, a user can use the system calls for synchronization – Called semaphores and related system calls 5/29/2016 COP4610 26 Software Attempt to Solve the Problem • Only 2 processes, P1 and P2 • General structure of process Pi (other process Pj) repeat entry section critical section exit section reminder section until false; • Processes may share some common variables to synchronize their actions. 5/29/2016 COP4610 27 Algorithm 1 • Shared variables: – var turn: (0..1); initially turn = 0 – turn - i Pi can enter its critical section • Process Pi repeat while turn i do no-op; critical section turn := j; reminder section until false; • Satisfies mutual exclusion, but not progress 5/29/2016 COP4610 28 Algorithm 2 • Shared variables – var flag: array [0..1] of boolean; initially flag [0] = flag [1] = false. – flag [i] = true Pi ready to enter its critical section • Process Pi repeat flag[i] := true; while flag[j] do no-op; critical section flag [i] := false; remainder section until false; • Satisfies mutual exclusion, but not progress requirement. 5/29/2016 COP4610 29 Algorithm 3 • Combined shared variables of algorithms 1 and 2. • Process Pi repeat flag [i] := true; turn := j; while (flag [j] and turn = j) do no-op; critical section flag [i] := false; remainder section until false; • Meets all three requirements; solves the critical-section problem for two processes. 5/29/2016 COP4610 30 Bakery Algorithm Critical section for n processes • Before entering its critical section, process receives a number. Holder of the smallest number enters the critical section. • If processes Pi and Pj receive the same number, if i < j, then Pi is served first; else Pj is served first. • The numbering scheme always generates numbers in increasing order of enumeration; i.e., 1,2,3,3,3,3,4,5... 5/29/2016 COP4610 31 Bakery Algorithm – cont. • Notation < lexicographical order (ticket #, process id #) – (a,b) < c,d) if a < c or if a = c and b < d – max (a0,…, an-1) is a number, k, such that k ai for i - 0, …, n – 1 • Shared data var choosing: array [0..n – 1] of boolean; number: array [0..n – 1] of integer, Data structures are initialized to false and 0 respectively 5/29/2016 COP4610 32 Bakery Algorithm (Cont.) repeat choosing[i] := true; number[i] := max(number[0], number[1], …, number [n – 1])+1; choosing[i] := false; for j := 0 to n – 1 do begin while choosing[j] do no-op; while number[j] 0 and (number[j],j) < (number[i], i) do no-op; end; critical section number[i] := 0; remainder section until false; 5/29/2016 COP4610 33 Algorithm • Shared variables: – boolean lock; initially lock = FALSE – lock is FALSE Pi can enter its critical section • Process P1 Process P2 repeat while (lock) do no-op; lock = TRUE; critical section lock = FALSE; reminder section until false; repeat while (lock) do no-op; lock = TRUE; critical section lock = FALSE reminder section until false; 5/29/2016 COP4610 34 Busy Wait Condition shared boolean lock = FALSE; shared double balance; Code for p1 Code for p2 COP4610 Interrupt lock = FALSE Interrupt Interrupt 5/29/2016 lock = TRUE p2 p1 /* Acquire the lock */ while(lock) ; lock = TRUE; /* Execute critical sect */ balance = balance - amount; /* Release lock */ lock = FALSE; Blocked at while /* Acquire the lock */ while(lock) ; lock = TRUE; /* Execute critical sect */ balance = balance + amount; /* Release lock */ lock = FALSE; 35 Synchronization Hardware • Test and modify the content of a word atomically (indivisibly) – The procedure cannot be interrupted until it has completed the routine – Implemented as a test-and-set instruction boolean Test-and-Set (boolean target) { boolean tmp tmp = target; target = true; return tmp; } 5/29/2016 COP4610 36 Mutual Exclusion with Test-and-Set • Shared data: boolean lock ; – Initially false • Process Pi repeat while Test-and-Set (lock) do no-op; critical section lock = false; remainder section until false; 5/29/2016 COP4610 37 Semaphores • Semaphore S – integer variable • can only be accessed via two indivisible (atomic) operations wait (S): while S 0 do no-op; S := S – 1; signal (S): S := S + 1; 5/29/2016 COP4610 38 Example: Critical Section of n Processes • Shared variables – var mutex : semaphore – initially mutex = 1 • Process Pi repeat wait(mutex); critical section signal(mutex); remainder section until false; 5/29/2016 COP4610 39 Shared Account Balance Problem Proc_0() { . . . /* Enter the CS */ P(mutex); balance += amount; V(mutex); . . . } proc_1() { . . . /* Enter the CS */ P(mutex); balance -= amount; V(mutex); . . . } semaphore mutex = 1; fork(proc_0, 0); fork(proc_1, 0); 5/29/2016 COP4610 40 Sharing Two Variables proc_A() { while(TRUE) { <compute section A1>; update(x); /* Signal proc_B */ V(s1); <compute section A2>; /* Wait for proc_B */ P(s2); retrieve(y); } } proc_B() { while(TRUE) { /* Wait for proc_A */ P(s1); retrieve(x); <compute section B1>; update(y); /* Signal proc_A */ V(s2); <compute section B2>; } } semaphore s1 = 0; semaphore s2 = 0; fork(proc_A, 0); fork(proc_B, 0); 5/29/2016 COP4610 41