BundleUnbundle_2level_LLfree_dynamic.tla / _3level_LLfree_dynamic.tlaThe dynamic mode of the LLfree Layer 2 spec: it adds runtime
child insertion (insert(online=true)) and release (release).
The tree structure is no longer fixed; it mutates dynamically each iteration.
Priority gating (CanProceed / TagAfterFail / TagAfterSuccess / PreemptTag / ClearMyTags)
is identical to 2-level LLfree — see also slides_layer2_LLfree.html for tree-structure detail.
Both children start unattached (their own priority wrappers).
Phase 1 attaches via insert; Phase 2 interleaves commit + release.
| Role (CONSTANT) | Behavior |
|---|---|
InsertThreads | Run insert(online=true) — pick an uninserted child and attach to Parent |
RootThreads | Run CommitParent — snapshot Parent, increment every discovered child's payload |
LeafThreads | Run CommitChild — direct commit per child discovered in the snapshot |
ReleaseThreads | Release children (only after own commits are done) |
Dynamic discovery is key: children are not hardcoded; commit targets come from the snapshot. This covers boundary races such as "commit while a half-constructed insert is in flight" and "commit just before release."
\* Insert is split into 5 actions so TLC explores every
\* half-constructed-insert interleaving (target: \E c : ~inserted[c]).
InsertStart → InsertCASParent → InsertReadChild →
InsertCASChild(t): linkage'[c] = InsertedRef(Parent, ser, cpkt) \* packet-carrying ref
InsertFinal(t): linkage'[Parent] = PriorityWrapper(
MakePacket(Parent, _, newSub, TRUE), ser) \* SEPARATE CAS, missing=TRUE
\* on success: inserted'[c]=TRUE, ClearMyTags(t)
ReleaseStart → ReleaseCASParent → ReleaseReadChild → ReleaseCASChild
\* the Parent-slot CAS and the child-slot CAS are SEPARATE actions;
\* the two CanProceed gates (Parent / c) live in different steps.
Interference between insert and bundle/commit:
If another thread runs bundle(Parent) while insert(c) fires,
the Phase-4 CAS fails its freshness check (the parent linkage changed)
→ retry; the bundling thread sees the newly inserted child on re-collect. (No reachability gate exists in the dynamic specs — that is hardlink-only.)
Priority gating arbitrates between the inserter and the bundler by transaction age.
| Item | Static (_LLfree.tla) | Dynamic (_LLfree_dynamic.tla) |
|---|---|---|
| Child set | Fixed from init (Child1, Child2) | Dynamically inserted / released (DynChild1, DynChild2) |
| New actions | — | Insert* (5-step) / Release* (4-step) pipelines |
| Thread roles | Root / Leaf roles (RootThreads / LeafThreads) | + Insert / Release roles (InsertThreads / ReleaseThreads) |
| Commit targets | Hardcoded | Discovered dynamically from snapshot |
| Invariants | 5 (SnapshotConsistency etc.) | + insert/release consistency checks |
| cfg | Threads | States | Depth | Time | Result |
|---|---|---|---|---|---|
| 2-level dynamic 2-thread superfine (no release) | 2 | (~M) | — | — | ✅ Pass (safety); liveness via the release run below |
| 2-level dynamic release superfine live | 2 | 413,884,516 | 320 | 7:13 | ✅ Pass + liveness (ohtaka) |
| 3-level dynamic 2-thread coarse | 2 | (M~) | — | — | ✅ Pass + liveness |
| 3-level dynamic 3-thread release | 3 | (large) | — | — | ohtaka pending |
What the 413M-state run proves: The 2-level dynamic release superfine liveness run is one of the largest verifications in the corpus. All interleavings that include dynamic insert/release satisfy safety + liveness — proven by exhaustion. Priority gating + dynamic discovery + bounded variable domains achieve CONSTRAINT-free termination.
# 2-level dynamic release superfine (ohtaka recommended)
java -XX:+UseParallelGC -Xmx32g -cp tla2tools.jar tlc2.TLC \
-workers auto -config BundleUnbundle_2level_LLfree_dynamic_release_superfine_live_mc.cfg \
BundleUnbundle_2level_LLfree_dynamic.tla
slides_layer2_LLfree.html — LLfree base specslides_layer2_LLfree_3level_en.html — 3-level LLfree diffslides_hardlink_en.html — hard-link topologies (incl. the sibling-parents dynamic variant)kamestm/tests/VERIFICATION.md §3 — latest results