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.