WDM Interrupt Objects

Up until now i thought that if i call IoConnectInterrupt() once per
device and store the returned PKINTERRUPT pointer in the device
extension then the first parameter of my ISR will have the same value
as the pointer in my device extension.

e.g. :

NTSTATUS StartDevice(…)
{

Status = IoConnectInterrupt(&pDevExt->pIntObj, ISR, …);

}

BOOLEAN ISR(PKINTERRUPT pIntObj, PVOID pContext)
{
DEVICEEXTENSION *pDevExt = (DEVICEEXTENSION*)pContext;

if (pDevExt->pIntObj != pIntObj)
{
// not my IntObj. No need to waste time for
// asking HW if it did interrupt
return FALSE;
}

int Reason = AskHwForIntReason()

if (Reason == 0)
{
// HW did not interrupt
return FALSE;
}

return TRUE;
}

That kind of code worked for several month until i began to use
different CPUs/Motherboards. On my current testsystem the expression
‘pDevExt->pIntObj != pIntObj’ is true although the interrupt was definitly
generated by my HW and since the code above does not handle the interrupt
i get an never ending interrupt storm.

Just removing the ‘if (pDevExt->pIntObj != pIntObj)’ block solves that
problem.

So i tried to find some information about this subject in the DDK. The
only thing i found so far is this:


The system creates an interrupt object for each processor the device is
capable of interrupting.

Does that mean that when i call IoConnectInterrupt on a SMP system the OS
creates an interrupt object for each processor but returns just a pointer
to one of them while the parameter to the ISR can be a pointer to any of
them?

regards,
poltrone

> ‘pDevExt->pIntObj != pIntObj’ is true although the interrupt was definitly

A useless operator. You must ask your hardware instead by reading its registers
whether it has an interrupt condition pending.

Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com

There is no guarantee about the value of the Interrupt parameter when
your ISR is invoked. Your first test is bogus. The only guarantee is
that ServiceContext is the value you specified in InConnectInterrupt.

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of poltrone
Sent: Thursday, June 29, 2006 4:16 AM
To: Windows System Software Devs Interest List
Subject: [ntdev] WDM Interrupt Objects

Up until now i thought that if i call IoConnectInterrupt() once per
device and store the returned PKINTERRUPT pointer in the device
extension then the first parameter of my ISR will have the same value
as the pointer in my device extension.

e.g. :

NTSTATUS StartDevice(…)
{

Status = IoConnectInterrupt(&pDevExt->pIntObj, ISR, …);

}

BOOLEAN ISR(PKINTERRUPT pIntObj, PVOID pContext)
{
DEVICEEXTENSION *pDevExt = (DEVICEEXTENSION*)pContext;

if (pDevExt->pIntObj != pIntObj)
{
// not my IntObj. No need to waste time for
// asking HW if it did interrupt
return FALSE;
}

int Reason = AskHwForIntReason()

if (Reason == 0)
{
// HW did not interrupt
return FALSE;
}

return TRUE;
}

That kind of code worked for several month until i began to use
different CPUs/Motherboards. On my current testsystem the expression
‘pDevExt->pIntObj != pIntObj’ is true although the interrupt was
definitly
generated by my HW and since the code above does not handle the
interrupt
i get an never ending interrupt storm.

Just removing the ‘if (pDevExt->pIntObj != pIntObj)’ block solves that
problem.

So i tried to find some information about this subject in the DDK. The
only thing i found so far is this:


The system creates an interrupt object for each processor the device is
capable of interrupting.

Does that mean that when i call IoConnectInterrupt on a SMP system the
OS
creates an interrupt object for each processor but returns just a
pointer
to one of them while the parameter to the ISR can be a pointer to any of
them?

regards,
poltrone


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

There is actually another guarantee here. A call to KeSynchronizeExecution
or KeAcquireInterruptSpinlock with the interrupt object that you get back
from IoConnectInterrupt(Ex) will take the same lock that is taken while
your
ISR is being invoked.

Just because you might be curious, calling IoConnectInterrupt(Ex) allocates
an interrupt object for every processor that you’re connecting to. Then it
hands you back a pointer to one of them. This is sufficient, because the
only thing that you can do with an interrupt object is to call one of the
interrupt spinlock routines or IoDisconnectInterrupt(Ex). A comparison
with
the one handed back to from IoConnectInterrupt means nothing, as you still
have to poll your hardware. (Note that your ISR will never be invoked with
somebody else’s interrupt object. The original poster’s test was, as Mark
said, meaningless.)

This, of course, will make an alert reader wonder why an ISR even has an
interrupt object parameter. There’s nothing you can validly do with it.
You can’t call IoDisconnectInterrupt(Ex) because you’re running at too high
an IRQL. You can’t call one of the spinlock acquisition routines because
you’re already holding the lock.

