Geoff Chappell - Software Analyst
This function acquires a queued spin lock at low IRQL, raising to SYNCH_LEVEL.
VOID FASTCALL KeAcquireInStackQueuedSpinLockRaiseToSynch ( KSPIN_LOCK *SpinLock, KLOCK_QUEUE_HANDLE *LockHandle);
The SpinLock argument provides the address of the spin lock that is to be acquired.
The LockHandle argument provides the address of an opaque context structure. This address is re-presented when releasing the lock. The context must have no other use until the lock has been released.
The KeAcquireInStackQueuedSpinLockRaiseToSynch function assumes that the IRQL is no higher than SYNCH_LEVEL. It returns with the IRQL at SYNCH_LEVEL. The spin lock and the context structure must be in non-paged memory when this function begins and must remain so until the lock is released.
The KeAcquireInStackQueuedSpinLockRaiseToSynch function is exported by name from x86 builds of the HAL in version 5.1 and higher and of the kernel in version 6.2 and higher. The HAL’s export in version 6.2 and higher is merely a forward to the kernel.
For 64-bit Windows, the KeAcquireInStackQueuedSpinLockRaiseToSynch function is exported by name from the kernel in all known versions, i.e., starting with the version 5.2 from Windows Server 2003 SP1.
The KeAcquireInStackQueuedSpinLockRaiseToSynch function is not documented.
The synchronisation level is at best semi-documented. The first known definition of SYNCH_LEVEL in a Device Driver Kit (DDK) is in the NTDDK.H from the DDK for Windows NT 4.0, but it has come and gone, sometimes changing its numerical value, sometimes being defined for some processor architectures only. The Windows Driver Kit (WDK) for Windows 10 refers to it in comments and even in annotations, yet never defines it. These notes presently leave it for another time.
The KeAcquireInStackQueuedSpinLockRaiseToSynch function is a compound. Its work is in two parts which can be done independently by calling exported functions or inlined routines: the first from the HAL (originally); the second from the kernel. The implementation gains by inlining its two parts and from skipping the second entirely for single-processor builds.
The first part is to raise the IRQL to SYNCH_LEVEL if it is not already there. This ensures that the current thread has exclusive use of the current processor. Interrupts can occur at higher IRQL, as with hardware interrupts, but they are not permitted to switch the processor to another thread. An equivalent exported function (x86) or inlined routine (x64) is KeRaiseIrqlToSynchLevel.
The second part is to arrange that the current processor has exclusive use of the protected resource. All threads that seek to use the resource must acquire the agreed lock. All call this function or a similar one so that all try to acquire the lock in the same way and are made to wait in a more or less tight loop until they own the lock. An equivalent exported function for this second part is KeAcquireInStackQueuedSpinLockAtDpcLevel. This part is trivial in single-processor builds.