In our final installment of this introductory series, we move from runaway loops to the opposite problem: The Deadlock. This is where the system isn’t “busy”—it’s “stuck.”
Two or more threads are waiting for resources held by each other, and neither can proceed. In the Windows kernel, this frequently manifests during power transitions (like sleeping or hibernating), leading to the infamous 0x9F: DRIVER_POWER_STATE_FAILURE.
1. The Locking Hierarchy
Kernel drivers use various synchronization primitives to protect shared data:
- Spinlocks: Fast, used at
DISPATCH_LEVEL. - Mutexes/ERESOURCEs: Used at
PASSIVE_LEVEL, allowing threads to wait (sleep) if the resource is busy.
The Deadlock Trap: Thread A acquires Lock 1 and tries to get Lock 2. Simultaneously, Thread B acquires Lock 2 and tries to get Lock 1. Both threads sit forever, and if one of those threads is required for a system-wide operation (like a shutdown), the Watchdog eventually triggers a BSOD.
2. Real Use Case: The Sleep-Timer Deadlock
Scenario: A laptop fails to enter “Sleep” mode. The screen goes black, the fans stay on for 30 seconds, and then it crashes with 0x9F.
Step 1: Analyze the Power IRP
For 0x9F, Parameter 1 tells us the type of violation. Usually, it’s 0x3 (A device object has been blocking an IRP for too long).
Run: !analyze -v
Then, find the pending IRP:
!irp <address_from_analyze>
Step 2: Finding the Blocker
The !irp command will show which driver is currently “owning” the power request.
Plaintext
>[0, 0] 0 0 ffffe001`1a2b3c40 00000000 fffff801`4b331010-fffff801`4b442020
\Driver\MyUsbFilter nt!PopRequestCompletion
Here, MyUsbFilter received a “Set Power” IRP but never passed it down or completed it.
Step 3: Thread Analysis
Why is the driver stuck? We look at the thread handling that IRP:
!thread <address>
The stack trace might look like this:
Plaintext
nt!KeWaitForSingleObject
MyUsbFilter!StopTrafficAndLock+0x45
MyUsbFilter!PowerDispatch+0x12
The Discovery: The driver is waiting for a Mutex to “Stop Traffic.” However, the thread that holds that Mutex is currently blocked waiting for the Power IRP to finish. This is a classic Circular Dependency.
3. Debugging Tools for Deadlocks
If you suspect a lock issue, WinDbg has specialized tools:
!locks: Displays all kernel resources and which threads own them. Look for “Threads Waiting.”!deadlock: If you have Driver Verifier’s Deadlock Detection enabled, this command will explicitly map out the circular chain for you.!ready: Shows all threads in a “Ready” state to see if anyone is being starved of CPU time.
4. Designing for Stability (Blog Advice)
- Lock Ordering: Always acquire locks in the exact same order across all functions in your driver. If you take Lock A then Lock B in one place, never take Lock B then Lock A elsewhere.
- Don’t Block in Power Paths: Power dispatch routines should be fast. If you need to wait for hardware, use a timeout.
- Use Passive-Level Interrupts: If your hardware allows, handle complexity at
PASSIVE_LEVELwhere you have more flexibility with synchronization.
Summary of Resource & Power Bug Checks
| Code | Name | Description |
| 0x9F | DRIVER_POWER_STATE_FAILURE | A driver is inconsistent or slow during a power state change. |
| 0x15F | CONNECTED_STANDBY_WATCHDOG_TIMEOUT | A specialized 0x9F for modern standby devices. |
| 0xCB | DRIVER_LEFT_LOCKED_PAGES_IN_PROCESS | A driver failed to release memory or locks before a process ended. |
| 0xDE | POOL_CORRUPTION_IN_FILE_AREA | Often a deadlock between the Memory Manager and a File System driver. |
Conclusion of the Series
Debugging is a mix of science and intuition. By mastering IRQLs, Pool Headers, DPCs, and Locking, you move from guessing why a system crashed to knowing exactly which line of code failed.
Happy Debugging!