I considered changing that parameter to a PVOID Reserved the last time I
took a pass through the interrupt code. But I figured that changing it
would only cause more confusion.

Jake Oshins
Windows Kernel Group
(Previous, though not first or last, owner of the interrupt-related code.)

“Roddy, Mark” wrote in message
> news:xxxxx@ntdev…
> There is no guarantee about the value of the Interrupt parameter when
> your ISR is invoked. Your first test is bogus. The only guarantee is
> that ServiceContext is the value you specified in InConnectInterrupt.
>
> -----Original Message-----
> From: xxxxx@lists.osr.com
> [mailto:xxxxx@lists.osr.com] On Behalf Of poltrone
> Sent: Thursday, June 29, 2006 4:16 AM
> To: Windows System Software Devs Interest List
> Subject: [ntdev] WDM Interrupt Objects
>
> Up until now i thought that if i call IoConnectInterrupt() once per
> device and store the returned PKINTERRUPT pointer in the device
> extension then the first parameter of my ISR will have the same value
> as the pointer in my device extension.
>
> e.g. :
>
> NTSTATUS StartDevice(…)
> {
> …
>
> Status = IoConnectInterrupt(&pDevExt->pIntObj, ISR, …);
> …
> }
>
> BOOLEAN ISR(PKINTERRUPT pIntObj, PVOID pContext)
> {
> DEVICEEXTENSION pDevExt = (DEVICEEXTENSION)pContext;
>
> if (pDevExt->pIntObj != pIntObj)
> {
> // not my IntObj. No need to waste time for
> // asking HW if it did interrupt
> return FALSE;
> }
>
> int Reason = AskHwForIntReason()
>
> if (Reason == 0)
> {
> // HW did not interrupt
> return FALSE;
> }
>
>
> …
>
> return TRUE;
> }
>
>
> That kind of code worked for several month until i began to use
> different CPUs/Motherboards. On my current testsystem the expression
> ‘pDevExt->pIntObj != pIntObj’ is true although the interrupt was
> definitly
> generated by my HW and since the code above does not handle the
> interrupt
> i get an never ending interrupt storm.
>
> Just removing the ‘if (pDevExt->pIntObj != pIntObj)’ block solves that
> problem.
>
>
> So i tried to find some information about this subject in the DDK. The
> only thing i found so far is this:
>
>
> The system creates an interrupt object for each processor the device is
> capable of interrupting.
>
>
>
> Does that mean that when i call IoConnectInterrupt on a SMP system the
> OS
> creates an interrupt object for each processor but returns just a
> pointer
> to one of them while the parameter to the ISR can be a pointer to any of
> them?
>
> regards,
> poltrone
>
>
>
> —
> Questions? First check the Kernel Driver FAQ at
> http://www.osronline.com/article.cfm?id=256
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>
>

Maxim, Mark,

i already learned my lesson (the hard way, i have to admit).

The reason for my posting was (and still is) my curiosity about

  • why my bogus code worked on some machines, but does not on others

  • wether my assumption about the creation of several intrrupt objects
    is correct.

  • if there is no guarantee about the value of the Interrupt parameter,
    is there a reasonable use for it, or should it be considered as a
    dummy parameter altogether?

regards,
poltrone

“Roddy, Mark” schrieb im Newsbeitrag news:xxxxx@ntdev…
There is no guarantee about the value of the Interrupt parameter when
your ISR is invoked. Your first test is bogus. The only guarantee is
that ServiceContext is the value you specified in InConnectInterrupt.

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of poltrone
Sent: Thursday, June 29, 2006 4:16 AM
To: Windows System Software Devs Interest List
Subject: [ntdev] WDM Interrupt Objects

Up until now i thought that if i call IoConnectInterrupt() once per
device and store the returned PKINTERRUPT pointer in the device
extension then the first parameter of my ISR will have the same value
as the pointer in my device extension.

e.g. :

NTSTATUS StartDevice(…)
{


Status = IoConnectInterrupt(&pDevExt->pIntObj, ISR, …);

}

BOOLEAN ISR(PKINTERRUPT pIntObj, PVOID pContext)
{
DEVICEEXTENSION pDevExt = (DEVICEEXTENSION)pContext;

if (pDevExt->pIntObj != pIntObj)
{
// not my IntObj. No need to waste time for
// asking HW if it did interrupt
return FALSE;
}

int Reason = AskHwForIntReason()

if (Reason == 0)
{
// HW did not interrupt
return FALSE;
}



return TRUE;
}

That kind of code worked for several month until i began to use
different CPUs/Motherboards. On my current testsystem the expression
‘pDevExt->pIntObj != pIntObj’ is true although the interrupt was
definitly
generated by my HW and since the code above does not handle the
interrupt
i get an never ending interrupt storm.

Just removing the ‘if (pDevExt->pIntObj != pIntObj)’ block solves that
problem.

So i tried to find some information about this subject in the DDK. The
only thing i found so far is this:


