Herlihy
Use when atomicizing any subsystem or removing a concurrency constraint — a lock, a Mutex/RwLock, a blocking wait, a serialization point, a step-barrier, a GIL-serialized scheduler. Triggers on "make this lock-free", "atomicize this", "rewrite this atomic", "which atomic primitive", "CAS or fetch-add", "is this actually wait-free / lock-free", "prove this concurrent path correct", "how do I safely reclaim this memory under lock-free readers", or designing a KV cache / scheduler / commit / free-list / ring on hardware atomics. This is the Herlihy doctrine: pick the primitive by consensus number, fix the linearization point, choose the progress guarantee by whether a token can wait, pick the reclamation scheme by reader lifetime, and know the impossibility walls before burning a run. Reach for it by default whenever a token-flow path must be non-blocking; skip only for genuinely single-threaded code with no shared mutable state.From its SKILL.md
npx -y skills add 88plug/herlihy --skill herlihyAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
3 things to look at
- 25 days oldThe repository was created 25 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
7.5 KB, ~1.7k tokens by cl100k_base, as published. Nobody here has run it
The Herlihy Doctrine
Named for Maurice Herlihy, who founded wait-free synchronization. This skill turns "everything atomic" from a slogan into a procedure grounded in his published results — so every atomicize/rewrite picks the sound primitive, has a provable correctness point, claims the true progress guarantee, and never chases something topology forbids.
Before writing the concurrent code, invoke read-the-damn-docs for the exact
atomic API in play (Rust std::sync::atomic orderings, CUDA atomicCAS/
atomicAdd semantics, the memory model). A wrong memory ordering is a
Heisenbug that a parity gate catches only sometimes — ground it in the docs.
The scholarship (verified primary sources, with the NOT-Herlihy flags) lives in
references/corpus.md. Read it before citing any result — misattributing a
technique to Herlihy is the exact overclaim this skill exists to prevent.
The core move: constraint → atomicize
Given a constraint (a lock, a blocking wait, a serialization/step-barrier), rewrite it atomic by running these seven rules in order. Each rule is grounded in a specific Herlihy result — cite it, don't assert it.
-
Name the constraint's consensus need. Does the rewrite require multi-party agreement — who wins a slot, who commits, who retires exactly once? If yes, the primitive floor is CAS. (Consensus-number hierarchy — Herlihy, "Wait-Free Synchronization", TOPLAS 1991.)
-
Pick the minimum sound primitive. Monotonic reservation / counters → fetch-add (consensus number 2). Any contended commit or reclaim → CAS (consensus number ∞). Never fetch-add where agreement is needed — two "winners" is a latent correctness bug. Never CAS a pure counter — a wasted retry loop. (Herlihy 1991.)
-
Check the impossibility wall first. A CAS-free (read/write/fetch-add-only) fast path for any contended commit is provably impossible wait-free. Don't burn a run inventing one. CAS (∞) is exactly the primitive that buys you out of the register wall. (Topological computability — Herlihy & Shavit, JACM 1999, Gödel Prize.)
-
Fix the linearization point = the single atomic step. Every fast path gets exactly one instant — the successful CAS or the release-store — where its effect becomes visible. A reader seeing old state must see a legal pre-commit history. Linearizability is local: prove each object at its point, and whole-engine correctness composes for free. (Herlihy & Wing, TOPLAS 1990.)
-
Choose the progress guarantee by whether a token can wait. Token-flow paths target wait-free. But upgrade a lock-free path to wait-free (via helping) only where measured starvation exists — helping costs an announce-scan on every op. Most paths at low concurrency are fine lock-free. (Universal construction / helping — Herlihy 1991; progress lattice — Herlihy & Shavit, OPODIS 2011.)
-
Reduce multi-word to one word before reaching for transactions. Prefer a version-pointer / index swap that makes the commit a single CAS (wait-free) over STM/HTM (only lock-free — abort/retry, livelock-prone, and there is no HTM on the GPU decode path). (Transactional Memory — Herlihy & Moss, ISCA 1993 — as a design lens, not a hot-path kernel.)
-
Pick reclamation by reader lifetime. Bounded, non-stalling readers (GPU decode kernels, one step long) → epoch-based reclamation (tick an epoch per step, free blocks retired ≥2 epochs back). Cite Pass-the-Buck as the canonical safe-reclamation lineage; use its per-guard handoff only if readers can stall unboundedly (not our case). (Repeat Offender / Pass-the-Buck — Herlihy, Luchangco, Moir, DISC 2002, Dijkstra Prize 2022. EBR itself is Fraser 2004 — NOT Herlihy.)
Per-subsystem map (LLM-inference)
Match the subsystem to the right result, progress guarantee, and linearization point. This is the reference for atomic-inference; the shape generalizes.
| Subsystem | Result to apply | Progress | Linearization point |
|---|---|---|---|
| KV cache slot commit | Linearizability + CAS (∞) | Wait-free | Release-store of ready/tail |
| Scheduler / mid-step admission | Universal construction (announce+help) | Lock-free → wait-free if starved | Winning CAS on running-set splice |
| MTP commit | Single-CAS reduction (consensus ∞) | Wait-free | Successful committed_len CAS |
| KV-block reclamation | Pass-the-Buck lineage → EBR | Lock-free (reclaimer) | Epoch-tick store |
| Request ring | Michael-Scott queue (NOT Herlihy) | Lock-free | fetch-add slot index |
| On-device sampling | Linearizability discipline | Wait-free | Single argmax CAS/store |
The honest hot-path caveat (read before you build)
Two Herlihy constructions are correctness references, not hot-path kernels:
- The universal construction (announce + consensus + help) proves any sequential object can be made wait-free — but its O(n) announce-scan per op serializes throughput. Borrow the helping idea and the proof, not the literal construction. Ship a bespoke single-CAS / fetch-add structure.
- Transactional memory gives multi-word atomicity but pays abort/retry and has no GPU-decode implementation. Reduce to one word instead.
Where a hand-rolled lock-free structure already gives the needed progress (a
Treiber stack for the free-list, an MS-queue for the ring — both not Herlihy,
see corpus.md), use it. The doctrine tells you which primitive is sound and
which guarantee you actually have — it is not a mandate to build the general
construction literally.
Audit rubric (labeling an existing path's true guarantee)
Cheap, high-value — run it before claiming any path is "lock-free":
- Single CAS / single release-store, bounded retries → genuinely wait-free.
- CAS-loop that can livelock under contention → only lock-free (or obstruction-free) — do not call it wait-free.
- Any Mutex / RwLock / epoch barrier / blocking wait on the path → it is blocking, not non-blocking. That is the constraint to rewrite.
Over-claiming a progress guarantee is the concurrency equivalent of an unscoped "world-first" — the same honesty discipline applies. Label the true class, then upgrade only the paths a token actually waits on.
The one-sentence version
Name what needs agreement, pick CAS if it does and fetch-add if it doesn't, give the commit one visible instant, claim only the progress you can prove, free memory by epoch, and never chase a wait-free path topology already ruled out.
What ships with it: 1 file
6.2 KB alongside SKILL.md
references/
- corpus.md6.2 KB