Linux PM QoS Latency Requests: Remove the Constraint When Its Owner Finishes
Give every latency-sensitive operation an explicit PM QoS owner and remove its request when that operation finishes. The effective CPU latency constraint is aggregated across owners, so closing one application’s request need not relax the system. Diagnose the surviving owner before changing idle-state policy globally.
Applicability: this article pins Linux v6.12 with CONFIG_CPU_IDLE and the /dev/cpu_dma_latency interface available. It addresses global CPU latency requests, not device runtime-PM references or frequency QoS. The numerical owner sequence is hypothetical; no latency setting, idle-state transition, or power measurement was executed.

1. Identify the constraint you are actually changing
The PM QoS interface guide distinguishes global CPU latency requests from per-device and frequency constraints. Keep the class and units in the ownership record. A CPU latency request is not a request to keep a particular peripheral runtime-active.
The CPU idle guide describes the global latency limit in microseconds and minimum aggregation. CPU idle governors consider it with the effective per-CPU resume-latency constraint when selecting eligible exit latencies. It does not guarantee an application response deadline that also includes interrupts, scheduling, locks, and device service.
Record the kernel, CPUIdle driver and governor, available states, workload, and other known constraints before testing. A request may exclude an otherwise eligible state, but its release does not compel the hardware to enter that state.
2. Model requests as owners, not one shared setting
Suppose hypothetical owner A requests 100 µs and owner B requests 20 µs, with no tighter request elsewhere. The effective global limit is 20 µs. A changing its request to 500 µs leaves that limit unchanged. Removing B leaves A’s 500 µs request, rather than restoring a remembered machine-wide default.
Each component should release its own request. Do not have A “restore 100 µs” by overwriting B’s state or assume the last writer wins. An unchanged aggregate can be correct even though a request was updated or removed successfully.
Keep an operation ledger with owner identity, creation point, requested value, update reason, and terminal release path. Distinguish a request retained for a genuinely active operation from one leaked after timeout or setup failure.
3. Follow the open file description through duplication
The v6.12 implementation allocates a request during open, stores it in the file’s private data, and removes it in the release callback. Separate opens create separate requests. Writes through one open update that request, while reads return the aggregate global value.
Descriptor lifetime needs precision. The Linux dup manual explains that duplicate descriptors share an open file description; fork similarly shares the underlying descriptions with inherited descriptors. Closing the original descriptor is therefore insufficient while another reference retains that open file description.
The close manual describes final-reference resource release. Audit helper processes, descriptor duplication, and inheritance across execution. Use an appropriate close-on-exec policy when the request must not survive a launched program, and explicitly close an inherited reference when a child does not own the operation.
Do not interpret “the parent exited” as proof that its constraint disappeared. A child or duplicate can retain it. Conversely, an ordinary short-lived command that opens, writes, and exits cannot hold a persistent request after its last reference is released.
4. Use the exact write ABI
In v6.12 cpu_latency_qos_write(), a four-byte write is copied as a native signed 32-bit value. Other lengths are parsed as base-16 text. Ordinary decimal text and a newline are therefore a poor substitute for a deliberate ABI encoding; a four-byte text string takes the binary branch.
The update helper ignores negative values other than the framework’s default sentinel, while the write handler can still return the supplied byte count. Check intended value, encoding, and resulting observations rather than treating a successful write alone as proof that the requested constraint changed.
Prefer a small reviewed application wrapper that owns the descriptor and uses an explicit native 32-bit representation for ordinary nonnegative requests. Check open and write results and keep the descriptor alive for the required interval. No such wrapper is supplied or claimed tested here.
5. Design cleanup before exercising the workload
Associate request ownership with the bounded operation that needs it. Cover normal completion, cancellation, timeout, initialization failure, and service shutdown. Ensure cleanup does not run while another thread is still relying on the same owner without an agreed handoff.
For kernel consumers, use the documented request handle and add/update/remove lifecycle rather than allocating an untracked temporary request. Preserve the handle until removal completes. Review concurrent updates and teardown in the consumer’s own synchronization design.
A long-lived service may retain one request object and relax its value between active phases, or create and release requests for bounded phases. Either can be valid if its idle policy is deliberate and all failure paths reach it. Do not let “process remains running” become an accidental reason to hold the strictest limit forever.
6. Test minimum aggregation and final release
On an authorized development system, propose the two-owner sequence in the figure. Observe the aggregate after each creation, update, and release. Repeat with a duplicate descriptor retained, then release that final reference. Include a controlled child process that closes its inherited reference as a positive cleanup check.
Inspect other request sources if the observed aggregate stays tighter than the fixture predicts. A read reports the aggregate, not the caller’s private value, so it cannot alone prove the caller’s write was applied. Correlate ownership events with suitable supported tracing and the controlled fixture.
Also distinguish /dev/cpu_dma_latency from the per-CPU power/pm_qos_resume_latency_us sysfs interface. The CPU idle guide describes that sysfs request as shared across userspace writers, rather than one independently owned request per open. Do not transfer descriptor-cleanup assumptions to it.
7. Separate accounting success from measured benefit
After ownership is correct, compare service latency and energy under the supported workload. Use hardware residency counters where available; software idle-state time is not exact proof of physical residency. Keep the observed state selection separate from the effective QoS limit.
The release artifact should show the owner ledger, encoding, cleanup branches, aggregate transitions, and measured service envelope when available. A removed request is an accounting result. Lower power and acceptable response latency are separate outcomes that need target evidence.