Peterson`s Algorithm Properties State Diagram

Peterson’s Algorithm
(For Two Processes)
Process1
Process2
while(TRUE){
while(TRUE){
D12=1;
D21=1;
T12=0;
T12=1;
D21=0 + T12=1 while (D21=1&&T12=0);
D12=0 + T12=0 while (D12=1&&T12=1);
CRIT1;
CRIT2;
D12=0’;
D21=0’;
P1;
P2;
}
}
D12 = 1 D="region of desire" D21 = 1
D12 = 0 I="region of indifference" D21 = 0
Properties
If both Processes 1 and 2 are in their D="region of desire" then D21 = D12 = 0. So the
only entry for either to its CRIT is throughT12. If T12 =1 Process 1 can enter. If T12 = 0
Process 2 can enter. However, just before CRIT each Processes sets T12 in a way such
that the other can enter. Therefore the first one to reach T12 sets it so the second can
enter and the second sets it so the first can enter, after which the first enters. (If each
process set T12 so it itself could enter then both could enter and that is forbidden)
1) If both Processes are in their D="region of desire" the first to set T12 will pass
through its while into its CRIT , but only after the other has set T12. That other will
be blocked from entering its CRIT. The state will become C,D or D,C
As soon as Process 1/2 leaves CRIT it sets D12,/D21 = 0, and so Process 2/1 can enter its
CRIT. If Process 1/2 is in I="region of indifference" D12/D21 = 0, and so process 2/1 can enter
its D="region of desire" and then its CRIT , that is it can enter D,I or I,D then onto C,I or I,C.
2) If one process is in its I="region of desire", the other process can be anywhere and
can always pass through its while into its CRIT.
From C,I/I,C--As soon as Process 1/2 leaves CRIT it sets D12,/D21 = 0, and so Process 2/1
can enter its I, thus state I,I, or Process 2/1 can enter their D thus state C,D/D,C.
State Diagram-Possible States
D --> C
D,D
D --> C
D,C
C,D
C --> I
D,I
I,D
D --> C
C,I
I,C
C --> I
I --> D
I --> D
except initially this
is the way to D,D
and rule 1) holds
I --> D
Figure 1: Peterson’s Algorithm: Major Features
I,I
1
proc X
proc Y
0
proc Z
down(m) 0
down(m)
0
down(m)
up(m)
up(m)
end
up(m)
end
read
end
proc X
proc Y
0
0
proc Z
down(m) 0
down(m)
up(m)
down(m)
up(m)
end
up(m)
end
read
end
proc X
proc Y
proc Z
Process Tables
OPERATING SYSTEM
Figure 2: Semaphore Process-CPU Occupancy Trace
2
OP SYS
PROCESSES
B
A
R
A=active
(running
In CPU)
B=blocked
(Waiting)
R= Ready
to run
s
t
a
t
e
proc X
A
s
t
a
t
e
proc Y
R
s
t
a
t
e
proc Z
R
down(m);[a]
a__
A r_
R
A r_
sema- return
phor addresses
m
mlist
1
1
0
R
A down(m);[z]
B z_
r
r,z
z
A s_
_
R s_
R
A ___
z
z,s
R s_
A s_
A down(m);[y]
B y_
z,y
A___
up(m)
R y_
A t_
R t_
z
z,y,t
z,t
A y_
up(m)
R t_
t_
A___
A w_
R w_
A read()
R
w_
B
A
w_
B z_
R z_
z,t,w
z ,w
z,w
z
A end
B
R z_
A z_
0
A up(m)
1
Figure 3: Semaphore Process-State Stack Trace
z
3
OPERATING
SYSTEM
Process A1
1 Process B
y=2, x=0
down(x)
2
x=0
x>0
y=2, x=0
down(y)
y=0
y>0
Block(y)
y=y-1
Block(x)
RegionB
4
up(y)
y=1,x=0
y=y+1
RegionA1
up(x)
x=x+1
x=1
UnBlock(x)
1 Process
x=x-1
UnBlock(y)
1 Process
possible
overlap
RegionA2 &
RegionA1
y=1, x=1
Process A2
3
5
y=1, x=1
down(y)
y=0
y>0
Process B
y=1, x=1
down(x)
Block(y)
y=y-1
y=0,x=1
possible
overlap
RegionB &
RegionA1
x=0
x>0
Block(x)
x=x-1
x=0
RegionB
RegionA2
up(y)
x=x+1
up(x)
y=y+1
y=1+1=2
UnBlock(y)
1 Process
x=2
UnBlock(x)
1 Process
y=n=2, x=0
y=0, x=2
Process A1
6
7
Process B
y=0, x=2
down(y)
y=0
y>0
Block(y)
y=0, x=2
Block(x)
x=0
x=1
y=y-1
RegionA2
up(x)
down(x)
x=x-1
y=0, x=1
RegionB
x=x+1
UnBlock(x)
1 Process
up(x)
y=y+1
y=0, x=1
UnBlock(x)
1 Process
If all regions are surrounded by down(bs) and up(bs) then there is
no overlap and B processes are blocked if x=0, while A processes
are blocked if y=0 and x + y = N at entry to a process. If entire
processes are thus surrounded there can be a permanent block.
Figure 4: Counting Semaphore Does Not Necessarily Provide Mutual Exclusion
4
#define N 27
semaphor mutex = 1;
semaphor empty = N;
semaphor full = 0;
PRODUCER
void producer(void)
{ int item
while(TRUE){
produce_item(&item);
down(&empty);
/* if (empty==0) BLOCK
if (empty > 0) empty = empty - 1 */
down(&mutex);
enter_item(item);
up(&mutex)
up(&full;
/* if any process is BLOCKED on semaphor full
}
UNBLOCK one, otherwise full = full+1 */
}
void consumer(void)
{ int item
while(TRUE){
down(&full)
/* if(full===0) BLOCK
if(full > 0 ) full = full - 1 */
CONSUMER
down(&mutex);
remove_item(&item);
up(&mutex);
up(&empty);
/* if any process is BLOCKED on empty semaphore
UNBLOCK one, otherwise empty = empty+1 */
consume_item(item);
}
}
empty contains a count of the number of buffer entries that are available
iif that number is 0 t wiill cause blocking in the PRODUCER.
full contains a count of the number of buffer entries that are occupied.
t will cause blocking if that number is 0 in the CONSUMER.
mutex is a binary semaphor to protect the access to the buffer.
Figure 5: Semaphore Prod-Cons Solutions
5
CONSUMER
PRODUCER
A while(TRUE)
{if(flag==0)
{produce_item(&item);
flag = 1;}
time
if(lock==0)
{lock = 1;
if (count < N)
{enter_item(&item);
count = count + 1;
flag = 0}}
lock = 0;
}
A while(TRUE)
{if(lock==0)
lock = 1;
{if (count > 0)
{remove_item(&item);
count = count - 1;
flag = 0;}}
lock = 0;
if (flag==0)
{consume_item(&item);
flag = 1;}
}
TROUBLE !
WHAT IS IT?
Figure 6: Question
6
M12
N12
M23
T1
T2
N23
Requirements
M12
N12
cons
prod
T1
T2
M23
cons
N23
enter
remove
enter
remove
Four Procedure Single Monitor
prod
M12
N12
cons
T1
prod
T2
M23
cons
N23
enter
enter
remove
remove
Two Monitors/ Two Procedures
in Each
Figure 7: Monitor Prod-Cons Requirments Solutions Schematic
7
Monitor Prod-Con1
condition bempty = 0;
condition bfull = 0;
int count = 0, N12 = 40, in = 0,out = 0;
int M12[40]
enter‘(source) {
if(count==N12)wait(bfull);
move(M12[in],source); count=count + 1;
in = in + 1%N12;
if (count==1) signal(bempty); }
remove (dest) {
if(count==0)wait(bempty);
move(M12[out],dest); count=count - 1;
out = out + 1 % N12;
if(count==N12 - 1) signal(bfull);}
End Monitor
Monitor Prod-Con2
condition bempty = 0;
condition bfull = 0;
int count = 0, N23 = 60, in = 0, out = 0;
int M23[60];
enter(source) {
if(count==N23)wait(bfull);
move(M23[in],source); count=count + 1;
in = in + 1 % N23;
if (count==1) signal(bempty); }
remove(dest) {
if(count==0)wait(bempty);
move(source,dest); count=count - 1;
out = out + 1 % N23
if(count==N23 - 1) signal(bfull); }
End Monitor
firstproducer(term) {
while(TRUE){
Prod-Con1.enter(term) /*term->M12*/ } }
take-massage-give() {
int T1, T2;
while(TRUE){
Prod-Con1.remove(T1); massage(T1);mv(T1,T2); /*M12->T1, T1->T2*/
Prod-Con2.enter(T2);
/*T2->M23*/} }
finalconsumer(item) {
while(TRUE){
Prod-Con2.remove(item); consume(item);
/*M23->item*/} }
Figure 8: Monitor Prod-Cons
8
Producer
Process
while(TRUE){
produce_item(&item)
make_msg(&m,item)
send(consumer, &m)
}
Consumer
B
Process
while(TRUE){
receive( producer,&m)
get_item(&m,&item)
consume_item(item)
}
A
R
Consumer
Producer
Execution
Execution
B
A produce_item(&item)
receive( &m)
item:m1
make_msg(&m,item) m:m1
B send(consumer, &m)
m1
UB receive( &m)
A get_item(&m,&item)
m1
consume_item(item)
A
B
produce_item(&item) item:m2
make_msg(&m,item) m:m2
send(consumer, &m)
R
m2
receive( &m)
get_item(&m,&item)
consume_item(item)
B receive( &m)
A
m2
A produce_item(&item) item:m3
R
A
B
make_msg(&m,item) m:m3
A
send(consumer, &m)
m3
m3
other
B or R
A
receive( &m)
get_item(&m,&item)
consume_item(item)
Figure 9: Send-Receive Rendevous Prod-Cons Trace
9
Consumer
Producer
Process
Process
for(i=0;i<N; i++)
send(producer, &m);
while(TRUE){
receive(producer, &x);
get_item(&m,&item);
make_msg(&m,item);
send(consumer, &m);
send(producer, &m);
consume_item(x);
}
}
Communication
Buffer
|
|
|
|
|
| m1 | ε | ε | ε |
| m1 |
| ε | ε |
| m1 | m2 | ε | ε |
Mailboxes
Execution
Execution
produce_item(&item) item:m1
B receive(consumer, &m)
|
|
i++)
send(producer, &m);
B receive(producer,
A
4
times
&m)
receive(consumer, &m)
| ε |
|
| ε |
| m2 |
| ε |
| ε |
| ε |
|
|
| C from producer
| P from consumer
C from producer
P from consumer
|
|
|
| C from producer
| ε | ε | ε | P from consumer
| m1 | |
|
|
|
| ε | ε | ε |
C from producer
P from consumer
receive(consumer, &m) ε
make_msg(&m,item) m:m2
|m1|
| |
|
| |
| ε | ε |
C from producer
P from consumer
|m1| m2 |
|
|
|
|
| ε | ε |
C from producer
P from consumer
|m1 | m2|
|
|
|
| |
| ε |
C from producer
P from consumer
|
|
|m2|
| |
|
|
| ε |
C from producer
P from consumer
|
|m2 |
| ε |
|
|
|
| ε |
C from producer
P from consumer
| |
| ε |
| |
| ε |
C from producer
P from consumer
send(consumer, &m) m2
R receive(consumer, &m)
A
receive(producer, &x) m1
send(producer, &m) ε
consume_item(ix)
|
|
|
produce_item(&item) item:m2
get_item(&m,&item) m:ε
| ε | m2 |
|
|
|
|
|
| |
| ε | ε | ε | ε |
|
|
make_msg(&m,item) m:m1
send(consumer, &m) m1
produce_item(&item) item:m3
| m1 | m2 |
R
A
| ε | ε | ε | ε |
| ε | ε | ε |
A
Consumer
Producer
A for(i=0;i<N;
|
B
while(TRUE){
produce_item(&item);
receive(consumer, &m);
m1
receive(producer, &x) m2
|
|
get_item(&m,&item)
Figure 10: Send_Recieve MailBox Buffering Prod-Cons Trace
10
USER PROCESS
The operating system provides a send and receive and a receive_s
(used in the REMOTE process). Procedures are shown that simulate
binary semaphor operations.
int msend.[3] /* msend[u/d] for either ’down’ or ’up’)
msend[sem] for the semaphor identification
msend[proc] for the process identification */
msend[proc] = This USERs processes identification;
down(x){
msend[u/d] = ’down’
msend[sem]= x
send(remote, &msend);
receive(remote,&mrec);}
up(x){
msend[u/d] = ’up’
msend[sem] = x
send(remote, &msend);
receive(remote,&mrec);}
[
REMAINDER
OF PROCESS
uses the up(x) and down(x)
semaphor operations
/*procedure using send and receive
to simulate down semaphor operation*/
/*procedure using send and receive
to simulate up semaphor operation*/
[
REMOTE PROCESS
For each [semaphor,process] pair to be handled by this remote
process, there is a list which contains all the processes sleeping
on that semaphore, and its current value--either 0 or 1.
while(TRUE){
/*receive_s(&set,&m) receive from any of
receive_s(&set,&m_user);
a set of processes given in array set*/
if(m_user[u/d]==up)
{if(list[m_user[sem], m_user[proc]) != εmpty)
{send(m_user[proc], &msg);
take_from( list[muser[sem], m_user[proc] ], sleeper); /*put process
send(&sleeper,&msg;)}
id in sleeper*/
else
{value[m_user[sem] ,m_user[proc]] = 1
send(m_user[proc],&msg);}}
if( m_user[u/d]==down)
if(value[m_user[sem], m_user[proc]]==0)
add_to( list[m_user[sem], m_user[proc] ], m_user[proc]);
else
{value[m_user[sem], m_user[proc]] = 0;
send(m_user[prod], &msg);}
}
Figure 11: Semaphore-Send_Recieve Equivalence
11
Monitor Prod-Cons /* Mutually Excusive Procedures */
semaphor bempty = 0;
semaphor bfull = 0;
int count = 0, N = 40
procedure(enter)
if(count==N) wait(bfull);
enter_item1(); count=count + 1;
if (count==1) signal(bempty);
;
procedure(remove)
if(count==0)wait(bempty);
remove_item1(item); count=count1 - 1;
if(count==N - 1) signal(bfull);
End Monitor
procedure(consumer)
while(TRUE){
Prod-Con.remove; consume(item);}
procedure(producer)
while(TRUE){
produce(item); Prod-Co.enter;}
THE FIX:
1) If the
count is 0, it is
necessary to be
assured that it
had just been 1
and became 0
by removal.
2) If the
count is N it is
necessary to be
assured that it
had just been N-1
and had become
N by entering.
In both cases
the absence of
a check results
in an exit without
an up(mutex)
cancelling the
down(mutex).
/*Prod-Cons Semaphores*/
semaphor mutex = 1;
semaphor bempty = 0;
semaphor bfull = 0;
int count = 0, N = 40;
int prod=0, cons0;
procedure(enter)
prods=1;
down(mutex);
if(count==N) { up(mutex); down(bfull);}
enter_item1(); count=count + 1;
ENTER
if (count==1 ) { up(bempty); exit;};
cons=0;
up(mutex);
&&cons==1
procedure(remove)
cons=1;
down(mutex);
if(count==0){ up(mutex); down(bempty);}
REMOVE remove_item1(item); count=count1 - 1;
if(count==N - 1 ) { up(bfull);exit;}
prods=0;
up(mutex)
&&prods==1
Figure 12: Semaphore-Monitor Equivalence
TROUBLE
(arrises if a signal
can occur though
no corresponding
wait exists)
initially:
mutex = 1
count = 0
then do:
ENTER, and
leave through
up(bempty);exit
So:
mutex = 0
count = 1
and no
procedure can
get beyonf its
down(mutex):
A General Fix Is
Given in Green.
Only 1 is needed
if initially count is
0
12
item
down
down
enter
up
up
down
down
rmv
up
up
item
down
down
rmv
up
up
item
mutex
item
down
down
enter
up
up
BUFFER
PRODUCERS
Processes
CONSUMERS
Processes
check
=0 -> sleep
>0 -> -1
+1, awake
sleeper
empty cnt
full cnt
+1, awake
sleeper
check
=0 -> sleep
>0 -> -1
Op Sys Address Space (Global Memory)
Process Address Space
Figure 13: Use Of Memory In Consumer-Producer Solution With Semaphors
13
P1’
P2’
P1
P2
proc=P2
me=0
down(me)
2
3
4
me=1
proc=P1
1
down(me)
2
me=1
proc=P1’
me=0
proc=P1
1’
down(me)
1
up(me)
3
up(me)
up(me)
end
end
OP SYS 2
OP SYS 1
Disable Interupts
Disable Interupts
4
lock
lock
sleepers on (me)?
yes
no
Awaken(proc)
proc=P2
4
lock
down or up
down or up code
protected by TSL(lock)
sleepers on (me)?
X proc SLEEPs
me=0
3
cmp (me)
jze X
me <- me +1
me <- me -1
P2 sleeps
on me
lock
lock
cmp (me)
jze X
me=1 me <- me +1
down
up
down
up
yes
no
busy
waits
me=0
me <- me -1
X proc SLEEPs
Awaken(proc)
1
1’
P1’ sleeps
on me
me
lock
sleepers
Process Tables
P1 P2 P1’P2’
SHARED Memory
pg 119 2nd edition Tannenbaum
Figure 14: Implementation Of Semaphores--Common Memory, 2 CPUs
14
DINING PHILOSOPHERS
If a philosopher is Hungry and finds that at least one of its chopsticks are unavailable
(at least one of its neighbors is Eating, it waits. It can only be restarted by another
process which must be one of those that it found Eating and has now finishied Eating
Note; This solution still leaves the possibility of starvation--explain?
Monitor F
The process for the ith philosopher is:
while(TRUE){
think();
F.getchopsticks(i);
Eat();
F.putforks(i);
}
int i;
int q(N);
cond s(N);
int T=1, H=2, E=3;
xi+k
getfork(i) {
q(i) = H;
if (q(i-1)==E ++ q(i+1)==E)wait(s(i));
q(i) = E; }
putfork(i) {
q(i) = T;
if (q(i+1)== H && q(i+2)!=E)signal(s(i+1));
if (q(i-1) == H && q(i-2) !=E)signal(s(i-1));}
x
i
x
i-k
End Monitor
DATABASE (Many Readers, One Writer)
If any reader is active the writer must wait. If writer is waiting
and the number of readers goes to 0 the writer writes.
Monitor RW
int rc; [rc = number of readers]
The process for the ith reader is:
while(TRUE){
RW.pre_read();
read_database();
RW.post_read();
use_data();
}
The writer process
int state=0;
cond db;
pre-read() {
rc = rc+1;}
post-read() {
rc = rc-1;
if (rc==0)signal(db);}
try_write() {
if (rc > 0)wait(db);
write_database();}
while(TRUE){
produce_data();
RW.try_write();
}
End Monitor
SLEEPING BARBER
Similar to the Prod_Cons Monitor BC
The process for the barber is:
while(TRUE){
BC.barber_checks();
cut_hair();
}
The process for the ith customer is:
BC.customer;
int chairs=0; [ chairs = # of cust
cond custnum; -omers awaiting
haircuts ]
barber_checks() {
if (chairs==0)wait(custnum);
chairs = chairs-1;}
customer() {
if (chairs<N)chairs = chairs+1;
if (chairs==1)signal(custnum);}
End Monitor
Figure 15: Classics By Monitor: Dining Philosophers, Readers-Writer, Sleeping Barber
xv
List of Figures
Figure 1: Peterson’s Algorithm: Major Features
Figure 2: Semaphore Process-CPU Occupancy Trace
Figure 3: Semaphore Process-State Stack Trace
Figure 4: Counting Semaphore Does Not Necessarily Provide Mutual Exclusion
Figure 5: Semaphore Prod-Cons Solutions
Figure 6: Question
Figure 7: Monitor Prod-Cons Requirments Solutions Schematic
Figure 8: Monitor Prod-Cons
Figure 9: Send-Receive Rendevous Prod-Cons Trace
Figure 10: Send_Recieve MailBox Buffering Prod-Cons Trace
Figure 11: Semaphore-Send_Recieve Equivalence
Figure 12: Semaphore-Monitor Equivalence
Figure 13: Use Of Memory In Consumer-Producer Solution With Semaphors
Figure 14: Implementation Of Semaphores--Common Memory, 2 CPUs
Figure 15: Classics By Monitor: Dining Philosophers, Readers-Writer, Sleeping Barber
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14