master-degree-notes/Concurrent Systems/notes/1b - Peterson algorithm.md

139 lines
5.1 KiB
Markdown
Raw Normal View History

2025-03-08 18:06:57 +01:00
### Peterson algorithm (for two processes)
Let's try to enforce MUTEX with just 2 processes.
##### 1st attempt:
```
lock(i) :=
AFTER_YOU <- i
wait AFTER_YOU != i
return
unlock(i) :=
return
```
This protocol satisfies MUTEX, but suffers from deadlock (if one process never locks).
##### 2nd attempt:
```
Initialize FLAG[0] and FLAG[1] to down
lock(i) :=
FLAG[i] <- up
wait FLAG[1-i] = down
return
unlock(i) :=
FLAG[i] <- down
return
```
Still suffers from deadlock if both processes simultaneously raise their flag.
##### Correct solution:
```
Initialize FLAG[0] and FLAG[1] to down
lock(i) :=
FLAG[i] <- up
AFTER_YOU <- i
wait FLAG[1-i] = down OR AFTER_YOU != i
return
unlock(i) :=
FLAG[i] <- down
return
```
**Features:**
- it satisfies MUTEX
- it satisfies bounded bypass, with bound = 1
- it requires 2 one-bit SRSW registers (the flags and 1 one-bit MRMW registers (AFTER_YOU)
- Each lock-unlock requires 5 accesses to the registers (4 for lock and 1 for unlock)
##### MUTEX proof
2025-03-08 18:11:57 +01:00
>[!info]
>Remember that, in the [[#Correct solution|correct implementation]], there is this line: `wait (FLAG[1-i] = down OR AFTER_YOU != i)`. Thus, to access the critical section (the `return` instruction of the `lock` function), the possibilities are just the two discussed above.
2025-03-08 18:06:57 +01:00
2025-03-08 18:11:57 +01:00
**How has p0 entered its CS?**
2025-03-08 18:06:57 +01:00
a) `FLAG[1] = down`, this is possible only with the following interleaving:
![[Pasted image 20250303100721.png]]
b) `AFTER_YOU = 1`, this is possible only with the following interleaving:
![[Pasted image 20250303100953.png]]
##### Bounded Bypass proof (with bound = 1)
- If the wait condition is true, then it wins (and waits 0).
- Otherwise, it must be that `FLAG[1] = UP` **AND** `AFTER_YOU = 0` (quindi p1 ha invocato il lock e p0 dovrà aspettare).
- If p1 never locks anymore then p0 will eventually read `F[1]` and win (waiting 1).
- It is possible tho that p1 locks again:
- if p0 reads `F[1]` before p1 locks, then p0 wins (waiting 1)
- otherwise p1 sets A_Y to 1 and suspends in its wait (`F[0] = up AND A_Y = 1`), p0 will eventually read `F[1]` and win (waiting 1).
### Peterson algorithm ($n$ processes)
- FLAG now has $n$ levels (from 0 to n-1)
- level 0 means down
- level >0 means involved in the lock
- Every level has its own AFTER_YOU
```
Initialize FLAG[i] to 0, for all i
lock(i) :=
for lev = 1 to n-1 do
FLAG[i] <- lev
AFTER_YOU[lev] <- i
wait (∀k!=i, FLAG[k] < lev
OR AFTER_YOU[lev] != i)
return
unlock(i) :=
FLAG[i] <- 0
return
```
2025-03-08 18:16:57 +01:00
We say that: $p_i$ is at level $h$ when it exits from the $h$-th wait $\to$ a process at level $h$ is at any level $<= h$
2025-03-08 18:06:57 +01:00
2025-03-08 18:16:57 +01:00
>[!info] What is the `wait` condition actually checking?
>In the wait condition we check that all other processes are at a lower level.
2025-03-08 18:06:57 +01:00
##### MUTEX proof
2025-03-08 18:41:57 +01:00
>[!def] Lemma
>For every $ \in \{0,\dots,n-1\}$ , at most n- processes are at level , this implies MUTEX by taking = n-1
2025-03-08 18:06:57 +01:00
Proof by induction on
Base (=0): trivial
Induction (true for , to be proved for +1):
- p at level can increase its level by writing its FLAG at +1 and its index in $A_Y[+1]$
- let $p_x$ be the last one that writes `A_Y[+1]`, so `A_Y[+1]=x`
- for $p_x$ to pass at level +1, it must be that $∀k≠x. F[k] < +1$, then $p_x$ is the only proc at level +1 and the thesis holds, since 1<=n--1
- otherwise, $p_x$ is blocked in the wait and so we have at most n--1 processes at level +1: those at level , that by induction are at most n-, except for px that is blocked in its wait.
##### Starvation freedom proof
**Lemma:** every process at level ($\leq n-1$) eventually wins $\to$ starvation freedom holds by taking $=0$.
Reverse induction on
Base ($=n-1$): trivial
Induction (true for +1, to be proved for ):
- Assume a $p_x$ blocked at level (aka blocked in its +1-th wait) $\to \exists k\neq x, F[k]\geq+1 \land A\_Y[+1]=x$
- If some $p_{y}$ will eventually set $A\_Y[+1]$ to $y$, then $p_x$ will eventually exit from its wait and pass to level +1
- Otherwise, let $G = \{p_{i}: F[i] \geq +1\}$ and $L=\{p_{i}:F[i]<+1\}$
- if $p \in L$, it will never enter its +1-th loop (as it would write $A_Y[+1]$ and it will unblock $p_x$, but we are assuming that it is blocked)
- all $p \in G$ will eventually win (by induction) and move to L
- $\to$ eventually, $p_{x}$ will be the only one in its +1-th loop, with all the other processes at level <+1
- $\to$ $p_{x}$ will eventually pass to level +1 and win (by induction)
##### Peterson algorithm cost
- $n$ MRSW registers of $\lceil \log_{2} n\rceil$ bits (FLAG)
- $n-1$ MRMW registers of $\lceil \log_{2}n \rceil$ bits (AFTER_YOU)
- $(n-1)\times(n+2)$ accesses for locking and 1 access for unlocking
It satisfies MUTEX and starvation freedom. It does not satisfy bounded bypass:
- consider 3 processes, one sleeping in its first wait, the others alternating in the CS
- when the first process wakes up, it can pass to level 2 and eventually win
- but the sleep can be arbitrary long and in the meanwhile the other two processes may have entered an unbounded number of CSs
Easy to generalize to k-MUTEX.