You shouldn’t protect data inside ISR, but out of it.
Each interrupt object has an interrupt spinlock in it. This spinlock is
obtained before your ISR be called and released after that. So your ISR
is already protected.
Knowing your ISR run in DIRQL, a normal spinlock had no effect. To
synchronize the accesses to shared resources, you must call
KeSynchronizeExecution from out your ISR.
Take a look at this link.
http://msdn2.microsoft.com/en-us/library/ms795140.aspx
Have fun,
–
Fernando Roberto da Silva
DriverEntry Kernel Development
http://www.driverentry.com.br
De: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] Em nome de Andrey
Kamchatnikov
Enviada em: quarta-feira, 18 de julho de 2007 07:57
Para: Windows System Software Devs Interest List
Assunto: [ntdev] locking shared data in Interrupt Service Routine
Hi,
Could someone please to help me with next question: how can I protect
data inside Isr?
Can I use normal spin lock?
Thank
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
> Could someone please to help me with next question: how can I protect data inside Isr?
If you want to synchronize with ISR, you have to use either KeSynchronizeExecution() or interrupt spinlock( only if the target OS version is meant to be >=5.1.) Please note that the system obtains interrupt spinlock that corresponds to a given KINTERRUPT object before calling ISR. Therefore, make sure you know what you are doing - if your ISR tries to acquire a spinlock that CPU already holds, it is going to deadlock…
Can I use normal spin lock?
You can (only as long as you know what you are doing - more on this below) , but you should not…
If you are just desperate to use a normal spinlock, then make sure that:
-
ISR obtains it with KeAcquireSpinLockAtDpcLevel() and releases it with KeReleaseSpinLockFromDpcLevel() - unlike KeAcquireSpinLock() and KeReleaseSpinLock(), these routines do not modify Task Priority Register, so that your ISR is still going to run at DIRQL, regardless of its spinlock operations. However, if you use KeAcquireSpinLock(), it will set IRQL to DISPATCH_LEVEL, and this is not the kind of thing that you want to do at DIRQL…
-
Non-ISR code raises IRQL to DIRQL before it acquires a spinlock (again, it has to get done at KeAcquireSpinLockAtDpcLevel()). Otherwise, if interrupt occurs while spinlock is held by non-ISR code and gets dispensed to the CPU that holds a given spinlock, a given CPU will deadlock when ISR tries to obtain a spinlock that CPU already holds, and all other CPUs will get deadlocked upon subsequent interrupts (because they will try to obtain a given spinlock from ISR, but this spinlock has no chance of ever getting released - CPU that holds it just has no chance to return from ISR)
All the above is purely a *THEORY* - in practical terms, you should not do it. Actually, I don’t know
how Driver Verifier will react if you try to test your driver with it, but there is a good chance that your test will fail. Instead, use interrupt spinlock or KeSynchronizeExecution() - this is how we are supposed to do things…
Anton Bassov
> Knowing your ISR run in DIRQL, a normal spinlock had no effect.
I am afraid you are much too optimistic - unless you know what you are doing, using normal spinlocks from ISR may have very, very negative effects…
Anton Bassov