Zephyr OS Power-State Locks: Match Releases to the Same State and Substate Set
A power-state lock excludes selected sleep states from policy consideration. It is not a generic “keep everything awake” token unless the selected API and state set actually express that scope. Releasing a different substate set can leave one state locked and incorrectly alter another.
For Zephyr OS power-policy review, record the exact state and substate for every acquisition. This discussion follows v4.4.0 and does not claim that unlocking a state guarantees a particular current level or that the system will immediately enter it.

Treat the lock scope as part of its identity
The tagged policy interface defines reference-counted state locks. PM_ALL_SUBSTATES applies an operation across the substates of the selected state. Repeated acquisitions require matching releases before the state becomes allowed again; PM_STATE_ACTIVE is always allowed.
Imagine a hypothetical peripheral transaction that excludes one suspend substate because it would remove a required clock. Another subsystem excludes every substate of that same state. These requests overlap, but they are not interchangeable. Completing the peripheral transaction should release only the scope it acquired, leaving the other subsystem's exclusion intact.
Put scope and owner together in the accounting record. A counter labelled merely “PM lock” hides the distinction between a specific substate, all substates within one state and the separate all-state lock interface.
Follow the generated state set
The tagged state-lock implementation builds its substate list from enabled devicetree power-state nodes. Get and put iterate matching entries. A first lock removes an entry from the unlocked mask; its final release restores that entry. The put path asserts against an unbalanced counter.
This means a scope review needs the actual generated power-state definitions, not just an enum value copied from a different board. A requested pair that does not match the configured list does not create a new power state or a new hardware capability.
As a design recommendation, wrap acquisition and release around one clearly owned activity, preserving the same arguments across normal completion, setup failure and cancellation. Do not repair an unexplained outstanding lock by issuing extra puts until a low-power state becomes available. That approach can consume another owner's protection.
Avoid overinterpreting broad status queries
In the inspected implementation, the state-lock status query returns when it encounters a matching entry. With an all-substates argument, that is not an exhaustive report of every independently locked substate. If the diagnostic question is which substates remain excluded, inspect each relevant configured pair rather than turning one broad Boolean into a full inventory.
Keep that diagnostic issue separate from acquisition semantics: get and put iterate their matching set. A status shortcut should not be assumed to have the same iteration-and-aggregation behavior merely because it accepts the same argument type.
A hypothetical debug display can list each configured state/substate and whether its lock is active. Label the values as observations rather than durable ownership claims, since other components can change policy after the query.
Distinguish permission from final state selection
The implementation also combines lock information with latency-related availability. Releasing all of an activity's locks does not guarantee that every state is now eligible, much less that the next idle interval will enter the deepest one. Other constraints and the selected policy still matter.
For proposed tests, first use two independent owners that acquire overlapping scopes. Complete them in both orders and verify that the remaining owner's exclusion persists. Then test a setup failure before work starts and a cancellation after work has begun, checking the exact release scope in each path.
Finally compare policy observations with an actual target trace of selected states. Keep electrical measurements separate, including the board configuration and enabled peripherals. A correct lock ledger establishes software intent; it does not by itself prove retention behavior or energy savings.
The useful fix is usually a scope or ownership correction, not an arbitrary delay before sleeping. Naming the precise excluded state makes both the software reasoning and the later hardware qualification more defensible.