Module 7: Process Synchronization

advertisement
Chapter 5: Process
Synchronization
Rev. by Kyungeun Park, 2015
Operating System Concepts Essentials – 8th Edition
Silberschatz, Galvin and Gagne ©2011
Chapter 5 : Process Synchronization










Background
The Critical-Section Problem
Peterson’s Solution
Synchronization Hardware
Mutex Locks
Semaphores
Classic Problems of Synchronization
Monitors
Synchronization Examples
Alternative Approaches
Operating System Concepts Essentials – 8th Edition
6.2
Silberschatz, Galvin and Gagne ©2011
Objectives

To introduce the critical-section problem, whose solutions can be used to
ensure the consistency of shared data

To present both software and hardware solutions of the critical-section problem

To examine several critical process-synchronization problems

To explore several tools that are used to solve process synchronization
problems
Operating System Concepts Essentials – 8th Edition
6.3
Silberschatz, Galvin and Gagne ©2011
Background

Processes can execute concurrently

May be interrupted at any time, partially completing execution

Concurrent access of cooperating processes or threads to shared data may
result in data inconsistency.

Maintaining data consistency requires mechanisms to ensure the orderly
execution of cooperating processes.

Illustration of the problem:

Suppose that we wanted to provide a solution to the consumer-producer
problem that fills all the buffers.

We can do so by having an integer count that keeps track of the number
of full buffers.

Initially, count is set to 0. It is incremented by the producer after it
produces a new buffer and is decremented by the consumer after it
consumes a buffer.
Operating System Concepts Essentials – 8th Edition
6.4
Silberschatz, Galvin and Gagne ©2011
Bounded-Buffer –
Shared-Memory Solution

How concurrent or parallel execution affects the integrity of data shared by
several processes?

Shared buffer: a circular array with two logical pointers: in and out
#define BUFFER_SIZE 10
typedef struct {
...
} item;
item buffer[BUFFER_SIZE];
int in = 0; /* the next free position in the buffer */
int out = 0; /* the first full position in the buffer */
in
Initial Empty Buffer (size 10)
0
1
2
9
out
Operating System Concepts Essentials – 8th Edition
6.5
Silberschatz, Galvin and Gagne ©2011
Producer
while (true) {
/* Produce an item and put in nextProduced */
while (counter == BUFFER_SIZE)
; // do nothing
buffer [in] = nextProduced;
in = (in + 1) % BUFFER_SIZE;
counter++;
}
* counter++ could be implemented in machine language as
register1 = counter
register1 = register1 + 1
counter = register1
Operating System Concepts Essentials – 8th Edition
6.6
Silberschatz, Galvin and Gagne ©2011
Consumer
while (true) {
while (counter == 0)
; // do nothing
nextConsumed = buffer[out];
out = (out + 1) % BUFFER_SIZE;
counter--;
/* Consume the item in nextConsumed */
}
* counter-- could be implemented in machine language as
register2 = counter
register2 = register2 - 1
count = register2
Operating System Concepts Essentials – 8th Edition
6.7
Silberschatz, Galvin and Gagne ©2011
Race Condition

Both the producer and consumer routines may not function correctly when executed
concurrently.

Consider this execution interleaving with “count = 5” initially:
S0: producer execute register1 = counter
{register1 = 5}
S1: producer execute register1 = register1 + 1 {register1 = 6}
S2: consumer execute register2 = counter
{register2 = 5}
S3: consumer execute register2 = register2 - 1 {register2 = 4}

S4: producer execute counter = register1
{counter = 6 }
S5: consumer execute counter = register2
{counter = 4}
Race Condition : a situation where several processes access and manipulate the
same data concurrently and the outcome of the execution depends on the particular
order in which the access takes place.

Ensure that only one process at a time can manipulate the variable counter.
 Process synchronization and coordination among cooperating processes
Operating System Concepts Essentials – 8th Edition
6.8
Silberschatz, Galvin and Gagne ©2011
Critical Section Problem

Consider system of n processes {p0, p1, … pn-1}

Each process has a segment of code, critical section, where

Process may be changing common variables, updating a table, writing a file, etc.

When one process is executing in critical section, no other process is allowed to
execute in its critical section.

Critical section problem is to design a protocol that the processes can use to
cooperate.

Each process must ask permission to enter its critical section in the entry section.

Followed by an exit section, then remainder section.

Kernel code  cause race conditions
Ex) a list of all open files maintained by an operating system.
data structures for maintaining memory allocation and process lists or
for handling interrupts
Operating System Concepts Essentials – 8th Edition
6.9
Silberschatz, Galvin and Gagne ©2011
Critical Section

General structure of process pi is
do {
entry section
critical section
exit section
remainder section
} while (TRUE)
Operating System Concepts Essentials – 8th Edition
6.10
Silberschatz, Galvin and Gagne ©2011
Solution to Critical-Section Problem (1)
 Three requirements:
1. Mutual Exclusion - If process Pi is executing in its critical section, then no
other processes can be executing in their critical sections.
2. Progress - If no process is executing in its critical section and there exist some
processes that wish to enter their critical section, then only those processes
that are not executing in their remainder sections can participate in deciding
which will enter its critical section next, and this selection cannot be postponed
indefinitely.
3. Bounded Waiting - There exists a bound, or limit 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.
Note
 Assume that each process executes at a nonzero speed
 No assumption concerning relative speed of the n processes
Operating System Concepts Essentials – 8th Edition
6.11
Silberschatz, Galvin and Gagne ©2011
Solution to Critical-Section Problem (2)

Two general approaches used to handle critical sections in operating systems

