Practical Session 5

Operating Systems, 112
Practical Session 5, Synchronization
1
Motivation
• Multiprocessing needs some tools for
managing shared resources
– Printers
– Files
– Data Bases
2
Conditions for a good Solution
1. Mutual Exclusion – No two processes are in
the critical section (CS) at the same time
2. Deadlock Freedom – If processes are trying to
enter the CS one will eventually enter it
3. Starvation Freedom – When a process tries to
enter its CS, it will eventually succeed
3
Solution Archetypes
• Busy wait
– Wastes CPU
– Priority inversion with busy waiting (*):
Task L (low priority) runs and gains exclusive use of
resource R. H (high priority) task is introduced and
attempts to acquire R and must therefore wait. Note that
since H is busy waiting it may still be scheduled (its state
remains runnable).
Result: L can’t run and release R because H is of higher
priority and is scheduled to run before it. H on the other
hand can’t proceed past its busy wait loop.
Deadlock!
• Sleep & Wake up
4
Peterson’s Solution
N=2; interested[0]=interested[1]=FALSE;
int turn;
/* Should be named NOT_MY_TURN
int interested[N];
/* all initially 0 (FALSE) */
*/
void enter_region(int process){ /* who is entering 0 or 1 ? */
int other = 1- process; /* opposite of process */
interested[process] = TRUE; /* signal that you're interested */
turn = process;
/* set flag – NOT my turn */
while (turn == process &&
interested[other] == TRUE); /* null statement */
}
void leave_region(int process){
interested[process] = FALSE;
}5
/* who is leaving 0 or 1 ? */
/* departure from critical region */
Peterson’s Solution
Process = 0
Process = 1
interested[0]=interested[1]=FALSE
int turn;
int interested[2];
interested[0]=interested[1]=FALSE
int turn;
int interested[2];
void enter_region(int process){
int other = 1;
interested[0] = TRUE;
turn = 0;
while (turn == 0 &&
interested[1] == TRUE);
}
void enter_region(int process){
int other = 0;
interested[1] = TRUE;
turn = 1;
while (turn == 1 &&
interested[0] == TRUE);
}
void leave_region(int process){
interested[0] = FALSE;}
void leave_region(int process){
interested[1] = FALSE;}
6
Question 1
N=1; interested[0]=interested[1]=FALSE;
int turn;
/* Should be named NOT_MY_TURN */
int interested[N];
/* all initially 0 (FALSE) */
void enter_region(int process){
/* who is entering 0 or 1 ? */
int other = 1- process;
/* opposite of process */
turn = process;
/* set flag – NOT my turn */
interested[process] = TRUE; /* signal that you're interested */
while (turn == process &&
interested[other] == TRUE); /* null statement */
}
void leave_region(int process){
/* who is leaving 0 or 1 ? */
interested[process] = FALSE;
/* departure from critical region */
}
Consider the following variant of Peterson’s solution
where the two red lines are swapped. Does this variant
solve the mutual exclusion problem?
7
Peterson’s Solution
Process = 0
Process = 1
interested[0]=interested[1]=FALSE
int turn;
int interested[2];
void enter_region(int process){
int other = 1;
turn = 0;
interested[0] = TRUE;
while (turn == 0 &&
interested[1] == TRUE);
}
void enter_region(int process){
int other = 1- process;
turn = 1;
interested[1] = TRUE;
while (turn == 1 &&
interested[0] == TRUE);
}
void leave_region(int process){
interested[0] = FALSE;}
void leave_region(int process){
interested[1] = FALSE;}
8
Answer
We will get a mutual exclusion violation:
P1 does turn:=1;
P0 does turn:=0;
P0 does interested[0]:=true;
P0 does while(turn == 0 && interested [1]); // (#t and #f)  #f
P0 enters the CS.
P1 does interested [1]:=true;
P1 does while(turn == 1 && interested [0]); // (#f and #t)  #f
P1 enters the CS.
now both processes are in the critical section.
9
Question 2
Assume the while statement in Peterson's
solution is changed to:
while (turn != process && interested[other] == TRUE)
Describe a scheduling scenario in which we will
receive a mutual exclusion violation and one in
which we will NOT receive a Mutual Exclusion
violation.
10
Question 2
N=2; interested[0]=interested[1]=FALSE;
int turn;
/* Should be named NOT_MY_TURN */
int interested[N];
/* all initially 0 (FALSE) */
void enter_region(int process){ /* who is entering 0 or 1 ? */
int other = 1- process; /* opposite of process */
interested[process] = TRUE; /* signal that you're interested */
turn = process;
/* set flag – NOT my turn */
while (turn != process &&
interested[other] == TRUE) /* null statement */
}
void leave_region(int process){
interested[process] = FALSE;
}
11
/* who is leaving 0 or 1 ? */
/* departure from critical region */
Peterson’s Solution
Process = 0
Process = 1
interested[0]=interested[1]=FALSE
int turn;
int interested[2];
void enter_region(int process){
int other = 1;
interested[0] = TRUE;
turn = 0;
while (turn != 0 &&
interested[1] == TRUE);
}
void enter_region(int process){
int other = 0;
interested[1] = TRUE;
turn = 1;
while (turn != 1 &&
interested[0] == TRUE);
}
void leave_region(int process){
interested[0] = FALSE;}
void leave_region(int process){
interested[1] = FALSE;}
12
Answer for Q.2
No mutual exclusion violation:
1. One enters and exits and only afterwards the
second receives a time quanta.
2. P0 – interested[0]=true,
P0 – turn = 0,
P1- interested[1]=true,
P1 – turn =1,
P1 passes while loop and enters CS,
P0 – stuck in while loop.
3. Many more….
13
Answer for Q.2
Mutual exclusion violation:
Process A executes:
`interested [process] = TRUE', `turn = process‘
and falls through the while loop shown above.
While in the critical section, the timer fires and process B
executes:
`interested [process] = TRUE', `turn = process'
and falls through the while loop shown above.
Both processes are in the critical section.
14
Dekker’s algorithm
1.bool* flag = {false, false};
2.int turn = 0 ;
3.void mutex() {
4.
flag[process] = true;
5.
while (flag[1-process]) {
6.
if (turn==(1-process)) {
7.
flag[process] = false;
8.
while (turn == (1-process)) { /*nothing*/ }
9.
flag[process] = true;}}
10. /* critical section */
11. turn = (1-process);
12. flag[process] = false;
13. /* non-critical section */
}
15
Question 3 (from midterm of 2005)
Prove Dekker’s algorithm for the Critical Section
problem. That is, show that there are no mutual
exclusion violations, no deadlocks and no
starvation problem.
16
Question 3 (from midterm of 2005)
Process = 0
Process = 1
1.bool* flag = {false, false};
2.int turn = 0 ;
1.bool* flag = {false, false};
2.int turn = 0 ;
3.void mutex() {
4.
flag[0] = true;
5.
while (flag[1]) {
6.
if (turn==1) {
7.
flag[0] = false;
8.
while (turn == 1) {}
9.
flag[0] = true;}}
10. /* critical section */
11. turn = 1;
12. flag[0] = false;
13. /* non-critical section */
}
3.void mutex() {
4.
flag[1] = true;
5.
while (flag[0]) {
6.
if (turn==0) {
7.
flag[1] = false;
8.
while (turn == 0) {}
9.
flag[1] = true;}}
10. /* critical section */
11. turn = 0;
12. flag[1] = false;
13. /* non-critical section */
}
17
Answer Q.3
No mutual exclusion violations – (no two processes will be in the
CS at the same time)
Falsely assume that both p0 and p1 are in the critical
section. Further assume WLG that p0 entered the CS first.
The last change p0 introduced on the algorithm’s
variables, before existing the outer loop (line 5), was the
assignment flag[0]=true.
Following our assumption, p1 followed p0 into the CS
which means that it must have exited its outer loop. This,
however, is only possible if flag[0]=false which is a
contradiction to our initial assumption.
18
Answer Q.3
No starvation – (any process attempting to enter the CS will
eventually succeed)
WLG assume p0 is attempting to enter the CS and is
somewhere in the while loop of line 5 (otherwise it
will enter the CS). p1 can be in several different
states:
1. Not in the CS
2. In the CS
3. In its while loop with turn=0
4. In its while loop with turn=1
19
Answer Q.3
Case 1 – a process not in the CS will not prevent other
processes from entering it
Any process which is not in the CS and does not
want to enter it turns off its flag flag[i]=false (line 12
or init).
This implies that any other process wishing to enter
the CS will find the condition on the outer while
loop (line 5, “while(flag[1])”) unsatisfied and will be
able to enter the CS without having to examine the
value of turn.
20
Answer Q.3
Case 2 – p1 is in the CS
After a finite amount of time p1 will exit the CS
and will set the value of turn to turn=0. If it stays
out then we are back to case 1.
Otherwise, if there is no preemption p1 may try
to enter the CS and we have to consider case 3
(p1 is in its while loop with turn=0).
21
Answer Q.3
Case 3 – p1 is in its while loop with turn=0
Since the value of turn is 0, and no process can
change it (p0 is attempting to enter the CS and will
only be able to change turn’s value after it leaves
the CS), p1 will eventually be held by the inner while
loop (line 8) after setting flag[1]=false.
At some point, p0 will receive CPU time. Since the
value of turn is 0, it will proceed to its outer while
loop (line 5). At this point the outer loop condition
will not hold it, since flag[1]=false (by p1), and p0
will proceed to the CS.
22
Answer Q.3
Case 4 – p1 is in its while loop with turn=1
If the value of turn is 1, then p1 will revolve in its
outer while loop (line 5). It will continue going
through it as long as flag[0]=true.
At some point, p0 will receive CPU time. Since the
value of turn is 1, it will proceed to its inner while
loop (line 8) after setting flag[0]=false. At this point
the outer loop condition will not hold p1, and we
will be back to case 2 or 3 (for which we have
shown that p0 may eventually enter the CS).
23
Answer Q.3
No Deadlock
No need to prove! Follows from the fact that
there’s no starvation.
24
Lamport’s Bakery Algorithm
int value[N]={0, 0,…,0};
int busy[N]={FALSE,…, FALSE};
/* processes get “waiting numbers” */
/* just a flag... */
void enter_region(int i ) /* process i entering.. */
{
busy[i] = TRUE;
/* guard the value selection */
value[i] = max(value[0], value[1], …, value[N-1]) + 1; /* LAST in line … */
busy[i] = FALSE;
for(k=0; k < N; k ++){
while (busy[k] == TRUE) ; /* wait before checking */
while((value[k] != 0) && ((value[k], k) < (value[i], i))); /* wait */
}
}
void leave_region(int i ) {
value[i ] = 0;
}
25
Question 4
Assume we have the following atomic command:
void swap(bool *a, bool *b) {
bool temp = *a;
*a = *b;
*b = temp;
}
Solve the N processes mutual exclusion problem
using the swap command.
26
Answer Q.4
bool lock = FALSE;
bool waiting[N] = {FALSE, FALSE, …,
FALSE};
void enter(int i) {
The idea:
waiting[i]
= TRUE;
Use a local variable “key” which
bool
key
will be
set=toTRUE;
true. Let all
while
(TRUE)
processes
swap{it with current
lock and
compete over
this line.
swap(&key,
&lock);
Only if
the( !waiting[i]
first process to
it
||grab
!key)
will have a value of false to the
break;
lock. This process will enter the
}CS.
}
27
void swap(bool *a, bool *b) {
bool temp = *a;
*a = *b;
*b = temp;
}
void leave(int i) {
waiting[i]= FALSE ;
The int
idea:
j = (i + 1) % N;
Seekwhile
the next
( (j(chronologically
!= i) &&
ordered)
interested process. If) {
waiting[j]==FALSE
such a process
grant
j = (j +exist,
1) %
N; it the
ability
} to enter the CS. Otherwise
resetifthe
locki)so
(j ==
{ that other
processeslock
will be
able to enter
= FALSE;
the CS
at a later
} else
{ time.
waiting[j] = FALSE;
}
}
Question 5a – midterm 2010
Let A be an n processes mutual exclusion
algorithm which is applied with the following
guarantee: whenever A is used, any process will
attempt to access the critical section only once.
Prove or disprove the following claim:
A is a starvation free algorithm if and only if it is a
deadlock free algorithm.
28
Answer Q.5a
The first part of the proof is trivial: starvation
freedom also implies deadlock freedom.
What about the second one?
Assume that there are n processes and that A is
free of deadlocks. Now, let us falsely assume that A
is not a starvation free algorithm and contradict this
assumption.
If A is not a starvation free algorithm, then there
must exist some process pi which goes through
infinitely many steps but still can’t enter the CS.
29
Answer Q.5a, continued
While pi goes through its steps other processes
manage to enter the CS (we assumed deadlock
freedom). As each process pj may only enter the CS
once, at some point all n-1 processes will go
through (in and out of) the CS and we will be left
with pi. At this point, pi is the only process
attempting to enter the CS. Following our initial
assumption, there can be no deadlocks and pi will
enter the CS. This contradicts our false assumption
that A is not a starvation free algorithm.
QED
30
Question Q.5b – midterm 2010
Consider the following simple algorithm similar to that shown in
class:
1 int lock initially 0
2 boolean interested[n] initially {false,…,false}
Code for procss i{0,…,n-1}
3 interested[i]:=true
4 await ((test-and-set(lock)=0) OR (interested[i] =false))
5 Critical Section
6 j:=(i+1) modulo n
7 while (j ≠ i) AND (interested[j] = false)
8
j:=(j+1) modulo n
9 if (j=i)
10
lock:=0
11 else
12
interested[j]:=false
13 interested[i]=false
Test-and-set(w)
do atomically
prev:=w
w:=1
return prev
Is this algorithm deadlock free? Prove or disprove by providing an accurate
scenario
which leads to a deadlock.
31
Answer Q.5b
The following scenario results in a deadlock:
1. A process p0 is executed and executes all lines up until the
beginning of line 13.
(Note that ‘lock’ is freed)
2. Another process p1 is executed and allowed to run all the way
through the CS. At this point p1 iterates through the other
processes and identifies that ‘interested[0]=true’.
3. As a result p1 resets the value ‘interested[0]:=false’ (line 12)
and does not free the lock. It then proceeds to line 13 and
exits.
4. p0 runs line 13.
5. At this point the system is in a state of deadlock. Any process
attempting to enter the CS will be stopped by line 4.
32