[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[tlaplus] Re: Deadlock reach without invocation of main actions.
There are problems in how atomic actions are defined in spec.
Take for example
LockAcquire(tx, req, tuple) ==
/\ \A tx1 \in tupleOwners[tuple]:
/\ HasConflict(req,txRequest[tx1])
/\ (tx < tx1)
/\ SetAbort(tx1)
/\ UNCHANGED <<txActive, txRequest, tupleOwners, tupleWaiters>>
/\ AddWaiter(tx, tuple)
/\ PromoteWaiter(tuple)
AddWaiter and PromoteWaiter should be different actions. From initial state
it is not possible to get an execution trace which satisfies LockAcquire action.
AddWaiter says that in the next state `tx` will be added in waiters of `tuple` but
PromoteWaiter expects that `tx` is in waiters of `tuple` in current state by usage of
tx = Min(tupleWaiters[tuple]).
Thanks and regards
Divyanshu Ranjan
On Friday, April 19, 2024 at 9:32:46 AM UTC+5:30 Tung Nguyen wrote:
Hi!
I am trying to specify a preemptive locking protocol for multiple transactions and tuples. In which, a transaction with a smaller ID is allowed to preempt the current lock holder, and a transaction with a larger ID needs to wait for the current lock holder to release.
I want to check the liveness property of it but before that, the specification ran into a Deadlock reach but the error trace shows no invocation of any actions in Next at all (I commented out all liveness checking code). I am quite confused... Can you please kindly let me know if there is anything I did wrong?
Here is my spec:
----------------------------- MODULE WoundWait -----------------------------
EXTENDS TLC, FiniteSets, Integers, Sequences
CONSTANT txs, tuples
VARIABLE txActive, txAbort, txRequest, tupleOwners, tupleWaiters
----------------------------------------------------------------------------
Vars == <<txActive, txAbort, txRequest, tupleOwners, tupleWaiters>>
RequestType == {"SH", "EX"}
TypeOK ==
/\ \A tx \in txs: txRequest[tx] \in RequestType
/\ \A tuple1 \in tuples: tupleOwners[tuple1] \subseteq txs
/\ \A tuple2 \in tuples: tupleWaiters[tuple2] \subseteq txs
/\ txActive \subseteq txs
/\ txAbort \subseteq txs
Init ==
/\ txActive = {}
/\ txAbort = {}
/\ txRequest = [tx \in txs |-> RandomElement(RequestType)]
/\ tupleOwners = [tuple1 \in tuples |-> {}]
/\ tupleWaiters = [tuple2 \in tuples |-> {}]
----------------------------------------------------------------------------
HasConflict(req1, req2) == (req1 = "EX") \/ (req2 = "EX")
Min(W) == CHOOSE tx \in W: \A tx2 \in W: tx <= tx2
SetAbort(tx) ==
/\ txAbort' = txAbort \cup {tx}
/\ \E tx1 \in txActive:
/\ tx = tx1
/\ txActive' = txActive \ {tx1}
SetActive(tx) ==
/\ txActive' = txActive \cup {tx}
/\ \E tx1 \in txAbort: tx = tx1
/\ txAbort' = txAbort \ {tx1}
Sort(set) ==
IF set = {} THEN {}
ELSE
CHOOSE sortedSet \in SUBSET set :
/\ sortedSet \subseteq set
/\ \A x \in sortedSet, y \in sortedSet : x <= y
AddWaiter(tx, tuple) ==
/\ tupleWaiters' = [tupleWaiters EXCEPT ![tuple] = Sort(tupleWaiters[tuple] \cup {tx})]
RemoveWaiter(tx, tuple) ==
tupleWaiters' = [tupleWaiters EXCEPT ![tuple] = tupleWaiters[tuple] \ {tx}]
AddOwner(tx, tuple) ==
tupleOwners' = [tupleOwners EXCEPT ![tuple] = tupleOwners[tuple] \cup {tx}]
RemoveOwner(tx, tuple) ==
tupleOwners' = [tupleOwners EXCEPT ![tuple] = tupleOwners[tuple] \ {tx}]
PromoteWaiter(tuple) == \E tx \in tupleWaiters[tuple]:
/\ tx = Min(tupleWaiters[tuple])
/\ HasConflict(txRequest[tx],txRequest[tupleOwners[tuple]]) = FALSE
/\ RemoveWaiter(tx, tuple)
/\ AddOwner(tx, tuple)
/\ SetActive(tx)
LockAcquire(tx, req, tuple) ==
/\ \A tx1 \in tupleOwners[tuple]:
/\ HasConflict(req,txRequest[tx1])
/\ (tx < tx1)
/\ SetAbort(tx1)
/\ UNCHANGED <<txActive, txRequest, tupleOwners, tupleWaiters>>
/\ AddWaiter(tx, tuple)
/\ PromoteWaiter(tuple)
LockRelease(tx, tuple) ==
/\ RemoveOwner(tx, tuple)
/\ PromoteWaiter(tuple)
\*/\ tx' = tx + Len(txActive)
----------------------------------------------------------------------------
Next == \E tx \in txs: \E tuple \in tuples:
\/ LockAcquire(tx, txRequest[tx], tuple)
\/ LockRelease(tx, tuple)
Spec ==
/\ Init
/\ [][Next]_Vars
(*
FairSpec ==
Spec /\ \A tx1 \in txs, tuple1 \in tuples:
WF_Vars(LockAcquire(tx1, txRequest[tx1], tuple1))
/\ \A tx2 \in txs, tuple2 \in tuples:
WF_Vars(LockRelease(tx2, tuple2))
*)
----------------------------------------------------------------------------
DeadLock == \A tuple \in tuples: tupleWaiters[tuple] # txs
(*
Starvation ==
/\ \A tx1 \in txs, tuple1 \in tuples:
[]<>(<<LockAcquire(tx1, txRequest[tx1], tuple1)>>_Vars)
/\ \A tx2 \in txs, tuple2 \in tuples:
[]<>(<<LockRelease(tx2,tuple2)>>_Vars)
*)
=============================================================================
And here are the cfg:
CONSTANTS
tuples = {t1, t2, t3, t4}
txs = {1, 2, 3}
INVARIANT TypeOK DeadLock
\*SPECIFICATION FairSpec
SPECIFICATION Spec
\*CHECK_DEADLOCK FALSE
\*PROPERTY Starvation
Thank you very much!
Best,
Tung Nguyen
--
You received this message because you are subscribed to the Google Groups "tlaplus" group.
To unsubscribe from this group and stop receiving emails from it, send an email to tlaplus+unsubscribe@xxxxxxxxxxxxxxxx.
To view this discussion on the web visit https://groups.google.com/d/msgid/tlaplus/336a251f-a0ba-453b-a159-91973929895cn%40googlegroups.com.