Preemptive kernel – allows preemption of process when running in kernel
mode
 Ex) two kernel-mode processes running simultaneously on different
processors in SMP environment

Non-preemptive kernel – a process runs until it exits kernel mode,
blocks, or voluntarily yields CPU
Essentially free from race conditions on kernel data structures

Then why preemptive kernel over non-preemptive one?
 preemptive kernel : complicated, but more responsive and more
suitable for real-time programming allowing a real-time process to
preempt a process currently running in the kernel
Operating System Concepts Essentials – 8th Edition
6.12
Silberschatz, Galvin and Gagne ©2011
Peterson’s Solution

Peterson’s solution: a classic software-based solution to the critical-section
problem


Worth reviewing the underlying algorithm to solve the critical section problem
and the way of reasoning how to satisfy three requirements
Restricted to two processes, P0 and P1, that alternate execution between their
critical sections and remainder sections
Operating System Concepts Essentials – 8th Edition
6.13
Silberschatz, Galvin and Gagne ©2011
Algorithm for Process Pi
do {
flag[i] = true;
turn = j;
while (flag[j] && turn == j);
critical section
flag[i] = false;
remainder section
} while (TRUE);
do {
flag[j] = true;
turn = i;
while (flag[i] && turn == i);
critical section
flag[j] = false;
remainder section
} while (TRUE);
* at Process Pi

The two processes share two data items:



int turn;
boolean flag[2]
The flag array is used to indicate if a process is ready to enter the critical section.


* at Process Pj
flag[i] = true implies that process Pi is ready!
The variable turn indicates whose turn it is to enter the critical section


if both processes try to enter at the same time, turn will be set to both i and j at roughly the same time
 only one of these assignments will last
the value of turn determines which of the two processes is allowed to enter its critical section first
Operating System Concepts Essentials – 8th Edition
6.14
Silberschatz, Galvin and Gagne ©2011
Algorithm for Process Pi
do {
do {
flag[i] = true;
turn = j;
while (flag[j] && turn == j);
critical section
flag[i] = false;
remainder section
} while (TRUE);
turn
would be 0 or 1
* at Process Pi
flag[j] = true;
turn = i;
while (flag[i] && turn == i);
critical section
flag[j] = false;
remainder section
} while (TRUE);
* at Process Pj

Prove: assume both processes executes in their critical sections at the same time
1.
Mutual exclusion is preserved:
When flag[j]=false or turn==i, each Pi enters its critical section.
To exit while loop and enter their critical sections, as flag[i]=true and flag[j]=true (insufficient)
 So the value of turn should be 0 for P0 and 1 for P1 at the same time : impossible!
2.
Progress requirement is satisfied:
Bounded-waiting requirement is met:
Pi can be prevented from entering the CS only if it is stuck in the while loop
If Pj is not ready to enter the critical section, then flag[j]=false and Pi can enter its CS
If Pj has set flag[j] to true and is also executing in its while loop, then either turn==i or turn==j.
 If turn==i then Pi will enter the CS: If turn==j then Pj will enter the CS.
If Pj exits its CS, it will reset flag[j] to false, allowing Pi to enter its CS.
 If Pj resets flag[j] to true immediately, it must also set turn to i. Since no change on turn in Pi
3.
 Pi will enter its CS (Progress) after at most one entry by Pj (bounded waiting).
Operating System Concepts Essentials – 8th Edition
6.15
Silberschatz, Galvin and Gagne ©2011
Synchronization Hardware

Many systems provide hardware support for critical section code

All solutions (from hardware to software-based APIs) based on idea of locking


Uniprocessors – could disable interrupts while modifying a shared variable




Protecting critical regions through the use of locks
Currently running code would execute without preemption
No other instructions would be run, so no unexpected modifications to the shared variables
Generally too inefficient on multiprocessor environments
 Disabling interrupt for all processors by sending the message: causes time consuming and
delays
Modern machines provide special atomic hardware instructions



Atomic : non-interruptable, uninterruptible
Allow us either test memory word and set the value : TestAndSet( ) instruction
Or swap contents of two memory words : CompareAndSwap( ) instruction
Operating System Concepts Essentials – 8th Edition
6.16
Silberschatz, Galvin and Gagne ©2011
TestAndSet() Instruction

Definition: run atomically as an uninterruptible instruction

if two instructions are executed simultaneously on a different CPU, they
will be executed sequentially in some order
boolean TestAndSet (boolean *target)
{
boolean rv = *target;
*target = TRUE;
return rv:
}
Operating System Concepts Essentials – 8th Edition
6.17
Silberschatz, Galvin and Gagne ©2011
Solution using TestAndSet()

Shared boolean variable lock, initialized to FALSE
 Solution:
do {
while (TestAndSet (&lock )) /* run as an uninterruptible unit */
; // do nothing
//
critical section
lock = FALSE;
//
remainder section
} while (TRUE);
Operating System Concepts Essentials – 8th Edition
6.18
Silberschatz, Galvin and Gagne ©2011
CompareAndSwap() Instruction

Definition: operates on three operands.
int CompareAndSwap (int *value, int expected, int new_value) {
int temp = *value;
if (*value == expected)
*value = new value;
return temp;
}
Operating System Concepts Essentials – 8th Edition
6.19
Silberschatz, Galvin and Gagne ©2011
Solution using CompareAndSwap()

Global variable, lock initialized to 0

The first process will set lock to 1 and enter its CS because lock == 0 inside
CompareAndSwap() instruction.
 When the process exits the CS, it sets lock back to 0, allowing another process
to enter its CS.

