Chapter 4Self-Stabilization
Self-StabilizationShlomi DolevMIT Press , 2000Draft of October 2003Shlomi Dolev, All Rights Reserved ©
Chapter 4: roadmap4.1 Token Passing: Converting a Central Daemon to
read/write
4.2 Data-Link Algorithms: Converting Shared Memory to Message Passing
4.3 Self-Stabilizing Ranking: Converting an Id-based System to a Special-processor System
4.4 Update: Converting a Special Processor to an Id-based Dynamic System
4.5 Stabilizing Synchronizers: Converting Synchronous to Asynchronous Algorithms
4.6 Self-Stabilizing Naming in Uniform Systems: Converting Id-based to Uniform Dynamic Systems
Token Passing: Converting a Central Daemon to read/write
• Distributed Daemon – activates a selected set of processors simultaneously to execute a computation step
1
43
2
state1
state4
state2
state3
• Central Daemon – is a special case of Distributed Daemon in which the set is of exactly 1 processor
• Synchronous System – is a special case in which the set consists all the processors in the system
The Daemon chooses a set of processors
Each processor in the set simultaneously reads from its neighbors…
… and then all write their new state
The use of Central Daemon• The literature in self-stabilizing is rich in
algorithms that assume the existence of powerful schedulers
WHY ?1. Dijkstras’ choices in the first work in the field2. The assumption of the existence of a daemon
enables the designer to consider only a subset of the possible execution set
• An algorithm designed to work in read/write atomicity can be used in any system in which there exists a daemon but the reverse wont work
Compiler
• An algorithm designed to stabilize in the presence of distributed daemon must stabilize in a system with central daemon
CompilerAL for T
(daemon)AL for T
(read/write)
• All the above facts are our motivation for designing a compiler:
1. Compose a spanning tree using the Spanning Tree Construction algorithm
Al for T (read/write) = Al for T (daemon) ◦ Mutual Exclusion
• How does the compiler work ?
Converting
2. Construct an Euler tour on the tree to create a virtual ring for the Mutual Exclusion algorithm3. A processor that enters the critical section reads the state of its neighbors changes state and writes, then it exits the critical section
Chapter 4: roadmap4.1 Token Passing: Converting a Central Daemon to
read/write
4.2 Data-Link Algorithms: Converting Shared Memory to Message Passing
4.3 Self-Stabilizing Ranking: Converting an Id-based System to a Special-processor System
4.4 Update: Converting a Special Processor to an Id-based Dynamic System
4.5 Stabilizing Synchronizers: Converting Synchronous to Asynchronous Algorithms
4.6 Self-Stabilizing Naming in Uniform Systems: Converting Id-based to Uniform Dynamic Systems
Designing a self-stabilization algorithm for asynchronous message-passing systems is more subtle than the same task in shared memory systemsMain difficulty :The messages stored in the communication links– No bound on message delivery time – No bound on number of messages that can be in
link
There are infinitely many initial configurations from which the system must stabilize
Converting Shared Memory toMessage Passing
Converting Shared Memory toMessage Passing
•Our main goal is designing of compiler:
CompilerAL for T
(read/write)AL for T
(message passing)
•First goal in designing of such a compiler is a self-stabilizing data-link algorithm
Definition of Self-Stabilizing Data-Link Algorithm
•Data-Link Algorithm : Messages fetched by sender from network layer should be delivered by receiver to network layer without duplications, omissions or reordering
•One of the implementations of data-link task is the token-passing algorithm
•Token-passing task is a set of executions TP
•The legal execution of TP is the sequence of configurations in which :
- No more than one processor holds the token
- Both the sender and receiver hold the token in infinitely many configurations
Unbounded solution of TP taskSender:
01 upon timeout
02 send (counter )
03 upon message arrival
04 begin
05 receive (MsgCounter)
06 if MsgCounter ≥ counter then
07 begin
08 counter := MsgCounter + 1
09 send (counter)
10 end
11 else send (counter)
12 end
A timeout mechanism is used to ensure that the system will not enter to communication-deadlock configuration
Each message has integer label called MsgCounter
Sender ( and Receiver ) maintains an unbounded local variable called counter
Unbounded solution of TP task
Receiver:
13 upon message arrival
14 begin
15 receive (MsgCounter)
16 if MsgCounter ≠ counter then
17 counter := MsgCounter
18 send (counter)
19 end
Token arrives
Token released
In safe configuration of TP and the algorithm - counter values of all messages and values of the counters of sender and receiver, have the same value (lemma 4.1)
The algorithm is self-stabilizing
For every possible configuration c , every fair execution that starts in c reaches a safe configuration with relation to TP (Theorem 4.1)
Question : Whether the unbounded counter andlabel can be eliminated from the
algorithm ?
Answer : NO
Lower Bound on the System Memory
•The memory of the system in configuration c is the number of bits for encoding state of sender, receiver, and messages in transit.
•Weak-Exclusion task (WE): In every legal execution E, there exists a combination of steps, a step for each processor, so that these steps are never executed concurrently.
• We will prove that there is no bound on system memory for WE task .
Lower Bound on the System Memory
Theorem: For any self-stabilizing message driven protocol for WE task and for any execution E’ in WE all the configurations are distinct.
Hence for any t > 0, the size of at least one of the first t configurations in E is at least log2(t)
Proof of Theorem
Sender sending…
Receiver acknowleging…
c1
c1
s1 r1
Sender Ps Receiver Pr
s1 r1
qs,r(c1) qr,s(c1)
qSr,s(E)qSs,r(E)
E
Any execution E’ in which not all the configurations are distinct has circular sub-execution E = (c1,a2,….,cm) where (c1=cm)
cm=
Proof - Building CE and cinit
•Let E – be circular sub-execution
•Si - sequence of steps of Pi
•CE – set of circular executions
•Each execution in CE – merge of Si’s , while keeping their internal order
•We obtain initial configuration of Ec in CE from c1 of E, and sequence of messages sent during E
cinitr1s1 qr,s(c1)
qs,r(c1)qSs,r(E) qSr,s(E)
cinit r1s1 qr,s(c1)
qs,r(c1)qSs,r(E) qSr,s(E)
qr,s(c1) qSr,s(E) qSr,s(E)
Receiver recieves… qRs,r(E)
Receiver sends… qSr,s(E)
qr,s(c1)
qs,r(c1)cinitr1s1
qSs,r(E) qSr,s(E)
Sender recieves… qRr,s(E)
Sender sends… qSs,r(E)
Proof - Possible execution in CE
E steps
•Sender steps during E is Ssender = {a1,a2…am}
•Receiver steps during E is Sreceiver = { b1,b2…bk }
•For any pair <ai, bj> there exists E’’CE in which there is configuration c, such that ai and bj is applicable in c c is not safe configuration
Proof – cont…
cinit
c
a1
a2
…
ai-1
b1
b2
…
bj-1
ai & bj
Proof – cont…
If self-stabilizing algorithm AL for WE task have circular sub-execution E exists infinite fair execution E∞ of AL , none of whose configurations is safe for WE
E’:
cinit cinit cinit
E’ from CE(E) E’ from CE(E) …
c1
Proof – cont…
•Let assume in contradiction that c1 is safe
•Then let’s extend E’ to E∞ by E1 , E2 , … , Ek - executions from CE(E)
E∞ :
•For each pair < ai, bj > there is c’ in E∞ so that both ai, bj applicable in c’ c’ is not safe
•The proof is complete!
cinit cinit cinitc1 …
E1• E2• … • Ek
c’
Bounded-Link Solution
•Let cap be the bound on number of the messages in transit
•The algorithm is the same as presented before with counter incremented modulo cap+1
08 counter := (MsgCounter + 1)mod(cap+1)
•Sender must eventually introduce a counter value that not existing in any message in transit
Randomized Solution•The algorithm is the same as original one with counter chosen randomly
08 label := ChooseLabel(MsgLabel)
• At least three labels should be used
•The sender repeatedly send a message with particular label L until the a message with the same label L arrives
•The sender chooses randomly the next label L’ from the remaining labels so that L’ ≠ L
Self-Stabilizing Simulation of Shared Memory
•The heart of the simulation is a self-stabilizing implementation of the read and write operations
•The simulation implements these operations by using a self-stabilizing, token passing algorithm
•The algorithm run on the two links connecting any pair of neighbors
• In each link the processor with the larger ID acts as the sender while the other as the receiver (Remind: all processors have distinct IDs)
Self-Stabilizing Simulation of Shared Memory - cont…
• Every time Pi receives a token from Pj. Pi write the current value of Rij in the value of the token
• Write operation of Pi into rij is implemented by locally writing into Rij
• Read operation of Pi from rji is implemented by:1. Pi receives the token from Pj
2. Pi receives the token from Pj. Return the value attached to this token
Self-Stabilizing Simulation of Shared Memory - Run
Rij Rji
PiPj
t | value = z
Write Operation: Pi write x to rij
Rij=X
Read Operation: Pi read from value y from rji
t+1 | value = z
t+1 | value = Y
Pi writes to Rij 1. Pi receive token from Pj
2. Pi send token to Pj4. Pi receive token from Pj and read the value of the token
t+1 | value = y
3. Pj receive token from Pi and write Rji to value of the token
Rji = Y
Chapter 4: roadmap4.1 Token Passing: Converting a Central Daemon to
read/write
4.2 Data-Link Algorithms: Converting Shared Memory to Message Passing
4.3 Self-Stabilizing Ranking: Converting an Id-based System to a Special-processor System
4.4 Update: Converting a Special Processor to an Id-based Dynamic System
4.5 Stabilizing Synchronizers: Converting Synchronous to Asynchronous Algorithms
4.6 Self-Stabilizing Naming in Uniform Systems: Converting Id-based to Uniform Dynamic Systems
Converting an Id-based System to a Special-processor System
• Our goal is to design a compiler that converts self-stabilizing algorithm for a unique ID system to work in special processor system.
• The ranking (compiler) task is to assign each of the n processors in the system with a unique identifier in the range 1 to n.
Converting an Id-based System to a Special-processor System
We will form the self stabilizing ranking algorithm by running 3 self-stabilizing algorithms one after the other:
1) Self-Stabilizing spanning tree construction (section 2.5)
2) Self-Stabilizing counting algorithm3) Self-Stabilizing naming algorithm
Special processor system
Unique Id’s system
Spanning tree const.
Counting algorithm
Naming algorithm
Self-Stabilizing Counting Algorithm
• Assuming rooted spanning tree system in which every processor knows its parent and children's
• Pi has a variable counti that hold the number of processor in sub-tree where Pi is a root
• The correctness proofs by induction on the height of a processor
Self-Stabilizing Counting Algorithm01 Root: do forever
02 sum:= 0
03 forall Pj children(i) do
04 lrji := read(rji)
05 sum := sum + lrji.count
06 od
07 counti = sum + 1
08 od
09 Other: do forever
10 sum:= 0
11 forall Pj children(i) do
12 lrji := read(rji)
13 sum := sum + lrji.count
14 od
15 counti = sum + 1
16 write ri,parent.count := counti
17 od
Calculate counti: sum the values of rji registers of his child’s and 1 (himself)
Write local count value to communication register
Self-Stabilizing Naming Algorithm
• The naming algorithm uses the value of the count fields from counting algorithm.
• Algorithm assign unique identifiers to the processors.
• The identifier of a processor is stored in the IDi variable.
• Proof of the stabilization by induction on the distance of the processors from the root
Self-Stabilizing Naming Algorithm01 Root: do forever
02 IDi:= 1
03 sum := 0
04 forall Pj children(i) do
05 lrji := read(rji)
05 write rij.identifier := Id + 1 + sum
06 sum := sum + lrji.count
08 od
09 od
10 Other: do forever
11 sum:= 0
12 lrparent,i := read(rparent,I)
13 IDi := lrparent,I.identifier
14 forall Pj children(i) do
15 lrji := read(rji)
16 write rij.identifier := Idi + 1 + sum
17 sum := sum + lrji.count
18 od
19 od
Ranking Task Run
Counti :=IDi :=
Counti :=IDi :=
Counti :=IDi :=
Counti :=IDi :=
Counti :=IDi :=
Counti :=IDi :=
Counti :=IDi :=
Counti :=IDi :=
r.id= r.id=
r.id=
r.id=
r.id=
r.id=
r.id=Counti := 1IDi :=
Counti := 1IDi :=
Counti := 2IDi :=
Counti := 1IDi :=
Counti := 2IDi :=
Counti := 3IDi :=
Counti := 2IDi :=
Counti := 8IDi :=
Counti := 8IDi := 1
r.id=2
r.id=4
r.id=6
Counti := 2IDi := 4
Counti := 1IDi := 5
Counti := 2IDi := 2
r.id=3Counti := 3IDi := 6
r.id=7
Counti := 2IDi := 7
r.id=8Counti := 1IDi := 3
Counti := 1IDi := 8
1
2
43
6
5 7
r.id=5
8
1
2
3 4
5
6
7
Counting Algorithm for non-rooted tree
01 do forever
02 forall Pj N(i) do lrji := read (rji)
03 sumi := 0
04 forall Pj N(i) do
05 sumj := 0
06 forall Pk N(i) do
07 if Pj != Pk then
08 sumj := sumj +lrki.count
09 od
10 counti[j] := sumj + 1
11 sumi := sumi + sumj
12 write rij.count := counti[j]
13 od
14 counti = sumi + 1
15 od
Each processor Pi has a variable counti[j] for every neighbor Pj
The value of counti[j] is the number of processors in subtree of T to which Pi belongs and Pj doesn’t.
The correctness proof is by induction on the height of the registers rij
Counting Algorithm for non-rooted tree Run
Counti[j]=3
Counti[1]=2
Counti[j]=5
Counti[j]=2
Counti[j]=1
Counti[j]=3Counti[j]=5
Counti[j]=3Counti[j] =3
Counti[1]=7
Counti[1]=6
Counti[1]=2
Counti[1]=7
Counti[j] =1
Counti[j]=2
Counti[j]=4
Counti[1]=1
Counti[j]=6
Counti[j]=5Counti[j]=6Counti[j] =4
Counti[j]=7
Chapter 4: roadmap4.1 Token Passing: Converting a Central Daemon to
read/write
4.2 Data-Link Algorithms: Converting Shared Memory to Message Passing
4.3 Self-Stabilizing Ranking: Converting an Id-based System to a Special-processor System
4.4 Update: Converting a Special Processor to an Id-based Dynamic System
4.5 Stabilizing Synchronizers: Converting Synchronous to Asynchronous Algorithms
4.6 Self-Stabilizing Naming in Uniform Systems: Converting Id-based to Uniform Dynamic Systems
Update - Converting a Special Processor to an Id-based Dynamic
System• The task of the update algorithm in id-based
system is to inform each processor of the other processors that are in its connected component.
• As a result every processor in the connected component knows the maximal identifier in the system, and a single leader is elected.
• The update algorithm is a self-stabilizing leader election algorithm within O(d) cycles (pulses).
The motivation for the restriction that the update must work in id-based system can be viewed by examining Dijkstra self stabilizing
ME algorithm for a ring of processors…
• Dijkstra proved that without a special processor, it is impossible to achieve ME in a self-stabilizing manner
• The impossibility proof is for composite number of identical processors connected in a ring activated by a central daemon
Dijkstra proof
ME requires that processor Pi should execute the critical section if and only if it is the only processor that can change its state (by reading its neighbors’ states) at
that execution point
S0
•Then, p1 and p3 will be at S1, p2 and p4 will be at S1’. •We can see that symmetry in state is preserved
Dijkstra proof
S1
p4
p3
p2
p1
S0
S0’S0’
S1
S1’S1’
P1 ,P3 ,P2 ,P4 …
•Consider P1,P3 starting in the same state S0, P2,P4 starting in the same state S0’
And execution order is:
Conclusions from Dijkstra’s proof• Whenever P1 has permission to execute critical
so does P3. (Like that for P2 and P4).• With no central daemon the impossibility result
of self-stabilizing ME algorithm holds also for a ring of prime number of identical processors.We start in a configuration that all the processors are in the same state, and the contents of all the registers are identical. An Execution that preserve that symmetry forever is one that every processor reads all neighbors registers before any writing is done.
The restriction for designing the update algorithm in an id-based (not identical)
system is thus clear.
The Update algorithm outlines• The algorithm constructs n directed
BFS trees. One for every processor. 1. Each processor Pi holds a BFS tree rooted at Pi.
2. When a node Pj with distance k+1 from Pi has more than one neighbor at distance k from Pi, Pj is connected to the neighbor (parent) with the maximal ID.
3. Each Pi reads from his δ neighbors their set of tuples <j,x> where j represents a processor id, and x is the distance of j from the processor that holds this tuple.
4. Pi tuples are computed from these neighbors’ sets, adapting for each ji the tuple <j,x> with the smallest x and adding 1 to x. Pi also adds the tuple <i,0> indicating the distance from itself. At the end of the iteration, Pi removes the floating (false) tuples.
Update algorithm
01 do forever02 Readseti :=Ø03 forall PjN(i) do04 Readseti := Readseti read(Processorsj)05 Readseti := Readseti \\ <i,*>06 Readseti := Readseti ++ \\<*,1>07 Readseti := Readseti {<i,0>}08 forall Pj processors(Readseti) do09 Readseti := Readseti\\ NotMinDist(Pj, Readseti) 10 write Processorsi := ConPrefix(Readseti)11od