School of Computing Science Simon Fraser University

CMPT 300: Operating Systems I Ch 6: Process Synchronization Dr. Mohamed Hefeeda


The Critical-Section Problem  And its hardware and software solutions


Consumer-Producer Problem
Classic example of process coordination Two processes sharing a buffer One places items into the buffer (producer) 
Must wait if the buffer is full

The other takes items from the buffer (consumer) 
Must wait if buffer is empty

Solution: Keep a counter on number of items in the buffer


Producer Process
while (true) { /* produce an item in nextProduced */ while (count == BUFFER_SIZE) ; // do nothing buffer [in] = nextProduced; in = (in + 1) % BUFFER_SIZE; count++; }

Consumer Process while (true) { while (count == 0) . // do nothing nextConsumed = buffer[out]. count--. /*consume item in nextConsumed */ } What can go wrong with this solution? 5 . out = (out + 1) % BUFFER_SIZE.

1  count = register2 Consider this execution interleaving with ´count = 5µ initially: S0: producer executes register1 = count {register1 = 5} S1: producer executes register1 = register1 + 1 {register1 = 6} S2: consumer executes register2 = count {register2 = 5} S3: consumer executes register2 = register2 .could be implemented as  register2 = count  register2 = register2 .1 {register2 = 4} S4: producer executes count = register1 {count = 6 } S5: consumer executes count = register2 {count = 4} 6 .Race Condition count++ could be implemented as  register1 = count  register1 = register1 + 1  count = register1 count-.

any method that solves the Critical-Section Problem must satisfy three requirements « 7 .Race Condition Occurs when multiple processes manipulate shared data concurrently and the result depends on the particular order of manipulation Data inconsistency may arise Solution idea  Mark code segment that manipulates shared data as critical section  If a process is executing its critical section. no other processes can execute their critical sections More formally.

Mutual Exclusion .If no process is executing in its critical section and there exist some processes that wish to enter their critical section. Progress .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 y Assumptions y Each process executes at a nonzero speed y No restriction on the relative speed of the N processes 8 . then selection of the process that will enter the critical section next cannot be postponed indefinitely 3.Critical-Section (CS) Problem 1. Bounded Waiting .If process Pi is executing in its critical section. then no other processes can be executing in their critical sections 2.

Why? ‡ Every processor has its own interrupts ‡ Disabling interrupts in all processors is inefficient Any problems with this solution even on uniprocessor systems? ‡ Users could make CS arbitrary large unresponsive system Solutions using software only Solutions using hardware support 9 .Solutions for CS Problem Disable interrupts during running CS Currently running code would execute without preemption Possible only on uniprocessor systems.

Peterson·s Solution Software solution.. no hardware support Two process solution Assume LOAD and STORE instructions are atomic (i.e. cannot be interrupted)  may not always be true in modern computers The two processes share two variables:  int turn. turn indicates whose turn it is to enter critical section The flag array indicates whether a process is ready to enter critical section  flag[i] = true ==> process Pi is ready 10 .  Boolean flag[2].

Algorithm for Process Pi while (true) { flag[i] = TRUE. Show this as an exercise. CRITICAL SECTION flag[i] = FALSE. while (flag[j] && turn == j) . 11 . turn = j. REMAINDER SECTION } Does this algorithm satisfy the three requirements? Yes.

Synchronization Hardware Many systems provide hardware support for critical section code more efficient and easier for programmers Modern machines provide special atomic (noninterruptable) hardware instructions Either test a memory word and set value Or swap contents of two memory words 12 .

return rv. *target = TRUE. } 13 .TestAndndSet Instruction Definition: boolean TestAndSet (boolean *target) { boolean rv = *target.

A process can wait indefinitely for another faster process that is accessing its CS. 14 . Check Fig 6. // remainder section } Does this algorithm satisfy the three requirements? NO. /* do nothing // critical section lock = FALSE. initialized to false while (true) { while ( TestAndSet (&lock ) ) .8 for a modified version.Solution using TestAndSet Shared boolean variable lock.

Swap Instruction Definition: void Swap (boolean *a. *a = *b. } 15 . boolean *b) { boolean temp = *a. *b = temp.

Solution using Swap Shared boolean variable lock initialized to FALSE. Each process has a local boolean variable key while (true) { key = TRUE. // critical section lock = FALSE. &key ). while ( key == TRUE) Swap (&lock. // remainder section } 16 .

Semaphore Much easier to use than hardware-based solutions Semaphore S ² integer variable Two standard operations to modify S: wait() signal() These two operations are indivisible (atomic) 17 .

we will see how to implement these operations with no busy waiting 18 . } Later. called busy waiting. } signal (S) { S++. spinlock S--.Semaphore Operations wait (S) { while (S <= 0) . // no-op.

// initialized to 1 wait (mutex).Semaphore Types and Usage Two types  Counting semaphore: can be any integer value  Binary semaphore: can be 0 or 1 (known as mutex locks) Usage examples: Mutual exclusion Semaphore mutex. Critical Section signal (mutex). 19 .

.Semaphore Types and Usage (cont·d) Process synchronization: S2 in P2 should be executed after S1 in P1 P1: S1.g. producer-consumer problem with finite buffer 20 . Control access to a resource with finite number of instances e. P2: wait (sem). signal (sem). S2.

Semaphore Implementation with no Busy Waiting Each semaphore has:  value (of type integer)  waiting queue Two operations:  block ² place the process invoking the operation in the waiting queue  wakeup ² remove one of the processes from the waiting queue and place it in the ready queue 21 .

Semaphore Implementation with no Busy Waiting wait (S) { value--. } } signal (S) { value++. if (value < 0) { add this process to waiting queue block(). } } 22 . if (value <= 0) { /*some processes are waiting*/ remove a process P from waiting queue wakeup(P).

implementation becomes the critical section problem where wait and signal code are placed in critical section. why do we not do the above in applications?  Applications may spend long (and unknown) amount of time in critical sections. and protected by  Disabling interrupts (uniprocessor systems only)  Busy waiting or spinlocks (multiprocessor systems) Well. unlike kernel which spends short and known beforehand time in critical section (~ ten instructions) 23 .Semaphore Implementation Must guarantee that no two processes can execute wait and signal on same semaphore at same time Thus.

. signal (Q). Starvation ² indefinite blocking. . . signal (Q). . signal (S). . wait (Q). .Deadlock and Starvation Deadlock ² two or more processes are waiting indefinitely for an event that can be caused by only one of the waiting processes Let S and Q be two semaphores initialized to 1 P0 P1 wait (S). signal (S). A process may never be removed from the semaphore queue in which it is suspended 24 . wait (S). wait (Q).

Classical Problems of Synchronization Bounded-Buffer (Producer-Consumer) Problem Dining-Philosophers Problem Readers-Writers Problem These problems are  abstractions that can be used to model many other resource sharing problems  used to test newly proposed synchronization schemes 25 .

Bounded-Buffer Problem N buffers. each can hold one item Semaphore mutex initialized to the value 1 Semaphore full initialized to the value 0 Semaphore empty initialized to the value N 26 .

Bounded Buffer Problem (cont·d) Structure of the producer process while (true) { // produce an item wait (empty). } 27 . signal (full). wait (mutex). // add item to buffer signal (mutex).

Bounded Buffer Problem (cont·d) Structure of the consumer process while (true) { wait (full). // consume removed item } 28 . // remove an item from buffer signal (mutex). wait (mutex). signal (empty).

a philosopher needs two chopsticks (at her left and right) Models multiple processes sharing multiple resources Write a program for each philosopher s.Dining-Philosophers Problem Philosophers alternate between eating and thinking  To eat. no starvation/deadlock occurs Solution approach:  Bowl of rice (data set)  Array of semaphores: chopstick [5] initialized to 1 29 .t.

wait ( chopstick[ (i + 1) % 5] ). // eat signal ( chopstick[i] ). signal (chopstick[ (i + 1) % 5] ).Dining-Philosophers Problem: Philosopher i While (true) { wait ( chopstick[i] ). // think } What can go wrong with this solution?  All philosophers pick their left chopsticks at same time (deadlock) Solutions?  Pick chopsticks only if both are available  Asymmetric: odd philosopher picks left chopstick first. even picks right first 30 .

Shared Data  Data set  Semaphore mutex initialized to 1  Semaphore wrt initialized to 1  Integer readcount initialized to 0 31 . they do not perform any updates  Writers ² can both read and write Problem ² allow multiple readers to read at the same time. Only one single writer can access the shared data at the same time.Readers-Writers Problem A data set is shared among a number of concurrent processes  Readers ² only read the data set.

// writing is performed signal (wrt) . } 32 .Readers-Writers Problem (cont·d) The structure of a writer process while (true) { wait (wrt) .

if (redacount == 0) signal (wrt) ...Readers-Writers Problem (cont·d) Idea of reader processes:  The first reader needs to check that there is no writer in CS  Other readers access CS right away. but they need to update the current number of readers in CS (readcount) while (true) { wait (mutex) . if (readercount == 1) wait (wrt) . readcount . signal (mutex) // reading is performed wait (mutex) . } 33 . // mutex: protects readcount readcount ++ . signal (mutex) .

but they provide higher concurrency by allowing multiples readers in CS 34 ..Readers-Writers Problem (cont·d) Some systems implement reader-writer locks  E. Solaris. Linux. Pthreads API  A process can ask for a reader-write lock either in read or write mode When would you use reader-writer locks?  Applications where it is easy to identify readers only and writers only processes  Applications with more readers than writers Tradeoff: cost vs.g. concurrency  Reader-writer locks require more overhead to establish than semaphores.

Be Careful When Using Semaphores Some common programming problems «  signal (mutex) «. wait (mutex) ‡ Multiple processes can access CS at the same time  wait (mutex) « wait (mutex) ‡ Processes may block for ever  Forgetting wait (mutex) or signal (mutex) 35 .

Monitors Monitor: High-level abstraction that provides a convenient and effective mechanism for process synchronization  Compiler (not programmer) takes care of mutual exculsion Only one process may be active within the monitor at a time monitor monitor_name { //shared variable declarations procedure P1 («) { «.) { « } } 36 . } « procedure Pn («) {««} Initialization code ( «.

Schematic View of a Monitor 37 .

Two operations on a condition variable:  x. y.signal () ² resumes one of processes (if any) that invoked x.Condition Variables condition x. signal has no effect  semaphores: signal always increments semaphore's value Condition variables are usually used in monitors to provide a way to suspend/awake processes 38 .wait () What is the difference between condition variables and semaphores?  condition variable: if no process is suspended.  x.wait () ² a process that invokes the operation is suspended.

Monitor with Condition Variables 39 .

Solution to Dining Philosophers monitor DP { enum {THINKING. test(i). // test left and right neighbors test((i + 4) % 5). } 40 . EATING} state [5] . } void putdown (int i) { state[i] = THINKING. //check both chopsticks if (state[i] != EATING) self [i].wait. HUNGRY. test((i + 1) % 5). condition self [5]. void pickup (int i) { state[i] = HUNGRY.

Solution to Dining Philosophers (cont·d) void test (int i) { if ( (state[i] == HUNGRY) && (state[(i + 4) % 5] != EATING) && (state[(i + 1) % 5] != EATING) ) { state[i] = EATING . self[i].signal () . i < 5. } } // end monitor 41 . i++) state[i] = THINKING. } } initialization_code() { for (int i = 0.

putdown (i) 42 .pickup (i) EAT dp.Solution to Dining Philosophers (cont·d) Each philosopher invokes the operations pickup() and putdown() in the following sequence: dp.

mutex locks.. «  In java. public synchronized void insert(«) { «} public synchronized void remove(«) { «} «. } Java guarantees that once a thread starts executing a synchronized method.Monitors Implementation It is up to the compiler to ensure mutual exclusion in monitors  Semaphores are usually used Languages like Java.5 has semaphores. condition variables.concurrent package Exercise: write a java solution for the Producer-Consumer problem 43 .util. C# (not C).. no other thread can execute any other synchronized method in the class Java 1. and Concurrent Pascal provide monitors-like mechanisms Java public class SimpleClass { ..

Synchronization Examples Windows XP Linux Pthreads 44 .

or events (condition variables) 45 . semaphores. which can act as mutexes.Windows XP Synchronization Masks interrupts to protect access to global resources on uniprocessor systems (inside kernel) Uses spinlocks on multiprocessor systems Also provides dispatcher objects for thread synchronization outside kernel.

Linux Synchronization Linux:  disables interrupts to implement short critical sections (on single processor systems) Linux provides:  semaphores  Spinlocks (on SMP)  Reader-writer locks 46 .

sem_post(&sem). pthread_mutex_init(&mutex. 47 . null). sem_wait(&sem). sem_init(&sem. pthread_mutex_lock(&mutex). 5). 0. pthread_mutex_unlock(&mutex).Pthreads Synchronization Pthreads API is OSindependent It provides:  mutex locks  condition variables #include <pthread.h> sem_t sem. extensions include:  semaphores  read-write locks  spin locks  May not be portable #include <semaphore.h> pthread_mutex_t mutex.

signal() must be atomic moves the CS problem to kernel  Monitors: high-level constructs (compiler) Some classical synchronization problems 48 .Summary Processor Synchronization  Techniques to coordinate access to shared data Race condition  Multiple processes manipulating shared data and result depends on execution order Critical section problem  Three requirements: mutual exclusion. Swap() ‡ Busy waiting (or spinlocks)  Semaphores: ‡ wait(). bounded waiting  Software solution: Peterson·s Algorithm  Hardware support: TestAndSet(). progress.

Sign up to vote on this title
UsefulNot useful