Solution:
do {
while (CompareAndSwap(&lock, 0, 1) != 0)
; /* do nothing */
// critical section
lock = 0;
// remainder section
} while (TRUE);

ME is met; but bounded waiting is not satisfied
Operating System Concepts Essentials – 8th Edition
6.20
Silberschatz, Galvin and Gagne ©2011
Bounded-waiting Mutual Exclusion
with TestAndSet()
do { // lock : false, waiting[n] : all false


waiting[i] = true;

key = true;
while (waiting[i] && key)
The two processes share two data items:

key = TestAndSet(&lock);
waiting[i] = false;
Mutual Exclusion: Pi can enter its CS only if
either waiting[i] == false or key == false

// critical section
j = (i + 1) % n;

while ((j != i) && !waiting[j])
j = (j + 1) % n;
Progress: since a process exiting the CS
either sets lock to false or sets waiting[j] to
false, allowing a process waiting to enter its
CS to proceed

Bounded Waiting Time: a leaving process
scans the array waiting in the cyclic ordering.
Any waiting process will enter CS within n-1
times.
lock = false; // initial state
else // within n-1 times
// remainder section
} while (true);
Operating System Concepts Essentials – 8th Edition
key = false only if TestAndSet() executed
ex) the first process of TestAndSet()
waiting[i] = false if another process leaves
its CS

if (j == i) // one cycle
waiting[j] = false; // take turns
boolean waiting[n]; // initialized to False
boolean lock;
// initialized to False
6.21
Silberschatz, Galvin and Gagne ©2011
Bounded-waiting Mutual Exclusion
with TestandSet()
do {
do {
waiting[i] = TRUE;
waiting[j] = TRUE;
key = TRUE;
key = TRUE;
while (waiting[i] && key)
while (waiting[j] && key)
key = TestAndSet(&lock);
key = TestAndSet(&lock);
waiting[i] = FALSE;
waiting[j] = FALSE;
// critical section
// critical section
j = (i + 1) % n;
i = (j + 1) % n;
while ((j != i) && !waiting[j])
while ((i != j) && !waiting[i])
j = (j + 1) % n;
i = (i + 1) % n;
if (j == i)
if (i == j)
lock = FALSE;
lock = FALSE;
else
else
waiting[j] = FALSE;
waiting[i] = FALSE;
// remainder section
// remainder section
} while (TRUE);
} while (TRUE);
* at Process Pi
Operating System Concepts Essentials – 8th Edition
6.22
* at Process Pj
Silberschatz, Galvin and Gagne ©2011
Mutex Locks

Previous solutions are complicated and generally inaccessible to application
programmers
 OS designers build software tools to solve critical section problem
 Simplest is mutex lock

A process should acquire a lock before entering a critical section;
 It releases the lock when it exits the critical section.
 Protect critical regions and prevent race conditions:
 By first acquire() a lock, then release() it
do {
 Boolean variable indicating if lock is available or not
 Calls to acquire() and release() must be atomic
acquire lock
 Usually implemented via hardware atomic instructions:
critical section
using TestAndSet() or CompareAndSwap() instructions
release lock
 Disadv) But this solution requires busy waiting
remainder section
 This lock therefore called a spinlock
} while (true);
 good for short term lock (No context-switch)
 Busy waiting wastes CPU cycles that
some other processes uses productively.
Operating System Concepts Essentials – 8th Edition
6.23
Silberschatz, Galvin and Gagne ©2011
acquire() and release()
acquire() {
while (!available)
; /* busy wait */
available = false;;
}
release() {
available = true;
}

Solution to the critical section problem using mutex lock
do {
acquire lock
critical section
release lock
remainder section
} while (true);
Operating System Concepts Essentials – 8th Edition
6.24
Silberschatz, Galvin and Gagne ©2011
Semaphore

Previous hardware-based solutions: hard for application programmers to use.
 Synchronization tool, similar to a mutex lock, a semaphore is introduced.
 Semaphore S – integer variable


Generally a counter used to provide access to a shared data object for
multiple processes.
Accessed only through two standard atomic operations: wait() and signal()
 wait() originally termed P, proberen, “to test”
signal() originally called V, verhogen, “to increment”
 Less complicated
 Can only be accessed via two indivisible (atomic) operations



wait (S) {
while S <= 0; // no-op, busy wait
S--;
}
signal (S) {
S++;
}
Operating System Concepts Essentials – 8th Edition
6.25
Silberschatz, Galvin and Gagne ©2011
Semaphore as
General Synchronization Tool


Counting semaphore – integer value can range over an unrestricted domain

Used to control access to a given resource consisting of a finite number of instances.

The semaphore is initialized to the number of resources available.

wait(S) when wishing to use a resource , signal(S) when releasing a resource
Binary semaphore – integer value can range only between 0 and 1;

Also known as mutex locks, initialized to 1

Can implement a counting semaphore S as a binary semaphore

Provides mutual exclusion
Semaphore mutex;
// initialized to 1
do {
wait (mutex);
// Critical Section
signal (mutex);
// remainder section
} while (TRUE);
Operating System Concepts Essentials – 8th Edition
6.26
Silberschatz, Galvin and Gagne ©2011
Semaphore as
General Synchronization Tool

Synchronization problems

Two concurrently running processes: P1 and P2

P1 with a statement S1

P2 with a statement S2

S2 to be executed only after S1 has completed

Common semaphore synch, initialized to 0, for P1 and P2
S1;
signal(synch); // in process P1
wait(synch); // in process P2
S2;
Note: because synch is initialized to 0, P2 will execute S2 only after P1 has invoked
signal(synch)
Operating System Concepts Essentials – 8th Edition
6.27
Silberschatz, Galvin and Gagne ©2011
Characteristics of Semaphore


