Geoff Chappell, Software Analyst
This function synchronises the execution of an arbitrary routine with a hardware interrupt’s service routine.
BOOLEAN KeSynchronizeExecution ( KINTERRUPT *Interrupt, KSYNCHRONIZE_ROUTINE *SynchronizeRoutine, PVOID SynchronizeContext);
The Interrupt argument is the address of the interrupt object that represents the service routine’s registration for handling the interrupt.
The SynchronizeRoutine is the address of a routine to call from inside the function, synchronisation with the service routine having been arranged.
The SynchronizeContext is arbitrary caller-supplied context that is to be passed back to the caller as an argument to the SynchronizeRoutine.
The function returns whatever the the SynchronizeRoutine returns.
The function temporarily raises the IRQL to the Device IRQL (DIRQL) that is specified for the interrupt. The IRQL on entry must be no higher. The SynchronizeRoutine executes at this raised IRQL.
The KeSynchronizeExecution function is exported by name from the kernel in all known versions, i.e., 3.10 and higher.
The KeSynchronizeExecution function is documented.
Put aside some developments for version 6.2 and higher, and the KeSynchronizeExecution function is in its essence a convenience whose work can be done independently in three parts:
The DIRQL is the SynchronizeIrql in the given KINTERRUPT. It will have been set when registering to handle the interrupt, e.g., as the SynchronizeIrql argument to the KeInitializeInterrupt or IoConnectInterrupt function. The spin lock is built into the KINTERRUPT by default but can have been supplied externally when registering to handle the interrupt, e.g., as the SpinLock argument to either of those functions.
Before version 5.1, controlling the IRQL and the spin lock independently requires that the caller remembers (accurately) what is configured in the KINTERRUPT. The KeSynchronizeExecution function is preferable even if the programmer thinks that working through a callback routine is cumbersome. Version 5.1 introduced the exported functions KeAcquireInterruptSpinLock and KeReleaseInterruptSpinLock, which allow the callback routine to be avoided in favour of a programming style that some find more natural.
The key development for version 6.2 is support for an interrupt’s service routine to execute at PASSIVE_LEVEL. This is indicated when the SynchronizeIrql is PASSIVE_LEVEL. The synchronisation is then not at higher IRQL with a spin lock but is instead with an event in a critical region, i.e., with normal kernel APCs disabled.
A curiosity for version 6.2 and higher is that the 32-bit coding remains in assembly language. The spin lock’s acquisition to execute the SynchronizeRoutine is therefore slightly different from the same lock’s acquisition by KeAcquireInterruptSpinLock.