This issue is probably related to a prior
microsoft.public.development.device.drivers post "64-bit system hang in
KiInterruptDispatch", and it looks to be fixed in Windows Vista x64 (tested
with RC1).

I would like to know where I can find the hotfix for my customers. Thank you!

The issue:
On Windows XP for 32-bit x86 (halmacpi,ntkrnlmp), KiInterruptDispatch raises
the IRQL to "SynchronizeIrql" (from IoConnectInterrupt) before acquiring the
SpinLock (ActualLock) and calling the ServiceRoutine. However on Windows XP
x64, KiInterruptDispatch seems to be raising IRQL to "Irql" instead of
"SynchronizeIrql" (from IoConnectInterrupt).

Why is this a problem?

Let us imagine that I have a device (AT-DIO-32F) with multiple interrupts
assigned, "X" and "Y". Lucky us, interrupt "X" is not used by any other
devices in the system and is assigned IRQL 5. Interrupt "Y", however, _is_
shared with other devices in the system and is assigned IRQL 10. I create 1
spinlock to protect access to device registers and variables from within the
interrupt service routine for this device. Next a call is made to
IoConnectInterrupt() for each assigned interrupt, where the SynchronizeIrql
is set to 10 and the same ServiceRoutine and SpinLock are used for both
calls.

The problematic scenario:
Interrupt "X" fires. KiInterruptDispatch on raises IRQL to 5 (not 10) and
grabs the shared spinlock. During the ServiceRoutine, interrupt "Y" fires.
Because "Y" is at IRQL 10, and the current IRQL is 5, it preempts the current
execution. Because "Y" is a shared interrupt, KiChainedDispatch is called.
KiChainedDispatch walks the list of _KINTERRUPT objects at IRQL "Irql",
raises the IRQL to "SynchronizeIrql" temporarily if it is higher than the
current IRQL, grabs their SpinLock, and calls their ServiceRoutines. When it
encounters the SpinLock (ActualLock) for my device, there is a problem
because this CPU is already holding the spinlock at the lower IRQL, so the
system hangs.

Stack:
nt!KiScanInterruptObjectList+0x72 (trying to grab my spinlock, again)
nt!KiChainedDispatch+0xd7
MyDriver!MyServiceRoutine+MyOffset
nt!KiInterruptDispatch+0x138 (holding my spinlock at Irql, not
SynchronizeIrql)

On Windows XP x86, things have run great for years. Also, Vista x86 and x64
(RC1) both seem to operate fine, though my testing there hasn't been
comprehensive -- just a quick test followed by some WinDBG disassembly to
confirm that it is fixed. I have not evaluated Server 2003.

I hope that saves the rest of you a man day or two.
--
Jeremiah
National Instruments -- http://www.ni.com

"stack smasher" djajadi tribute.

RE: XP x64 deadlock issue with KiInterruptDispatch by Jeremiah

Jeremiah
Wed Oct 04 21:04:01 CDT 2006

If you need the hotfix for this issue, try the following:
KB Article Number(s): 907723
--
Jeremiah
National Instruments -- http://www.ni.com


"Jeremiah" wrote:

> This issue is probably related to a prior
> microsoft.public.development.device.drivers post "64-bit system hang in
> KiInterruptDispatch", and it looks to be fixed in Windows Vista x64 (tested
> with RC1).
>
> I would like to know where I can find the hotfix for my customers. Thank you!
>
> The issue:
> On Windows XP for 32-bit x86 (halmacpi,ntkrnlmp), KiInterruptDispatch raises
> the IRQL to "SynchronizeIrql" (from IoConnectInterrupt) before acquiring the
> SpinLock (ActualLock) and calling the ServiceRoutine. However on Windows XP
> x64, KiInterruptDispatch seems to be raising IRQL to "Irql" instead of
> "SynchronizeIrql" (from IoConnectInterrupt).
>
> Why is this a problem?
>
> Let us imagine that I have a device (AT-DIO-32F) with multiple interrupts
> assigned, "X" and "Y". Lucky us, interrupt "X" is not used by any other
> devices in the system and is assigned IRQL 5. Interrupt "Y", however, _is_
> shared with other devices in the system and is assigned IRQL 10. I create 1
> spinlock to protect access to device registers and variables from within the
> interrupt service routine for this device. Next a call is made to
> IoConnectInterrupt() for each assigned interrupt, where the SynchronizeIrql
> is set to 10 and the same ServiceRoutine and SpinLock are used for both
> calls.
>
> The problematic scenario:
> Interrupt "X" fires. KiInterruptDispatch on raises IRQL to 5 (not 10) and
> grabs the shared spinlock. During the ServiceRoutine, interrupt "Y" fires.
> Because "Y" is at IRQL 10, and the current IRQL is 5, it preempts the current
> execution. Because "Y" is a shared interrupt, KiChainedDispatch is called.
> KiChainedDispatch walks the list of _KINTERRUPT objects at IRQL "Irql",
> raises the IRQL to "SynchronizeIrql" temporarily if it is higher than the
> current IRQL, grabs their SpinLock, and calls their ServiceRoutines. When it
> encounters the SpinLock (ActualLock) for my device, there is a problem
> because this CPU is already holding the spinlock at the lower IRQL, so the
> system hangs.
>
> Stack:
> nt!KiScanInterruptObjectList+0x72 (trying to grab my spinlock, again)
> nt!KiChainedDispatch+0xd7
> MyDriver!MyServiceRoutine+MyOffset
> nt!KiInterruptDispatch+0x138 (holding my spinlock at Irql, not
> SynchronizeIrql)
>
> On Windows XP x86, things have run great for years. Also, Vista x86 and x64
> (RC1) both seem to operate fine, though my testing there hasn't been
> comprehensive -- just a quick test followed by some WinDBG disassembly to
> confirm that it is fixed. I have not evaluated Server 2003.
>
> I hope that saves the rest of you a man day or two.
> --
> Jeremiah
> National Instruments -- http://www.ni.com
>
> "stack smasher" djajadi tribute.