Resource sharing by a process:

Test the semaphore that controls the resource

Positive semaphore value  use the resource, decrement by 1

0 semaphore value  go to sleep until (semaphore > 0)

Done with a shared resource  increment by 1, awakening sleeping processes
Main disadvantage of the semaphore definition is that it requires busy waiting.

While a process is in its critical section, any other process that tries to enter its critical section
must loop continuously in the entry code.

Continual looping  a problem in a multiprogramming system with a single CPU

Busy waiting wastes CPU cycle that some other process might use.

This type of semaphore is called a spinlock (spinning while waiting for the lock)

Useful for multiprocessor systems as the alternative to the context switch when locks are
expected to be held for short time.
Operating System Concepts Essentials – 8th Edition
6.28
Silberschatz, Galvin and Gagne ©2011
Semaphore Implementation
with no Busy waiting


To overcome the need for busy waiting:

With each semaphore there is an associated waiting queue,

Modification of the definition of the wait() and signal() semaphore operations

a process executes wait() and finds the semaphore is not positive 

wait and rather than busy waiting, block itself

placing it into a waiting queue associated with the semaphore

process state to waiting state

control to the CPU scheduler resulting in selecting another process

the process waiting on a semaphore should be restarted when some other
process executes a signal()
Two operations provided by the OS as basic system calls

block() – places the process invoking the operation on the appropriate waiting
queue, suspending the process that invokes it.

wakeup() – remove one of processes in the waiting queue and place it in the
ready queue to restart it, changing from the waiting state to the ready state.
Operating System Concepts Essentials – 8th Edition
6.29
Silberschatz, Galvin and Gagne ©2011
Semaphore Implementation
with no Busy waiting

Each entry (semaphore) in a waiting queue has two data items:

value (of type integer)

list : pointer to a list of processes
typedef struct {
int value;
struct process * list;
} semaphore;
Operating System Concepts Essentials – 8th Edition
6.30
Silberschatz, Galvin and Gagne ©2011
Revised Semaphore Implementation

Implementation of wait() :
wait(semaphore *S) {
Svalue--;
// semaphore value may be negative, identifying # of
if (Svalue < 0) { // processes waiting on that semaphore
add this process to Slist;
block();
// suspends the process that invokes it
}
}
 Implementation of signal() :
signal(semaphore *S) {
Svalue++;
if (Svalue <= 0) {
remove a process P from Slist;
wakeup(P); // resumes the execution of a blocked process P
}
}
Operating System Concepts Essentials – 8th Edition
6.31
Silberschatz, Galvin and Gagne ©2011
Semaphore Implementation

Must guarantee that no two processes can execute wait () and signal () on the
same semaphore at the same time

Thus, implementation becomes the critical section problem where the wait and
signal code are placed in the critical section

In a single-processor environment, solved by disabling interrupts during the time the wait()
and signal() operations are executing.

In a multiprocessor environment, interrupts must be disabled on every processor.



This is a difficult task and causes performance degradation.

SMP system must provide a locking techniques, such as spinlocks.
Still, have busy waiting with wait() and signal() operations in critical section implementation

Problem moved from the entry section to the critical sections of wait() and signal()
operations

But they are usually short

critical section rarely occupied
Note that applications may contain long CSs and spend lots of time
 Busy waiting is not a good solution.
Operating System Concepts Essentials – 8th Edition
6.32
Silberschatz, Galvin and Gagne ©2011
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.

Definition (from Wiki )
A deadlock is the situation where a group of processes blocks forever
because each of the processes is waiting for resources which are held by
another process in the group.

Let S and Q be two semaphores initialized to 1
P0
P1
wait (S);
wait (Q);
wait (Q);
wait (S);
…
…
signal (S);
signal (Q);

Starvation – indefinite blocking (LIFO queue)


signal (Q);
signal (S);
A process may never be removed from the semaphore queue in which it is suspended
Priority Inversion – Scheduling problem when lower-priority process holds a
lock needed by higher-priority process

