Agent skill

Rcu Mutation

by isc-projects in isc-projects/bind9

Correct discipline for mutating an RCU / lock-free pointer-based data structure (trie, tree, list, graph) that has concurrent readers — build a new node cluster invisibly, publish it, then reclaim…

MPL-2.0Auto-check passedDevOps & Cloud

Install Rcu Mutation

skills CLI
$ npx skills add isc-projects/bind9 --skill rcu-mutation -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install isc-projects/bind9 rcu-mutation --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/isc-projects/bind9.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/rcu-mutation .claude/skills/rcu-mutation && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
rcu-mutation
GitHub stars
780
Token cost
~3.8k tokens
SKILL.md length
2,236 words
Files
1
Skills in repo
9
Repo updated
First seen
Licence
MPL-2.0

At a glance

Correct discipline for mutating an RCU / lock-free pointer-based data structure (trie, tree, list, graph) that has concurrent readers — build a new node cluster invisibly, publish it, then reclaim…

  • Works in 3 steps: Build (may fail). Allocate and fully… → Publish (must not fail). With the… → Reclaim. Free the old nodes, deferred…
  • Reviewing any mutator on a structure read concurrently under RCU (or any publish/consume scheme)
  • SKILL.md covers The three phases, Observability — the core concept, Rules that fall out and Anti-patterns (and why), plus 2 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md

What it does

Rcu Mutation is an agent skill from isc-projects/bind9. Correct discipline for mutating an RCU / lock-free pointer-based data structure (trie, tree, list, graph) that has concurrent readers — build a new node cluster invisibly, publish it, then reclaim the old nodes after a grace period. Use when writing or reviewing any mutator on a structure read concurrently under RCU (or any publish/consume scheme), especially one with allocation-failure paths.

Its SKILL.md is about 3.8k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in DevOps & Cloud. The repository describes itself as: Archived mirror of https://gitlab.isc.org/isc-projects/bind9, please submit issues and PR/MRs in the GitLab. The licence is MPL-2.0.

When your agent uses it

  • Reviewing any mutator on a structure read concurrently under RCU (or any publish/consume scheme)
  • Especially one with allocation-failure paths

Example prompts

  • “/rcu-mutation”

Workflow steps