The system creates an interrupt object for each processor the device is
capable of interrupting.


Does that mean that when i call IoConnectInterrupt on a SMP system the
OS
creates an interrupt object for each processor but returns just a
pointer
to one of them while the parameter to the ISR can be a pointer to any of
them?

regards,
poltrone


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Thanks, Jake, for your elaborate answer.
When i wrote my posting, i already hoped you were going to answer :wink:

regards,
poltrone

“Jake Oshins” schrieb im Newsbeitrag news:xxxxx@ntdev…
> There is actually another guarantee here. A call to KeSynchronizeExecution
> or KeAcquireInterruptSpinlock with the interrupt object that you get back
> from IoConnectInterrupt(Ex) will take the same lock that is taken while your
> ISR is being invoked.
>
> Just because you might be curious, calling IoConnectInterrupt(Ex) allocates
> an interrupt object for every processor that you’re connecting to. Then it
> hands you back a pointer to one of them. This is sufficient, because the
> only thing that you can do with an interrupt object is to call one of the
> interrupt spinlock routines or IoDisconnectInterrupt(Ex). A comparison with
> the one handed back to from IoConnectInterrupt means nothing, as you still
> have to poll your hardware. (Note that your ISR will never be invoked with
> somebody else’s interrupt object. The original poster’s test was, as Mark
> said, meaningless.)
>
> This, of course, will make an alert reader wonder why an ISR even has an
> interrupt object parameter. There’s nothing you can validly do with it.
> You can’t call IoDisconnectInterrupt(Ex) because you’re running at too high
> an IRQL. You can’t call one of the spinlock acquisition routines because
> you’re already holding the lock.
>
> I considered changing that parameter to a PVOID Reserved the last time I
> took a pass through the interrupt code. But I figured that changing it
> would only cause more confusion.
>
> Jake Oshins
> Windows Kernel Group
> (Previous, though not first or last, owner of the interrupt-related code.)
>
>
>> “Roddy, Mark” wrote in message news:xxxxx@ntdev…
>> There is no guarantee about the value of the Interrupt parameter when
>> your ISR is invoked. Your first test is bogus. The only guarantee is
>> that ServiceContext is the value you specified in InConnectInterrupt.
>>
>> -----Original Message-----
>> From: xxxxx@lists.osr.com
>> [mailto:xxxxx@lists.osr.com] On Behalf Of poltrone
>> Sent: Thursday, June 29, 2006 4:16 AM
>> To: Windows System Software Devs Interest List
>> Subject: [ntdev] WDM Interrupt Objects
>>
>> Up until now i thought that if i call IoConnectInterrupt() once per
>> device and store the returned PKINTERRUPT pointer in the device
>> extension then the first parameter of my ISR will have the same value
>> as the pointer in my device extension.
>>
>> e.g. :
>>
>> NTSTATUS StartDevice(…)
>> {
>> …
>>
>> Status = IoConnectInterrupt(&pDevExt->pIntObj, ISR, …);
>> …
>> }
>>
>> BOOLEAN ISR(PKINTERRUPT pIntObj, PVOID pContext)
>> {
>> DEVICEEXTENSION pDevExt = (DEVICEEXTENSION)pContext;
>>
>> if (pDevExt->pIntObj != pIntObj)
>> {
>> // not my IntObj. No need to waste time for
>> // asking HW if it did interrupt
>> return FALSE;
>> }
>>
>> int Reason = AskHwForIntReason()
>>
>> if (Reason == 0)
>> {
>> // HW did not interrupt
>> return FALSE;
>> }
>>
>>
>> …
>>
>> return TRUE;
>> }
>>
>>
>> That kind of code worked for several month until i began to use
>> different CPUs/Motherboards. On my current testsystem the expression
>> ‘pDevExt->pIntObj != pIntObj’ is true although the interrupt was
>> definitly
>> generated by my HW and since the code above does not handle the
>> interrupt
>> i get an never ending interrupt storm.
>>
>> Just removing the ‘if (pDevExt->pIntObj != pIntObj)’ block solves that
>> problem.
>>
>>
>> So i tried to find some information about this subject in the DDK. The
>> only thing i found so far is this:
>>
>>
>> The system creates an interrupt object for each processor the device is
>> capable of interrupting.
>>
>>
>>
>> Does that mean that when i call IoConnectInterrupt on a SMP system the
>> OS
>> creates an interrupt object for each processor but returns just a
>> pointer
>> to one of them while the parameter to the ISR can be a pointer to any of
>> them?
>>
>> regards,
>> poltrone
>>
>>
>>
>> —
>> Questions? First check the Kernel Driver FAQ at
>> http://www.osronline.com/article.cfm?id=256
>>
>> To unsubscribe, visit the List Server section of OSR Online at
>> http://www.osronline.com/page.cfm?name=ListServer
>>
>>
>
>
>