preempt
| plugin-preempt — Served by | plugin-preempt |
| plugin-preempt — Placement | compiled-in (in-process) |
| plugin-preempt — Version | 2026.183.0000 |
| plugin-preempt — Served by | plugin-preempt |
| plugin-preempt — Placement | compiled-in (in-process) |
| plugin-preempt — Version | 2026.183.0000 |
preempt is a command word served by 2 plugin candies — plugin-preempt and plugin-preempt — at different points in the command tree. Both are real invocations; charly --help prints which is which.
About plugin-preempt, which serves it
Section titled “About plugin-preempt, which serves it”COMPILED-IN charly plugin owning the RESOURCE ARBITER (cutover C9) — the final core-externalization cutover. It serves TWO capabilities:
-
verb:arbiter — the exclusive/shared resource arbiter, the 1225-LOC coordination logic MOVED OUT of charly core (the former charly/preempt.go ResourceArbiter): acquire/release exclusive+shared leases, stop + restore preemptible holders, the crash-safe lease ledger (~/.local/share/charly/preemption/leases.yml), GPU-resource poisoning (device_lock-wedge containment), owner liveness, and the vfio<->nvidia driver-mode arbitration math (arbiter.go + arbiter_support.go). The arbiter reaches its HOST dependencies — the project config, the VM/pod lifecycle, the GPU driver flip — that it cannot hold across the module boundary over TWO generic reverse legs: gather/resources read the generic Executor.InvokeProvider(“build”,“project”) envelope (K1-unblock wave 1 — the former bespoke arbiter reverse-RPC channel
- its host handler are DELETED); the other 6 (running / stop[+wait] / start / switchMode / ensureCDI / gpuCDI) run over Executor.InvokeProvider (FLOOR-SLIM-proper Unit-8, holder_dispatch.go — a prior cutover). The former in-core PROXY (charly/preempt.go newResourceArbiter + acquire*/release* shims) is DELETED (K-wave 2 cone CONTESTED — zero production callers after the check-bed/start/vm/cmd/arbiter-bracket consumers all went peer-dispatch; the sole survivor is the op=“remove” release chain in charly/host_build_pod_lifecycle_dispatch.go, host-process CHARLY_PREEMPT_LEASE state a placement-agnostic plugin cannot own).
-
command:preempt — the operator
charly preempt status/restoreCLI. It OWNS the CLI grammar + the lease-table formatting and reaches its OWN peer capability verb:arbiter DIRECTLY via InvokeProvider over the in-proc reverse channel (no hidden__preempt-*forward, no in-core proxy hop). No ad-hoc podman/virsh (R4).
PLACEMENT — COMPILED-IN (listed in the embedded charly/charly.yml compiled_plugins:). The arbiter is on the deploy / vm-create / check-bed hot paths and needs the LOCAL lease ledger + the LOCAL project config, so in-proc is the right placement (like candy/plugin-gpu); the reverse channel is in-proc (no gRPC broker), the SAME dispatchBuild pattern. The cmd/serve binary backs the out-of-process placement.
The DRIVER-SWITCH (vfio<->nvidia rebind) that the arbiter’s switchMode seam drives now lives in candy/plugin-gpu (C9, 1B); the host receives the arbiter’s switchMode call and routes it there via the core gpu shims (a plugin->plugin edge through the host).
R10: the disposable check-preempt-arbiter-pod bed exercises the FULL acquire/preempt path with ZERO GPU — a preemptible pod holder on a SYNTHETIC selector-less token (test-lock) + a requires_exclusive claimant, so AcquireExclusive -> holdersToStop -> stopHolders+wait -> lease persisted -> applyMode SKIPS (no gpu selector) -> claim, then teardown -> ReleaseClaimant -> restoreHolders, all THROUGH the externalized dispatch + the resolved-project envelope (gather/resources) + InvokeProvider (the rest).
About plugin-preempt, which serves it
Section titled “About plugin-preempt, which serves it”COMPILED-IN charly plugin owning the RESOURCE ARBITER (cutover C9) — the final core-externalization cutover. It serves TWO capabilities:
-
verb:arbiter — the exclusive/shared resource arbiter, the 1225-LOC coordination logic MOVED OUT of charly core (the former charly/preempt.go ResourceArbiter): acquire/release exclusive+shared leases, stop + restore preemptible holders, the crash-safe lease ledger (~/.local/share/charly/preemption/leases.yml), GPU-resource poisoning (device_lock-wedge containment), owner liveness, and the vfio<->nvidia driver-mode arbitration math (arbiter.go + arbiter_support.go). The arbiter reaches its HOST dependencies — the project config, the VM/pod lifecycle, the GPU driver flip — that it cannot hold across the module boundary over TWO generic reverse legs: gather/resources read the generic Executor.InvokeProvider(“build”,“project”) envelope (K1-unblock wave 1 — the former bespoke arbiter reverse-RPC channel
- its host handler are DELETED); the other 6 (running / stop[+wait] / start / switchMode / ensureCDI / gpuCDI) run over Executor.InvokeProvider (FLOOR-SLIM-proper Unit-8, holder_dispatch.go — a prior cutover). The former in-core PROXY (charly/preempt.go newResourceArbiter + acquire*/release* shims) is DELETED (K-wave 2 cone CONTESTED — zero production callers after the check-bed/start/vm/cmd/arbiter-bracket consumers all went peer-dispatch; the sole survivor is the op=“remove” release chain in charly/host_build_pod_lifecycle_dispatch.go, host-process CHARLY_PREEMPT_LEASE state a placement-agnostic plugin cannot own).
-
command:preempt — the operator
charly preempt status/restoreCLI. It OWNS the CLI grammar + the lease-table formatting and reaches its OWN peer capability verb:arbiter DIRECTLY via InvokeProvider over the in-proc reverse channel (no hidden__preempt-*forward, no in-core proxy hop). No ad-hoc podman/virsh (R4).
PLACEMENT — COMPILED-IN (listed in the embedded charly/charly.yml compiled_plugins:). The arbiter is on the deploy / vm-create / check-bed hot paths and needs the LOCAL lease ledger + the LOCAL project config, so in-proc is the right placement (like candy/plugin-gpu); the reverse channel is in-proc (no gRPC broker), the SAME dispatchBuild pattern. The cmd/serve binary backs the out-of-process placement.
The DRIVER-SWITCH (vfio<->nvidia rebind) that the arbiter’s switchMode seam drives now lives in candy/plugin-gpu (C9, 1B); the host receives the arbiter’s switchMode call and routes it there via the core gpu shims (a plugin->plugin edge through the host).
R10: the disposable check-preempt-arbiter-pod bed exercises the FULL acquire/preempt path with ZERO GPU — a preemptible pod holder on a SYNTHETIC selector-less token (test-lock) + a requires_exclusive claimant, so AcquireExclusive -> holdersToStop -> stopHolders+wait -> lease persisted -> applyMode SKIPS (no gpu selector) -> claim, then teardown -> ReleaseClaimant -> restoreHolders, all THROUGH the externalized dispatch + the resolved-project envelope (gather/resources) + InvokeProvider (the rest).
charly --help prints the command tree, including where each preempt is invoked and under which parent.