Solved via priority-inheritance protocol (by inheriting the higher priority until the
lower priority process finishes using resource R, needed by the higher-priority
process.
Operating System Concepts Essentials – 8th Edition
6.33
Silberschatz, Galvin and Gagne ©2011
Classical Problems of Synchronization

Classical problems used to test newly-proposed synchronization schemes,
semaphores (mutex locks)

Bounded-Buffer Problem

Readers and Writers Problem

Dining-Philosophers Problem
Operating System Concepts Essentials – 8th Edition
6.34
Silberschatz, Galvin and Gagne ©2011
Bounded-Buffer Problem

N buffers, each can hold one item

Semaphore mutex, initialized to the value 1, providing mutual exclusion for
accesses to the buffer pool

Semaphore full, initialized to the value 0, count the # of full buffers

Semaphore empty, initialized to the value N, count the # of empty buffers
Operating System Concepts Essentials – 8th Edition
6.35
Silberschatz, Galvin and Gagne ©2011
Bounded Buffer Problem with Semaphore

The structure of the producer process

do {
The structure of the consumer process
do {
wait (full);
// produce an item
wait (mutex);
// in next_produced
// remove an item
wait (empty);
// from buffer to next_consumed
wait (mutex);
signal (mutex);
// add the item to the buffer
signal (empty);
signal (mutex);
// consume the item
signal (full);
// in next_consumed
} while (TRUE);
Operating System Concepts Essentials – 8th Edition
} while (TRUE);
6.36
Silberschatz, Galvin and Gagne ©2011
Readers-Writers Problem


A database is shared among several concurrent processes

Readers – only read the database; they do not perform any updates

Writers – can update (both read and write) the database

Database access by reader(s) and writer(s), simultaneously causes chaos.
Require that the writers have exclusive access to the shared database while writing to
the database

Synchronization problem: Readers-writers problem
Problem – allow multiple readers to read at the same time



Only one single writer can access the shared data exclusively
Shared Data

Semaphore mutex, initialized to 1, ensures mutual exclusion when read_count is updated

Semaphore rw_mutex, initialized to 1, common to both reader and writer processes,
functions as a mutual exclusion semaphore for the writers, and used by the first and last
reader, and not used by readers while other readers are in their CS.

Integer read_count, initialized to 0, keeps track of how many processes are currently
reading the object.
Operating System Concepts Essentials – 8th Edition
6.37
Silberschatz, Galvin and Gagne ©2011
Readers-Writers Problem (Cont.)

The structure of a writer process

The structure of a reader process
do {
do {
wait (mutex) ; // down to access read_count
read_count++ ;
if (read_count == 1) // if first process to read
wait (rw_mutex) ; // wait until no write
signal (mutex) // up for releasing read_count
wait (rw_mutex) ;
//
writing is performed
signal (rw_mutex) ;
// reading is performed
} while (TRUE);
wait (mutex) ; // down mutex
read_count-- ;
if (read_count == 0) // if no more reader
signal (rw_mutex) ; // allow a writer
signal (mutex) ; // up mutex
} while (TRUE);
Operating System Concepts Essentials – 8th Edition
6.38
Silberschatz, Galvin and Gagne ©2011
Readers-Writers Problem with reader-writer lock

Problem is solved on some systems by kernel providing reader-writer locks

Specifying the mode of the lock: either read or write access

Only for reading?  acquire the reader-writer lock in read mode

Wishing to modify?  request the lock in write mode

Useful when it is easy to identify which one is reader or writer for shared data

Useful for applications that have more readers than writers : increased
concurrency compensates the overhead to implement reader-writer lock
Operating System Concepts Essentials – 8th Edition
6.39
Silberschatz, Galvin and Gagne ©2011
Dining-Philosophers Problem

Each philosophers must alternately think and eat.

Originally formulated in 1965 by E. Dijkstra as a competing problem for
access to tape drive peripherals (Wiki)

Don’t interact with their neighbors, occasionally try to pick up 2 (left and right)
chopsticks (one at a time) to eat from bowl


Need both to eat, then release both when done
In the case of 5 philosophers

Shared data

Bowl of rice (data set): Infinite supply

Semaphore chopstick [5],
initialized to 1
Operating System Concepts Essentials – 8th Edition
6.40
Silberschatz, Galvin and Gagne ©2011
Dining-Philosophers Problem Algorithm

The structure of Philosopher i:
do {
wait ( chopstick[i] );
wait ( chopstick[ (i + 1) % 5] );
// wait for left chopstick
// wait for right chopstick
// eat for a while
signal ( chopstick[i] );
signal ( chopstick[ (i + 1) % 5] );
// think for a while
} while (TRUE);

What is the problem with this algorithm?


Deadlock: simultaneously grab left chopstick and delayed forever
Starvation?
Operating System Concepts Essentials – 8th Edition
6.41
Silberschatz, Galvin and Gagne ©2011
Problems with Semaphores

Incorrect use of semaphore operations  causes various types of errors




Typical CS solution with semaphore (mutex, initialized to 1):

wait (mutex) …. signal (mutex)

what if signal (mutex) …. wait (mutex) ?  ME violation because
several processes in CS, but found only if it happens
wait (mutex) … wait (mutex)  Deadlock
Omitting of wait (mutex) or signal (mutex) (or both)  ME violation or
Deadlock
As a solution to this incorrect use of semaphores, high-level language
constructs, the monitor type has been developed.
Operating System Concepts Essentials – 8th Edition
6.42
Silberschatz, Galvin and Gagne ©2011
Monitors

A high-level abstraction that provides a convenient and effective mechanism for
process synchronization
 A monitor type is an abstract data type, a collection of shared variables and
operations on those variables: only accessible by code within the procedure
 Only one process (thread) may be active within the monitor at a time
 Implicit mutual exclusion, No need to code the synchronization constraint
explicitly.
monitor monitor-name
{
// shared variable declarations
procedure P1 (…) { …. }
procedure Pn (…) {……}
Initialization code (…) { … }
}
 But not powerful enough to model some synchronization schemes
 Additional explicit synchronization mechanisms to write a tailor-made
synchronization scheme
 Provided by the condition construct
Operating System Concepts Essentials – 8th Edition
6.43
Silberschatz, Galvin and Gagne ©2011
Schematic view of a Monitor
Operating System Concepts Essentials – 8th Edition
6.44
Silberschatz, Galvin and Gagne ©2011
Condition Variables

Monitor condition variables


condition x, y; // condition type variables
Only two operations on a condition variable:


x.wait () – a process invoking the operation is suspended until x.signal () is
invoked

Put executing process (thread) at the end of the condition variable queue

Releases access to the monitor
x.signal () – resumes exactly one suspended process (if any) that invoked x.wait ()

If no x.wait () on the variable, then it has no effect on the variable
c.f. signal() associated with semaphores : always affect the state of semaphore
Operating System Concepts Essentials – 8th Edition
6.45
Silberschatz, Galvin and Gagne ©2011
Monitor with Condition Variables
Operating System Concepts Essentials – 8th Edition
6.46
Silberschatz, Galvin and Gagne ©2011
Monitor Behavior (1)
Ref. for Monitor with semaphore: http://www.eecs.harvard.edu/~mdw/course/cs61/mediawiki/images/7/7e/Lectures-semaphores.pdf
Operating System Concepts Essentials – 8th Edition
6.47
Silberschatz, Galvin and Gagne ©2011
Monitor Behavior (2)
Ref. for Monitor with semaphore: http://www.eecs.harvard.edu/~mdw/course/cs61/mediawiki/images/7/7e/Lectures-semaphores.pdf
Operating System Concepts Essentials – 8th Edition
6.48
Silberschatz, Galvin and Gagne ©2011
Monitor Behavior (3)
Ref. for Monitor with semaphore: http://www.eecs.harvard.edu/~mdw/course/cs61/mediawiki/images/7/7e/Lectures-semaphores.pdf
Operating System Concepts Essentials – 8th Edition
6.49
Silberschatz, Galvin and Gagne ©2011
Condition Variables Choices


If process P invokes x.signal (), with Q in x.wait () state, what should happen
next?

If Q is resumed, then P must wait within the monitor.

Otherwise, both P and Q processes would be active simultaneously within the monitor.
Two possibilities exist:

Signal and wait – P waits until Q leaves monitor or waits for another condition

Signal and continue – Q waits until P leaves the monitor or waits for another condition

Both have pros and cons – language implementer can decide

Monitors implemented in Concurrent Pascal compromise

P executing signal() immediately leaves the monitor. Hence Q is resumed.
(signal_and_leave)

Implemented in other languages including Java and C#.
Operating System Concepts Essentials – 8th Edition
6.50
Silberschatz, Galvin and Gagne ©2011
Dining-Philosophers Solution Using Monitors

Deadlock-free solution to the dining-philosophers problem
 Restriction: A philosopher may pick up her chopsticks only if both of them are
available.
 Additional data structure to distinguish the philosophers’ state
enum {THINKING, HUNGRY, EATING} state[5]; //Three states of a philosopher
condition self[5];

Each philosopher i invokes the operations pickup() and putdown() in the following
sequence:
DiningPhilosophers.pickup(i);
EAT
DiningPhilosophers.putdown(i);

No deadlock, but starvation is possible!
Operating System Concepts Essentials – 8th Edition
6.51
Silberschatz, Galvin and Gagne ©2011
Solution to DP using Monitor(Cont.)
monitor DiningPhilosophers {
enum { THINKING, HUNGRY, EATING } state [5] ;
condition self [5];
void pickup (int i)
void putdown (int i)
void test (int i)
void initialization_code()
}
Operating System Concepts Essentials – 8th Edition
6.52
Silberschatz, Galvin and Gagne ©2011
Solution to DP using Monitor(Cont.)
monitor DiningPhilosophers {
enum { THINKING, HUNGRY, EATING } state [5] ;
condition self [5];
void test (int i) {
if ( (state[(i + 4) % 5] != EATING) &&
(state[i] == HUNGRY) &&
(state[(i + 1) % 5] != EATING) ) {
state[i] = EATING;
self[i].signal();
}
}
void pickup (int i) {
state[i] = HUNGRY;
test(i);
if (state[i] != EATING) self [i].wait();
}
void putdown (int i) {
state[i] = THINKING;
// test left and right neighbors
test((i + 4) % 5);
test((i + 1) % 5);
}
void initialization_code() {
for (int i = 0; i < 5; i++)
state[i] = THINKING;
}
}
Operating System Concepts Essentials – 8th Edition
6.53
Silberschatz, Galvin and Gagne ©2011
Monitor Implementation Using Semaphores

Variables
semaphore mutex; // (initially = 1), provided for each monitor
semaphore next;
// (initially = 0), used by the signaling process
// to suspend themselves and wait until the
// resumed process either leaves or waits
// (signal_and_wait)
int next_count = 0; // provided to count the # of processes
suspended on next
 Each external function F will be replaced by:
wait(mutex); // before entering the monitor
…
body of F;
…
if (next_count > 0) // if there is process suspended on next
signal(next)
else
signal(mutex); // after leaving the monitor
 Mutual exclusion within a monitor is ensured.
Operating System Concepts Essentials – 8th Edition
6.54
Silberschatz, Galvin and Gagne ©2011
Condition Variables Implementation in Monitor
 For each condition variable x, we have:
semaphore x_sem; // (initially = 0)
int x_count = 0;
 The operation x.wait() can be implemented as:
x_count++;
if (next_count > 0)
signal(next);
else
signal(mutex);
wait(x_sem);
x_count--;
 The operation x.signal() can be implemented as:
// unlock the monitor for
// processes waiting outside
// the monitor
// wait on the CV queue
// can be taken out of CV q.
Operating System Concepts Essentials – 8th Edition
6.55
if (x_count > 0) { // only if processes on CV
next_count++;
signal(x_sem);
wait(next);
// signal and wait 
// causes signaling process
// to suspend themselves
//(by Hoare style)
next_count--;
}
Silberschatz, Galvin and Gagne ©2011
Monitor Behavior (4)
Ref. for Monitor with semaphore: http://www.eecs.harvard.edu/~mdw/course/cs61/mediawiki/images/7/7e/Lectures-semaphores.pdf
Operating System Concepts Essentials – 8th Edition
6.56
Silberschatz, Galvin and Gagne ©2011
Monitor Behavior (5)
Ref. for Monitor with semaphore: http://www.eecs.harvard.edu/~mdw/course/cs61/mediawiki/images/7/7e/Lectures-semaphores.pdf
Operating System Concepts Essentials – 8th Edition
6.57
Silberschatz, Galvin and Gagne ©2011
Signaling on CV  block
After signaling
on CV,
immediately leave
(or execute)
Ref. for Monitor with semaphore: http://www.eecs.harvard.edu/~mdw/course/cs61/mediawiki/images/7/7e/Lectures-semaphores.pdf
Operating System Concepts Essentials – 8th Edition
6.58
Silberschatz, Galvin and Gagne ©2011
Resuming Processes within a Monitor

If several processes queued on condition x, and x.signal() executed, which should be
resumed?

Process-resumption order:


First-come, first-served (FCFS) : frequently, but not adequate in some cases
conditional-wait construct of the form:
x.wait(c)
where c is priority number (an integer expression):
used as the priority number of a process
stored with the name of the process
Process with lowest number (highest priority) is scheduled next
Operating System Concepts Essentials – 8th Edition
6.59
Silberschatz, Galvin and Gagne ©2011
A Monitor to Allocate Single Resource

ResourceAllocator monitor

controls the allocation of a single resource among competing processes.

Requesting process specifies the maximum time it plans to use the resource.
monitor ResourceAllocator {
boolean busy;
condition x;
void acquire(int time) {
if (busy)
x.wait(time); // monitor allocates the resource to the process
busy = TRUE;
// with the shortest time-allocation request
}
void release() {
busy = FALSE;
x.signal();
}
initialization code() {
busy = FALSE;
}
}
Operating System Concepts Essentials – 8th Edition
6.60
Silberschatz, Galvin and Gagne ©2011
Synchronization Examples

Windows

Linux

Solaris

Pthreads
Operating System Concepts Essentials – 8th Edition
6.61
Silberschatz, Galvin and Gagne ©2011
Windows Synchronization

Windows OS is a multithreaded kernel for real-time applications and multiple
processors

When kernel accesses a global resource:

a single processor system: temporarily masks interrupts for all interrupt
handlers to protect access to global resources

a multiprocessor system: protects access to global resources using
spinlocks (short code segments), non-preempting threads while holding a
spinlock


Spinlocking-thread will never be preempted
Also provides dispatcher objects for thread synchronization outside the
kernel, which may implement mutex locks, semaphores, events, and timers.

Events

An event acts much like a condition variable

Timers notify one or more thread when time expired

Dispatcher objects in either signaled-state (object available) or non-signaled state
(object not available, thread will block)
Operating System Concepts Essentials – 8th Edition
6.62
Silberschatz, Galvin and Gagne ©2011
Linux Synchronization

Linux:

Prior to kernel Version 2.6, disables interrupts (non-preemptive) to implement short critical
sections

Now (Version 2.6 and later), fully preemptive

Atomic simple math operations for the simplest synchronization technique: atomic_t,
atomic_set(), atomic_add(), atomic_sub(), atomic_inc(), atomic_read()

Linux provides synchronization mechanisms in the kernel:

mutex locks

semaphores

spinlocks

reader-writer versions of both

For SMP, spinlock is provided

On single-processor system, spinlocks are inappropriate for use and are replaced by

Enabling kernel preemption, rather than releasing a spinlock (SMP)


preempt_enable()
Disabling kernel preemption, rather than holding a spinlock (SMP)

preempt_disable()
Operating System Concepts Essentials – 8th Edition
6.63
Silberschatz, Galvin and Gagne ©2011
Solaris Synchronization

Implements a variety of locks to support multitasking, multithreading (including realtime threads), and multiprocessing

Uses adaptive mutex for efficiency when protecting critical data item from short
code segments

On SMP: adaptive mutex starts as a standard semaphore implemented as a spinlock

If the data are locked and in use, two choices: either spin or block

If held by a thread running on another CPU, then the thread spins

If lock held by non-run-state thread, the thread blocks and sleeps waiting for signal of lock
being released

Uses condition variables and semaphores for longer code segment

Uses readers-writers locks when protecting data accessed frequently but in a
read-only manner (multiple readers concurrently) and useful for long sections of
code

Uses turnstiles, a queue structure containing threads blocked on a lock, to order
the list of threads waiting to acquire either an adaptive mutex or reader-writer lock


Turnstiles are per-lock-holding-thread, not per-object
Priority-inheritance per-turnstile gives the running thread the highest of the
priorities of the threads in its turnstile
Operating System Concepts Essentials – 8th Edition
6.64
Silberschatz, Galvin and Gagne ©2011
Pthreads Synchronization

Pthreads API is OS-independent

It provides:


mutex locks : fundamental synchronization technique used with Pthreads

condition variables
Non-portable extensions include:

semaphores

spinlocks
Operating System Concepts Essentials – 8th Edition
6.65
Silberschatz, Galvin and Gagne ©2011
The Deadlock Problem

In a multiprogramming environment, a set of blocked processes each holding a
resource and waiting to acquire a resource held by another process in the set

Example


System has 2 disk drives

P1 and P2 each hold one disk drive and each needs another one
Example

semaphores A and B, initialized to 1 P0 and P1
wait (A);
wait(B)
wait (B);
wait(A)
Operating System Concepts Essentials – 8th Edition
6.66
Silberschatz, Galvin and Gagne ©2011
Bridge Crossing Example

Traffic only in one direction

Each section of a bridge can be viewed as a resource

If a deadlock occurs, it can be resolved if one car backs up (preempt
resources and rollback)

Several cars may have to be backed up if a deadlock occurs

Starvation is possible

Note – Most OSes do not prevent or deal with deadlocks
Operating System Concepts Essentials – 8th Edition
6.67
Silberschatz, Galvin and Gagne ©2011
System Model

A system consists of a finite number of resources to be distributed among a
number of competing processes.

Resource types R1, R2, . . ., Rm
CPU cycles, memory space, files, I/O devices

Each resource type Ri has Wi instances.

Each process utilizes a resource in only the following sequence

request

use

release
Operating System Concepts Essentials – 8th Edition
6.68
Silberschatz, Galvin and Gagne ©2011
Deadlock Characterization
Deadlock can arise if the following four conditions hold simultaneously.

Mutual exclusion: only one process at a time can use a resource in a
nonsharable mode

No preemption: a resource can be released only voluntarily by the
process holding it, after that process has completed its task

Hold and wait: a process holding at least one resource is waiting to
acquire additional resources held by other processes

Circular wait: there exists a set {P0, P1, …, Pn} of waiting processes such
that P0 is waiting for a resource that is held by P1, P1 is waiting for a
resource that is held by P2, …, Pn–1 is waiting for a resource that is held by
Pn, and Pn is waiting for a resource that is held by P0.
Operating System Concepts Essentials – 8th Edition
6.69
Silberschatz, Galvin and Gagne ©2011
Simple Resource Deadlock
Operating System Concepts Essentials – 8th Edition
6.70
Silberschatz, Galvin and Gagne ©2011
Related: Indefinite postponement

Also called indefinite blocking or starvation


Occurs due to biases in a system’s resource scheduling policies
Aging

Technique that prevents indefinite postponement by increasing process’s
priority as it waits for resource
COP 5994 - Operating Systems
Operating System Concepts Essentials – 8th Edition
6.71
71
Silberschatz, Galvin and Gagne ©2011
Resource-Allocation Graph
A set of vertices V and a set of edges E


V is partitioned into two types:

P = {P1, P2, …, Pn}, the set consisting of all the processes in the
system

R = {R1, R2, …, Rm}, the set consisting of all resource types in the
system
E is directed edge from process to resource type

request edge – directed edge Pi  Rj

assignment edge – directed edge Rj  Pi
Operating System Concepts Essentials – 8th Edition
6.72
Silberschatz, Galvin and Gagne ©2011
Resource-Allocation Graph (Cont.)

Process

Resource Type with 4 instances

Pi requests instance of Rj
request edge – directed edge Pi  Rj
Pi
Rj

Pi is holding an instance of Rj
assignment edge – directed edge Rj  Pi
Pi
Rj
Operating System Concepts Essentials – 8th Edition
6.73
Silberschatz, Galvin and Gagne ©2011
Example of a Resource Allocation Graph
Operating System Concepts Essentials – 8th Edition
6.74
Silberschatz, Galvin and Gagne ©2011
Resource Allocation Graph With A Deadlock
Operating System Concepts Essentials – 8th Edition
6.75
Silberschatz, Galvin and Gagne ©2011
Graph With A Cycle But No Deadlock
Operating System Concepts Essentials – 8th Edition
6.76
Silberschatz, Galvin and Gagne ©2011
Basic Facts

If graph contains no cycles  no deadlock

If graph contains a cycle 

if only one instance per resource type, then deadlock

if several instances per resource type, possibility of deadlock
Operating System Concepts Essentials – 8th Edition
6.77
Silberschatz, Galvin and Gagne ©2011
Methods for Handling Deadlocks

Prevent or avoid deadlocks by ensuring that the system will never enter a
deadlock state

Allow the system to enter a deadlock state and then recover

Ignore the problem and pretend that deadlocks never occur in the system; used
by most operating systems, including UNIX
Operating System Concepts Essentials – 8th Edition
6.78
Silberschatz, Galvin and Gagne ©2011
Dealing with Deadlock

Deadlock prevention

Deadlock avoidance

Deadlock detection

Deadlock recovery
Operating System Concepts Essentials – 8th Edition
6.79
Silberschatz, Galvin and Gagne ©2011
Deadlock Prevention
Includes a set of methods for ensuring that at least one of the necessary conditions cannot hold.
Prevent deadlocks by constraining request operations

To prevent Mutual Exclusion – not required for sharable resources; must
hold for nonsharable resources

To prevent Hold and Wait – must guarantee that whenever a process
requests a resource, it does not hold any other resources

Require process to request and be allocated all its resources before it begins
execution, or allow process to request resources only when the process has none

Low resource utilization; starvation possible
Operating System Concepts Essentials – 8th Edition
6.80
Silberschatz, Galvin and Gagne ©2011
Deadlock Prevention (Cont.)


To prevent No Preemption –

If a process that is holding some resources requests another resource that cannot be
immediately allocated to it, then all resources currently being held are released

Preempted resources are added to the list of resources for which the process is waiting

Process will be restarted only when it can regain its old resources, as well as the new
ones that it is requesting
To prevent Circular Wait – impose a total ordering of all resource types, and
require that each process requests resources in an increasing order of
enumeration
Operating System Concepts Essentials – 8th Edition
6.81
Silberschatz, Galvin and Gagne ©2011
Deadlock Avoidance
Requires that the system has some additional information concerning which
resources a process will request and use during its lifetime

Simplest and most useful model requires that each process declare the
maximum number of resources of each type that it may need

The deadlock-avoidance algorithm dynamically examines the resourceallocation state to ensure that there can never be a circular-wait condition

Resource-allocation state is defined by the number of available and
allocated resources, and the maximum demands of the processes
Operating System Concepts Essentials – 8th Edition
6.82
Silberschatz, Galvin and Gagne ©2011
Download