3 steps, taken from the first numbered list in SKILL.md.

  1. Build (may fail). Allocate and fully wire the new node cluster. Touch
  2. Publish (must not fail). With the cluster fully built, perform the
  3. Reclaim. Free the old nodes, deferred (call_rcu / synchronize_rcu /

What it can do on your machine

Read from SKILL.md and the folder at commit 784d666. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md.

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Rcu Mutation loads about 3.8k tokens when it runs. Until then it costs about 102 tokens; SKILL.md has 2,236 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~102
When it runs · the whole SKILL.md, loaded when a task matches
~3.8k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from isc-projects/bind9 at commit 784d666, republished under its MPL-2.0 licence (© isc-projects). 2,236 words, ~3,847 tokens.

Download SKILL.mdSave it as .claude/skills/rcu-mutation/SKILL.md (or your agent's skills folder).
name
rcu-mutation
description
Correct discipline for mutating an RCU / lock-free pointer-based data structure (trie, tree, list, graph) that has concurrent readers — build a new node cluster invisibly, publish it, then reclaim the old nodes after a grace period. Use when writing or reviewing any mutator on a structure read concurrently under RCU (or any publish/consume scheme), especially one with allocation-failure paths.

RCU mutation: build-invisible → publish → reclaim

The safe shape for a structural mutation with concurrent RCU readers is three phases. Get the phase boundaries right and most correctness questions dissolve.

The three phases

  1. Build (may fail). Allocate and fully wire the new node cluster. Touch only new nodes and their fields. The cluster must be reachable by a concurrent reader from neither direction (see "Observability"). On allocation failure, free the new nodes immediately (they were never observable — no grace period) and return; the old structure is untouched, so there is nothing to roll back.
  2. Publish (must not fail). With the cluster fully built, perform the minimal set of stores that link it into the live structure. After the first such store the cluster is observable, so no failure is permitted past this point — do all fallible work (allocations) in phase 1.
  3. Reclaim. Free the old nodes, deferred (call_rcu / synchronize_rcu / grace period). They were observable, so a reader may still hold a reference.

Observability — the core concept

A node is observable the moment a concurrent reader can reach it from the roots. Enumerate every channel readers traverse; in a doubly-linked structure there are usually two:

  • Forward: a reachable node's child/next slot points to it (the descent).
  • Backward: a reachable node's parent/prev back-pointer points to it, if readers follow back-pointers (up-walks, ordered traversal, lazy node recovery from a compressed/skip encoding).
  • Sideways: a secondary reader-traversable index — an ordered sibling/cell list, a hash chain, a cached min/max endpoint — that reaches the node independently of the tree. Each such index is its own channel: a node is observable while any channel can reach it, and "unreachable through the tree" proves nothing about the index.

A write publishes (crosses into observable) the instant it links a new node into any channel of an already-reachable node. Writes that only touch a brand-new node's own fields, or links between new nodes, are internal / non-observable — do as many of those as you like in phase 1.

The classic trap: a line that looks like "set up the new node" is actually a publish because its target is a reachable node. E.g. set_parent(old_child, new_node) publishes new_node through the back channel, because old_child is still reachable via the old structure.

Rules that fall out

  • Never reclaim a node that became observable without a grace period. And never make a node observable during phase 1 only to free it on the error path — that needs a grace period and leans on fragile reader-side consistency heuristics during the window. Keep the build invisible instead.
  • In phase 1, wire back-pointers directly from the pointers you hold. Do NOT recover a cluster node via the read-side recovery machinery (the same code a reader uses to chase a back-pointer / decode a compressed pointer). During the build that machinery follows a back-pointer that still points at the old structure, so it returns the wrong node and you corrupt it. The mutator holds every new node directly — use that, not recovery.
  • Track / free cluster nodes by an identity that does NOT need recovery. This is the same rule applied to the abort path. If your scheme has an encoding that resolves a node via a back-pointer (a skip/indirect pointer recovered through its child's parent link), do not record cluster nodes in that encoded form: the abort/free walk will resolve each tracked node to free it, and that back-pointer is still deferred (stale) → it resolves to the wrong, live node and frees it. Track the direct/plain form; if the published slot wants the encoded form, write the encoded value into the (still-private) slot just before publish, but keep the tracking/free/back-pointer-record in the plain form. (Builder helpers should therefore return the plain flag and let the caller re-encode the slot, not return the encoded one.)
  • Publish ordering matters for reader consistency (not for failure). Publish the channel that stops readers from reaching about-to-be-freed nodes first. (In a re-parent: set the surviving child's new back-pointer before swinging the top forward slot, so an up-walk from that child enters the new cluster before the new cluster becomes forward-reachable and the old node is freed.) The brief 2-store window between is the normal mutation window your readers' retry/validate logic already handles.
  • When several children's back-pointers are deferred together, wire them fresh-before-live. A cluster-leaf (see the realloc rule below) defers all its children's back-pointers to publish, and those children are often a mix of fresh (new, reachable only through the cluster) and live (re-parented from the old structure). Setting a live child's back-pointer is itself the back-channel publish: the instant it lands, a reader up-walking from that still-reachable child enters the cluster and can scan the cluster's other slots — including fresh siblings. So wire the cluster's own upward link and every fresh child's back-pointer first, and the live re-parent edge last (immediately before the forward publish). Backwards, a reader enters via the live edge and reaches a fresh sibling whose parent is not yet set — and this is not a transient window the reader retries past: the reader's data-dependency (consume) chain is anchored at the live back-pointer it loaded, so a fresh-parent store sequenced after that load has no release-consume edge to the reader. It observes the stale (often NULL) parent at any later wall-clock time. (Diagnosing exactly this — a parent set microseconds earlier yet read NULL — is the worked example in the lttng-tracing-root-cause-analysis skill. The single-surviving-child re-parent in the rule above is the degenerate case with no fresh siblings to strand.)
  • Commit every reader channel in one publish — a secondary index is a channel. If readers also traverse a secondary index (ordered cell list, hash chain), the structural publish and the index splice/unsplice are ONE logical publication. Publishing the structure first opens a window where a reader finds the new node by exact lookup, then steps through its not-yet-spliced index entry — NULL links read as end-of-list, which is neither the pre- nor the post-state. Symmetrically, freeing an index entry whose neighbours' stale links still reference it is a use-after-free even when the node itself is unreachable through the tree (the tree is not the only channel). Either fold the index edges into the same atomic commit (one flip covering forward edge + index links), or make the reader fast path detect a not-yet-spliced entry (e.g. NULL link but not the cached tail) and fall back to the structural walk. A guard on the writer's own fast path does not protect concurrent readers.
  • Every reader-visible publish goes through the release-store primitive (rcu_assign_pointer) — including out-param helpers. A helper that returns its result through a caller-supplied slot pointer (*slotp = new) performs an unordered publish whenever a caller passes a LIVE slot (a child slot of a published parent, the root) instead of a local. Either use rcu_assign_pointer unconditionally in the helper (harmless when the slot is a local), or forbid live slots in the helper's contract and make every caller re-publish with the release store. Audit out-param helpers by call site: the one caller that passes a live slot turns a correct helper into a plain-store publication with no ordering against the node-body stores.
  • The old nodes stay allocated and coherent through phases 1 and 2. They are serving readers the whole time. Free only in phase 3.
  • An "exclusive / no-readers" mode flips deferred reclaim to synchronous — re-check every safety argument built on the grace period. Code whose correctness argument is "the old copy stays allocated until a grace period elapses" (a relocation pass navigating from old copies, an undo walk back through possibly-freed ancestors, draining a detached subtree) silently becomes a use-after-free when the structure is in exclusive mode and frees happen immediately. The dual obligation: never mark a structure exclusive — or return it to a caller as exclusive — on a path that skipped the reader drain; every path that can leave a parked reader inside must synchronize first, not just the common one.
  • A node that may be reallocated mid-build defers ALL its children's back-pointers — no per-child exception. If your structure grows/shrinks a node by reallocating it (resize, recompact, rebalance creates a new copy and re-parents the children it copied), then a live child whose back-pointer you set "directly" still gets re-published to each successive copy by that re-parent step — and left dangling if a later allocation frees the copy. So at a cluster-leaf (a new node at the cluster's lower boundary, whose children include live nodes), set no child's back-pointer during the build, not even the children that look new/safe; wire them all at publish, using the node's final identity (track it across reallocations — the caller always gets the new flag back). Selective deferral is the trap: inserting a sibling child reallocates the node and re-parents the one you thought you'd deferred. (A boolean "this target is a cluster-leaf, skip its whole re-parent step" is cleaner and order-independent than a per-child "defer this one" flag, which would force you to add the deferred child last.)
  • Clear a freshly-built node's parent/back-link metadata before you grow (reallocate) it. If you build a new node and then add another child that triggers a realloc, the realloc copies the old node's parent (and any back-link slot it derives from it) into the new copy — and may write through that inherited parent to update its forward slot. A fresh node from a recycled allocation can carry stale, non-NULL parent metadata, so that inherited write lands on an unrelated live node. The new node has no parent until you wire it at publish; zero its parent/back-link fields before the growing step.
Show full SKILL.md (653 more words)Show less

Anti-patterns (and why)

  • Mutate-in-place then roll back on error. Tempting and localized, but if the mutated pointer was observable, rollback alone is a use-after-free (a reader grabbed the transient target); you must add a grace period before freeing, and the in-window correctness depends on a reader-side heuristic (e.g. "the lengths won't match so the reader retries") that is an emergent, non-local invariant, not a guarantee. Prefer build-invisible: there is no window and nothing to roll back.
  • Using the published-tree insert/link API to wire an unpublished cluster. Those APIs set back-pointers via read-side recovery (see the rule above) and assume the slot is already consistent. Wire the cluster with direct field stores.

Composing build-invisible steps into a transaction

A build-invisible step is only as safe as the transaction around it.

  • Propagate the step's failure; don't let a dispatch layer swallow it. When a descent/dispatch routine calls your mutation and treats its allocation failure like an ordinary "stop" (e.g. returns the same "done" signal on both success and OOM), the caller proceeds on un-built / stale state and corrupts the structure anyway — the build-invisible step's clean OOM is wasted. Thread the failure out and abort the whole transaction before any irreversible publish (before the point of no return, so there is nothing to roll back). A (void)-cast or ignored return on a fallible mutation is a red flag.
  • Never publish an incomplete intermediate that a later, fallible step completes. A transaction that publishes a deliberately-partial structure (e.g. a branch holding one of its eventual two children, meant to be finished by a subsequent allocating step) is not atomic: an OOM in the later step leaves the partial structure live — often a verify-invalid / non-canonical node rather than a dangling pointer, so it's a subtler corruption that exact lookups miss. Either build the whole cluster (every step's output) invisibly and publish once, or accept that the later step's failure must roll back the earlier publish — usually impractical once the replaced node is freed. If you can only fix the first step now, say so explicitly and scope the transaction-atomicity of the rest as separate work.
  • Error paths must report failure faithfully and reset out-params. Mapping an allocation failure to a benign status (NOT_FOUND, or a "duplicate found" success) tells the caller the operation didn't happen — or worse, that it did. And if an out-param was set optimistically before the fallible step (e.g. *result = removed chain, under a contract of "caller reclaims it after a grace period"), the error path MUST reset it to NULL: a caller that keys reclamation off the non-NULL out-param frees live data. Decide each error exit's (status, out-params, structure state) triple together; an error status paired with a success-shaped out-param is as dangerous as the reverse. Where a distinct out-of-memory status exists, use it — the caller's retry decision depends on distinguishing "absent" from "failed".

Worked example (userspace-rcu fractal trie compressed-split)

Splitting compressed node cn("ABCDE", child C) under parent P on insert of "ABXYZ": build cluster P→(skip "AB")→branch{ 'C'→sfx"DE"→C , 'X'→nb"YZ"→leaf }.

  • Phase 1: alloc sfx/nb/branch/prefix; wire forward slots and set every new node's back-pointer directly; set the branch→sfx slot to its final skip value even though it only becomes recoverable once C->parent flips — no reader sees it yet, and the mutator never recovers through it. Never touch C or P's slot. (Install sfx with its plain flag so the API recovers it directly, then overwrite the slot with the skip value — never install the skip flag, which would recover sfx through C->parent = still cn.)
  • OOM in phase 1: free sfx/nb/branch/prefix immediately; C, cn, P untouched.
  • Phase 2: C->parent = sfx (back), then P.slot = skip(branch,2) (forward).
  • Phase 3: free cn deferred.

"Skip-encoded" is a publication property: a skip pointer encodes the compressed node's child + length and recovers the node via that child's back-pointer, so it only resolves once that back-pointer is published. Setting the value early in an unobserved slot is fine; resolving it is a reader concern.

© isc-projects, MPL-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .agents/skills/rcu-mutation of isc-projects/bind9.

Open the folder on GitHubat commit 784d666

Compare with similar skills

Rcu Mutation next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Rcu Mutation compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Rcu Mutation this skillisc-projects/bind9780—~3.8kAutomated safety check: PassMPL-2.0
Monitor CInrwl/nx29k5 repos~4.7kAutomated safety check: PassMIT
Terraform and OpenTofu Guideagentscope-ai/QwenPaw35k6 repos~4.2kAutomated safety check: PassApache-2.0
Vercel Optimize Auditvercel-labs/agent-skills32k8 repos~4.3kAutomated safety check: PassNone
Analyze GitHub Action Logswithastro/astro63k1 repos~1.3kAutomated safety check: PassCustom licence
Docs Learn PR Previewnetdata/netdata81k—~2kAutomated safety check: PassGPL-3.0

Similar skills

  • Monitor CI

    nrwl/nx

    Monitor Nx Cloud CI pipeline and handle self-healing fixes. An agent skill from nrwl/nx.

    29k GitHub starsUsed in 5 repos~4.7k tokens
    DevOps & CloudAuto-check passed
  • Terraform and OpenTofu Guide

    agentscope-ai/QwenPaw

    Guidance for writing and testing Terraform and OpenTofu code: module structure, naming, test approaches, CI/CD workflows, state handling and security scanning.

    35k GitHub starsUsed in 6 repos~4.2k tokens
    DevOps & CloudAuto-check passed
  • Vercel Optimize Audit

    vercel-labs/agent-skills

    Official

    Runs a metrics-first audit of a deployed Vercel project, gating investigations on real signals to produce ranked, citation-backed cost and performance recommendations.

    32k GitHub starsUsed in 8 repos~4.3k tokens
    DevOps & CloudAuto-check passed
  • Official

    Analyze recent GitHub Actions workflow runs to identify patterns, mistakes, and improvements.

    63k GitHub starsUsed in 1 repo~1.3k tokens
    DevOps & CloudAuto-check passed
  • Docs Learn PR Preview

    netdata/netdata

    Use only when the user explicitly asks to build, run, preview, inspect, or validate learn.netdata.cloud locally using the contents of a PR or documentation branch before merge.

    81k GitHub stars~2k tokensUpdated today
    DevOps & CloudAuto-check passed
  • Repo Mirror Sources

    netdata/netdata

    Inspect Netdata-org source checkouts under NETDATAREPOSDIR, or set up and synchronize that mirror when requested.

    81k GitHub stars~1.2k tokensUpdated today
    DevOps & CloudAuto-check: notes

More from isc-projects/bind9

All 9 skills in this repo
  • Isc Mem Allocator

    isc-projects/bind9

    BIND 9's memory allocator wrapper (iscmem memory contexts and iscmempool fixed-size pools).

    780 GitHub stars~2.9k tokensUpdated yesterday
    Auto-check passed
  • Struct Layout Analysis

    isc-projects/bind9

    Measure and fix C struct layout in BIND 9 — pahole on the build's DWARF for sizes, padding holes, and cacheline boundaries, plus the house cacheline-padding idiom.

    780 GitHub stars~461 tokensUpdated yesterday
    Auto-check passed
  • Tweak Release Notes

    isc-projects/bind9

    Review and refine ISC BIND 9 release notes for a new version — audit audience/action tags against the actual change substance, verify every covered issue is closed, and rewrite the auto-generated…

    780 GitHub stars~1.2k tokensUpdated yesterday
    Auto-check passed
  • Bind Mr Description

    isc-projects/bind9

    Drafting BIND 9 merge-request titles and descriptions — they feed the generated release notes, so the audience is system administrators.

    780 GitHub stars~674 tokensUpdated yesterday
    Auto-check passed
  • Isc Async Scheduling

    isc-projects/bind9

    How BIND 9 schedules callbacks — iscjobrun (same loop), iscasyncrun (any thread → any loop), iscworkenqueue (offload to a worker thread).

    780 GitHub stars~1.8k tokensUpdated yesterday
    Auto-check passed
  • Methodology for root-causing hard concurrency / memory-ordering bugs (intermittent races, use-after-free, RCU/lock-free publish-order defects, "impossible" stale reads) with LTTng flight-recorder…

    780 GitHub stars~2.5k tokensUpdated yesterday
    Auto-check passed

Categories

Questions about Rcu Mutation

What does Rcu Mutation do?

Correct discipline for mutating an RCU / lock-free pointer-based data structure (trie, tree, list, graph) that has concurrent readers — build a new node cluster invisibly, publish it, then reclaim…. Rcu Mutation is an agent skill from isc-projects/bind9. Correct discipline for mutating an RCU / lock-free pointer-based data structure (trie, tree, list, graph) that has concurrent readers — build a new node cluster invisibly, publish it, then reclaim the old nodes after a grace period.

When should I use Rcu Mutation?

Rcu Mutation fits situations like: reviewing any mutator on a structure read concurrently under RCU (or any publish/consume scheme); especially one with allocation-failure paths.

How do I install Rcu Mutation in Claude Code?

Run `npx skills add isc-projects/bind9 --skill rcu-mutation -a claude-code`. Or copy the skill folder (.agents/skills/rcu-mutation in isc-projects/bind9) into .claude/skills/rcu-mutation in your project. Claude Code loads it when a task matches its description.

How do I install Rcu Mutation in Codex?

Run `npx skills add isc-projects/bind9 --skill rcu-mutation -a codex`. Or copy the skill folder (.agents/skills/rcu-mutation in isc-projects/bind9) into .agents/skills/rcu-mutation in your project. Codex loads it when a task matches its description.

Can I use Rcu Mutation in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add isc-projects/bind9 --skill rcu-mutation -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/rcu-mutation, .gemini/skills/rcu-mutation, .github/skills/rcu-mutation and .opencode/skills/rcu-mutation in your project.

What does Rcu Mutation need to run?

SKILL.md names no scripts, command-line tools or credentials: Rcu Mutation is instructions for the agent only.

Does Rcu Mutation access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Rcu Mutation safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Rcu Mutation use?

Rcu Mutation is published under the MPL-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Rcu Mutation use?

About 3.8k tokens (SKILL.md is roughly 15k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Rcu Mutation?

Skills that share tags, products or a category with Rcu Mutation: Monitor CI (nrwl/nx, 29k stars), Terraform and OpenTofu Guide (agentscope-ai/QwenPaw, 35k stars), Vercel Optimize Audit (vercel-labs/agent-skills, 32k stars) and Analyze GitHub Action Logs (withastro/astro, 63k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Rcu Mutation?

isc-projects (a GitHub organization) maintains it in isc-projects/bind9, which has 780 GitHub stars. The repository holds 9 skills in this directory. The repository was last updated on October 7, 2026.

Source: isc-projects/bind9 on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.