CMPT 880: Internet Architectures and Protocols
Download
Report
Transcript CMPT 880: Internet Architectures and Protocols
School of Computing Science
Simon Fraser University
CMPT 300: Operating Systems I
Ch 6: Process Synchronization
Dr. Mohamed Hefeeda
1
Objectives
Understand
The Critical-Section Problem
And its hardware and software solutions
2
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
3
Producer Process
while (true) {
/* produce an item in nextProduced */
while (count == BUFFER_SIZE)
; // do nothing
buffer [in] = nextProduced;
in = (in + 1) % BUFFER_SIZE;
count++;
}
4
Consumer Process
while (true) {
while (count == 0)
; // do nothing
nextConsumed = buffer[out];
out = (out + 1) % BUFFER_SIZE;
count--;
/*consume item in nextConsumed */
}
What can go wrong with this solution?
5
Race Condition
count++ could be implemented as
register1 = count
register1 = register1 + 1
count = register1
count-- could be implemented as
register2 = count
register2 = register2 - 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 - 1 {register2 = 4}
S4: producer executes count = register1 {count = 6 }
S5: consumer executes count = register2 {count = 4}
6
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, any method that solves the
Critical-Section Problem must satisfy three
requirements …
7
Critical-Section (CS) Problem
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 selection of the process that will
enter the critical section next cannot be postponed
indefinitely
3. 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
Assumptions
Each process executes at a nonzero speed
No restriction on the relative speed of the N processes
8
Solutions for CS Problem
Disable interrupts during running CS
Currently running code would execute
without preemption
Possible only on uniprocessor systems. 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
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;
Boolean flag[2];
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
Algorithm for Process Pi
while (true) {
flag[i] = TRUE;
turn = j;
while (flag[j] && turn == j)
;
CRITICAL SECTION
flag[i] = FALSE;
REMAINDER SECTION
}
Does this algorithm satisfy the three requirements?
Yes. Show this as an exercise.
11
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
TestAndndSet Instruction
Definition:
boolean TestAndSet (boolean *target)
{
boolean rv = *target;
*target = TRUE;
return rv;
}
13
Solution using TestAndSet
Shared boolean variable lock, initialized to false
while (true) {
while ( TestAndSet (&lock ) )
; /* do nothing
// critical section
lock = FALSE;
// remainder section
}
Does this algorithm satisfy the three requirements?
NO. A process can wait indefinitely for another faster process
that is accessing its CS. Check Fig 6.8 for a modified version.
14
Swap Instruction
Definition:
void Swap (boolean *a, boolean *b)
{
boolean temp = *a;
*a = *b;
*b = temp;
}
15
Solution using Swap
Shared boolean variable lock initialized to FALSE;
Each process has a local boolean variable key
while (true) {
key = TRUE;
while ( key == TRUE)
Swap (&lock, &key );
// critical section
lock = FALSE;
//
remainder section
}
16
Semaphores
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
Semaphore Operations
wait (S) {
while (S <= 0)
; // no-op, called busy waiting, spinlock
S--;
}
signal (S) {
S++;
}
Later, we will see how to implement these
operations with no busy waiting
18
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; // initialized to 1
wait (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;
signal (sem);
P2:
wait (sem);
S2;
Control access to a resource with finite number
of instances
e.g., producer-consumer problem with finite
buffer
20
Semaphore Implementation with no Busy Waiting
Each semaphore has:
value (of type integer)
waiting queue
Two internal 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--;
if (value < 0) {
add this process to waiting queue
block();
}
}
signal (S) {
value++;
if (value <= 0) { /*some processes are waiting*/
remove a process P from waiting queue
wakeup(P);
}
}
22
Semaphore Implementation
Must guarantee that no two processes can
execute wait and signal on same semaphore at
same time
Thus, implementation becomes the critical
section problem where wait and signal code are
placed in critical section, and protected by
Disabling interrupts (uniprocessor systems only)
Busy waiting or spinlocks (multiprocessor systems)
Well, why do not we do the above in applications?
Applications may spend long (and unknown) amount of
time in critical sections, unlike kernel which spends
short and known beforehand time in critical section (~
ten instructions)
23
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);
wait (Q);
wait (Q);
wait (S);
.
.
.
.
.
.
signal (S);
signal (Q);
signal (Q);
signal (S);
Starvation – indefinite blocking. A process may never be
removed from the semaphore queue in which it is
suspended
24
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)
25
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
26
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
27
Bounded Buffer Problem (cont’d)
Structure of the producer process
while (true) {
// produce an item
wait (empty);
wait (mutex);
// add item to buffer
signal (mutex);
signal (full);
}
28
Bounded Buffer Problem (cont’d)
Structure of the consumer process
while (true) {
wait (full);
wait (mutex);
// remove an item from buffer
signal (mutex);
signal (empty);
// consume removed item
}
29
Dining-Philosophers Problem
Philosophers alternate between eating and thinking
To eat, a philosopher needs two chopsticks (at her left and right)
Models multiple processes sharing multiple resources
Write a program for each philosopher s.t. no starvation/deadlock
occurs
Solution approach:
Bowl of rice (data set)
Array of semaphores: chopstick [5] initialized to 1
30
Dining-Philosophers Problem: Philosopher i
While (true) {
wait ( chopstick[i] );
wait ( chopstick[ (i + 1) % 5] );
// eat
signal ( chopstick[i] );
signal (chopstick[ (i + 1) % 5] );
// 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
31
Readers-Writers Problem
A data set is shared among a number of
concurrent processes
Readers – only read the data set; they do not perform
any updates
Writers – can 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.
Shared Data
Data set
Semaphore mutex initialized to 1
Semaphore wrt initialized to 1
Integer readcount initialized to 0
32
Readers-Writers Problem (cont’d)
The structure of a writer process
while (true) {
wait (wrt) ;
//
writing is performed
signal (wrt) ;
}
33
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) ; // mutex: protects readcount
readcount ++ ;
if (readercount == 1) wait (wrt) ;
signal (mutex)
// reading is performed
wait (mutex) ;
readcount - - ;
if (redacount == 0) signal (wrt) ;
signal (mutex) ;
}
34
Readers-Writers Problem (cont’d)
Some systems implement reader-writer locks
E.g., 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. concurrency
Reader-writer locks require more overhead to
establish than semaphores, but they provide higher
concurrency by allowing multiples readers in CS
35
Condition Variables
Condition x, y;
Two operations on a condition variable:
x.wait () – a process that invokes the operation is
suspended.
x.signal () – resumes one of processes (if any) that
invoked x.wait ()
What is the difference between condition variables
and semaphores?
condition variable: if no process is suspended, signal
has no effect
semaphores: signal always increments semaphore's
value
Condition variables are usually used to
suspend/awake processes
36
Monitors
Monitor: High-level abstraction that provides a convenient
and effective mechanism for process synchronization
Compiler (not programmer) takes care of mutual exclusion
Only one process may be active within the monitor at a time
monitor monitor_name
{
//shared variable declarations
procedure P1 (…) { …. }
…
procedure Pn (…) {……}
Initialization code ( ….) { … }
}
37
Schematic View of Monitors
38
Solution to Dining Philosophers
monitor DP
{
enum {THINKING, HUNGRY, EATING} state [5] ;
condition self [5];
void pickup (int i) {
state[i] = HUNGRY;
test(i); //check both chopsticks,
// set state[i] = EATING if both are available
if (state[i] != EATING) self [i].wait;
}
void putdown (int i) {
state[i] = THINKING;
// test left and right neighbors
test((i + 4) % 5); // right
test((i + 1) % 5); // left
39
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 () ;
}
}
initialization_code() {
for (int i = 0; i < 5; i++)
state[i] = THINKING;
}
} // end monitor
40
Solution to Dining Philosophers (cont’d)
Each philosopher invokes the operations pickup()
and putdown() in the following sequence:
dp.pickup (i)
EAT
dp.putdown (i)
41
Monitors Implementation
It is up to the compiler to ensure mutual exclusion in monitors
Semaphores are usually used
Languages like Java, C# (not C), and Concurrent Pascal provide
monitors-like mechanisms
Java
public class SimpleClass {
....
public synchronized void insert(…) { …}
public synchronized void remove(…) { …}
….
}
Java guarantees that once a thread starts executing a
synchronized method, no other thread can execute any other
synchronized method in the class
Java 1.5+ has semaphores, condition variables, mutex locks, …
In java.util.concurrent package
Exercise: write java programs for the Producer-Consumer and
dinning philosophers problems
42
Synchronization Examples
Windows XP
Linux
Pthreads
43
Windows XP Synchronization
Masks interrupts to protect access to global
resources on uniprocessor systems (inside
kernel)
Uses spinlocks on multiprocessor systems
Provides dispatcher objects for thread
synchronization outside kernel, which can act as
mutexes, semaphores, or events (condition
variables)
44
Linux Synchronization
Linux:
disables interrupts to implement short critical sections
(on single processor systems)
Linux provides:
semaphores
Spinlocks (on SMP)
Reader-writer locks
45
Pthreads Synchronization
Pthreads API is OSindependent
It provides:
mutex locks
condition variables
#include <pthread.h>
pthread_mutex_t mutex;
pthread_mutex_init(&mutex, null);
pthread_mutex_lock(&mutex);
pthread_mutex_unlock(&mutex);
extensions include:
semaphores
read-write locks
spin locks
May not be portable
#include <semaphore.h>
sem_t sem;
sem_init(&sem, 0, 5);
sem_wait(&sem);
sem_post(&sem);
46
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, progress,
bounded waiting
Software solution: Peterson’s Algorithm
Hardware support: TestAndSet(), Swap()
• Busy waiting (or spinlocks)
Semaphores:
• wait(), signal() must be atomic moves the CS
problem to kernel
Monitors: high-level constructs (compiler)
Some classical synchronization problems
47