KSPIN_LOCK_QUEUE_NUMBER

With Windows XP, Microsoft introduced the queued spin lock as improving on the basic spin lock because it “guarantees that processors acquire the spin lock on a first-come first-served basis”. Each contender for a lock not only specifies which lock but also provides a KSPIN_LOCK_QUEUE structure so that its contention for the lock can be queued. What Microsoft did not say when introducing queued spin locks for general use is that queued spin locks existed earlier for particular purposes. The KSPIN_LOCK_QUEUE_NUMBER lists those purposes. Each purpose has its own per-processor queued spin lock. Collectively, these are the LockQueue array of KSPIN_LOCK_QUEUE structures in each KPRCB. The KSPIN_LOCK_QUEUE_NUMBER indexes this array.

In 32-bit Windows, the KSPIN_LOCK_QUEUE_NUMBER is an enumeration (formally _KSPIN_LOCK_QUEUE_NUMBER). For 64-bit Windows, Microsoft seems to have rethought the exposure, e.g., in symbol files, and the KSPIN_LOCK_QUEUE_NUMBER is instead defined as a ULONG64. Either way, the possible values are the same.

The KSPIN_LOCK_QUEUE_NUMBER is not documented, but a C-language definition has long been published, first in NTDDK.H from the Device Driver Kit (DDK) for Windows XP and later in WDM.H. Its existence in these kits as anything other than an opaque type is something of a mystery, since the only use that is made of it in any other header from a DDK or Windows Driver Kit (WDK) is in NTIFS.H for declarations of such functions as KeAcquireQueuedSpinLock which have only ever been documented as reserved.

Value Name Versions
0x00 LockQueueDispatcherLock 5.0 to 6.0
LockQueueUnusedSpare0 6.1 and higher
0x01 LockQueueContextSwapLock 5.0 to 5.1
LockQueueUnusedSpare1 5.2
LockQueueExpansionLock 6.0 to 6.3
LockQueueUnusedSpare1 10.0 and higher
0x02 LockQueuePfnLock 5.0 to 6.0
LockQueueUnusedSpare2 6.1 and higher
0x03 LockQueueSystemSpaceLock 5.0 to 6.3
LockQueueUnusedSpare3 10.0 and higher
0x04 LockQueueVacbLock 5.0 and higher
0x05 LockQueueMasterLock 5.0 and higher
0x06 LockQueueNonPagedPoolLock 5.1 and higher
0x07 LockQueueIoCancelLock 5.1 and higher
0x08 LockQueueWorkQueueLock 5.1 and higher
0x09 LockQueueIoVpbLock 5.1 and higher
0x0A LockQueueIoDatabaseLock 5.1 and higher
0x0B LockQueueIoCompletionLock 5.1 and higher
0x0C LockQueueNtfsStructLock 5.1 and higher
0x0D LockQueueAfdWorkQueueLock 5.1 and higher
0x0E LockQueueBcbLock 5.1 and higher
0x0F LockQueueMmNonPagedPoolLock 5.2 to 6.3
LockQueueUnusedSpare15 10.0 and higher
0x10 LockQueueUnusuedSpare16 late 5.2 and higher
0x11 LockQueueTimerTableLock late 5.2 to 6.0
0x06 (5.0);
0x0F (5.1);
0x10 (early 5.2);
0x21 (late 5.2 to early 6.0);
0x31 (late 6.0);
0x11
LockQueueMaximumLock 5.0 and higher

Because the availability of C-language definitions and of type information in symbol files begins with Windows XP, interpretation for version 5.0 is not certain. Even in that version the LockQueue array has space for 0x10 queued spin locks. That only the first six are seen to be used (or even initialised) doesn’t mean that more were not defined.

The value LockQueueTimerTableLock selects a cache-aligned array of 0x10 or 0x20 lock queues for accessing the kernel’s timer table (shared among processors). This became redundant when Windows 7 introduced per-processor timer tables.