OS Module III Part I SPP
OS Module III Part I SPP
Process Synchronization
by:
Dr. Soumya Priyadarsini Panda
Assistant Professor
Dept. of CSE
Silicon Institute of Technology, Bhubaneswar
Basic Concepts
A cooperating process is one that can affect or be affected by other
processes executing in the system.
Readers-Writers Problem
Dining-Philosopher Problem
Examples:
A compiler may produce assembly code that is consumed by an
assembler
A web server produces (provides) html files and images which are
consumed (read) by client web browser requesting the resource.
Cont…
i.e. a buffer of items will reside in a shared memory location that can be
filled by producer and emptied by the consumer.
Bounded-buffer:
Assumes that there is a fixed buffer size.
The consumer must wait if the buffer is empty and producer must wait if
buffer is full.
Bounded-Buffer – Shared-Memory
Solution
Shared data: Can be implemented using circular array.
Where variables:
#define BUFFER_SIZE 5 ‘in’ points to next free position,
typedef struct { ‘out’ points to first full position
... Buffer is empty when in==out
} item;
The buffer is full when:
item buffer[BUFFER_SIZE]; ((in+1)%BUFFER_SIZE)==out
int in = 0;
int out = 0;
0 1 2 3 4
in
out
Bounded-Buffer – Shared-Memory
Solution Cont…
//Producer Process: //Consumer Process:
This solution allows at most n-1 items in buffer (of size n) at the same
time.
Example: 0 1 2 3 4
out in
0 1 2 3 4
item1
out in
0 1 2 3 4
item1 item2
out in
…….
0 1 2 3 4
item1 item2 item3 item4
out in
Counter is incremented each time a new item is added to the buffer and
decremented each time an item is removed from the buffer.
The modified producer and consumer code works fine when executed
separately but doesn’t function correctly when executed concurrently
Problems with this solution
Example:
counter++ may be implemented as: counter-- may be implemented as:
Example: The final value of the shared data counter depends upon
which process finishes last
Each process has a segment of code called critical section in which the
process may change values of common variables, update a table, write
to a file, etc.
Preemptive Kernel:
• It allows a process to be preempted when running in kernel mode.
• Pre-emptive kernel must be carefully designed to ensure that shared
kernel data are free from race condition.
• Pre-emptive kernels are more suitable for real time programming.
Non-preemptive Kernel:
• It doesn’t allows a process running in kernel mode to be preempted.
• A kernel mode process will run until it exits kernel mode, blocks, or
voluntarily yields CPU.
• A non-preemptive kernel is free from race condition.
Peterson’s Solution
It’s a classical s/w based solution to the critical section problem.
Let Pi and Pj are 2 process sharing some data and alternate execution
between their critical sections
The variable turn indicates whose turn it is to enter the critical section.
The flag array is used to indicate if a process is ready to enter its critical
section.
To enter the critical section, process Pi first sets flag[i] to be true and
then sets turn to the value j
Structure of Process Pj
do {
critical section
remainder section
} while (true);
To enter the critical section, process Pj first sets flag[j] to be true and
then sets turn to the value i
Peterson’s Solution (Cont…)
do {
acquire lock
critical section
release lock
remainder section
} while (TRUE);
Cont…
The critical section problem can be solved in a uni-processor
environment by preventing interrupts from occurring while a shared
variable is updated.
The h/w based solutions to critical section problem are complicated for
application programmers to use.
wait(S) signal(S)
{ {
while (S <= 0) S++;
; // busy wait }
S--;
}
When one process modifies the semaphore values no other process can
simultaneously modify the same semaphore value.
When the count for the semaphore goes to 0, all resources are being
used.
Semaphore Cont…
The main disadvantage of semaphore is:
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.
Example:
Let S and Q be two semaphores initialized to 1
P0 P1
wait(S); wait(Q);
wait(Q); wait(S);
… ...
signal(S); signal(Q);
signal(Q); signal(S);
Example:
Let L, M, H are 3 processes with prioritie in the order: L < M < H
If process H requires resource R, currently accessed by L. Then H has to wait
for L to release the resource.
If process M becomes runnable, and it preempts L.
Indirectly a process with low priority (M) has affected the high priority
process’s (H) execution.
Priority Inheritance Protocol (PIP)
When they are finished, their priorities revert to their original values.
Semaphore Solutions to the classical
synchronization problems
The Bounded-Buffer Problem
The classical problems of synchronization-
producer – consumer problem (Bounded buffer)
Initialization:
Semaphore mutex initialized to the value 1
Semaphore full initialized to the value 0
Semaphore empty initialized to the value n
Semaphore solution to Bounded-
Buffer Problem
Producer Process: Consumer Process:
Readers-Writers Problem
A database is shared among a number of concurrent processes
Readers – only read the database; they do not perform any updates
Writers – can both read and write
Shared Data:
Database
Semaphore rw_mutex initialized to 1
Semaphore mutex initialized to 1
Integer read_count initialized to 0
Code
do {
wait (chopstick[i] );
wait (chopStick[ (i + 1) % 5] );
// eat
signal (chopstick[i] );
signal (chopstick[ (i + 1) % 5] );
// think
} while (TRUE);
Deadlock Handling:
Allow at most 4 philosophers to be sitting simultaneously at the
table.
Syntax of a monitor:
monitor monitor-name {
// shared variable declarations
procedure P1 (…)
{ ….
}
…….
procedure Pn (…)
{
……
}
Initialization code (…) { … }
}
}
Schematic view of a Monitor
DiningPhilosophers.pickup(i);
…..
Eat
….
DiningPhilosophers.putdown(i);
Cont…
monitor DiningPhilosophers
{
enum { THINKING; HUNGRY, EATING) state [5] ;
condition self [5];
initialization_code()
{
for (int i = 0; i < 5; i++)
state[i] = THINKING;
}
}