2 KiB
2 KiB
Initial idea:
Initialize Y at ⊥, X at any value (e.g., 0)
lock(i) :=
x <- i
if Y != ⊥ then FAIL
else Y <- i
if X = i then return
else FAIL
unlock(i) :=
Y <- ⊥
return
Problems:
- we don't want the FAIL
- it is possible to have an execution where nobody accesses its CS, if repeated forever it entails a deadlock
Initialize Y at ⊥, X at any value (e.g., 0)
lock(i) :=
* FLAG[i] <- up
X <- i
if Y ≠ ⊥ then
FLAG[i] <- down
wait Y = ⊥
goto *
else Y <- i
if X = i then return
else FLAG[i] <- down
∀j.wait FLAG[j] = down
if Y = i then return
else wait Y = ⊥
goto *
unlock(i) :=
Y <- ⊥
FLAG[i] <- down
return
MUTEX proof
!
(must finished before nel senso che
p_i
deve aspettare $p_j$)
Deadlock freedom
Let p_i
invoke lock
- If it eventually wins -> √
- If it is blocked forever, where can it be blocked?
- In the second wait Y = ⊥
- in this case, it read a value in Y different from i
- there is a
p_h
that wrote Y afterp_i
- let us consider the last of such
p_h \to
it will eventually win
- In the ∀j.wait FLAG[j] = down
- this wait cannot block a process forever
- if
pj
doesn't lock, it flag is down - if
pj
doesn't find Y at ⊥, it puts its flag down - if pj doesn't find X at j, it puts its flag down, otherwise pj enters its CS and eventually unlocks (flag down)
-
- In the first wait Y = ⊥
- since pj read a value different from ⊥, there is at least one pk that wrote Y before (but has not yet unlocked)
- if
p_k
eventually enters its CS -> ok, otherwise it must be blocked forever as well. Where?- In the second wait Y = ⊥: but then there exists a
p_h
that eventually enters its CS -> good - In the ∀j.wait FLAG[j]=down: this wait cannot block a process forever
- In the second wait Y = ⊥: but then there exists a
- In the second wait Y = ⊥
esercizio: prova che NON soddisfa starvation freedom