-/*\r
- * PROJECT: ReactOS Kernel\r
- * LICENSE: GPL - See COPYING in the top level directory\r
- * FILE: ntoskrnl/ke/krnlinit.c\r
- * PURPOSE: Portable part of kernel initialization\r
- * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)\r
- */\r
-\r
-/* INCLUDES *****************************************************************/\r
-\r
-#include <ntoskrnl.h>\r
-#define NDEBUG\r
-#include <debug.h>\r
-#include <internal/napi.h>\r
-\r
-/* GLOBALS *******************************************************************/\r
-\r
-/* PRCB Array */\r
-PKPRCB KiProcessorBlock[MAXIMUM_PROCESSORS];\r
-\r
-/* NUMA Node Support */\r
-KNODE KiNode0;\r
-PKNODE KeNodeBlock[1];\r
-UCHAR KeNumberNodes = 1;\r
-UCHAR KeProcessNodeSeed;\r
-\r
-/* Initial Process and Thread */\r
-ETHREAD KiInitialThread;\r
-EPROCESS KiInitialProcess;\r
-\r
-/* System-defined Spinlocks */\r
-KSPIN_LOCK KiDispatcherLock;\r
-KSPIN_LOCK MmPfnLock;\r
-KSPIN_LOCK MmSystemSpaceLock;\r
-KSPIN_LOCK CcBcbSpinLock;\r
-KSPIN_LOCK CcMasterSpinLock;\r
-KSPIN_LOCK CcVacbSpinLock;\r
-KSPIN_LOCK CcWorkQueueSpinLock;\r
-KSPIN_LOCK NonPagedPoolLock;\r
-KSPIN_LOCK MmNonPagedPoolLock;\r
-KSPIN_LOCK IopCancelSpinLock;\r
-KSPIN_LOCK IopVpbSpinLock;\r
-KSPIN_LOCK IopDatabaseLock;\r
-KSPIN_LOCK IopCompletionLock;\r
-KSPIN_LOCK NtfsStructLock;\r
-KSPIN_LOCK AfdWorkQueueSpinLock;\r
-KSPIN_LOCK KiTimerTableLock[16];\r
-KSPIN_LOCK KiReverseStallIpiLock;\r
-\r
-/* FUNCTIONS *****************************************************************/\r
-\r
-VOID\r
-NTAPI\r
-KiInitSystem(VOID)\r
-{\r
- ULONG i;\r
-\r
- /* Initialize Bugcheck Callback data */\r
- InitializeListHead(&BugcheckCallbackListHead);\r
- InitializeListHead(&BugcheckReasonCallbackListHead);\r
- KeInitializeSpinLock(&BugCheckCallbackLock);\r
-\r
- /* Initialize the Timer Expiration DPC */\r
- KeInitializeDpc(&KiExpireTimerDpc, KiExpireTimers, NULL);\r
- KeSetTargetProcessorDpc(&KiExpireTimerDpc, 0);\r
-\r
- /* Initialize Profiling data */\r
- KeInitializeSpinLock(&KiProfileLock);\r
- InitializeListHead(&KiProfileListHead);\r
- InitializeListHead(&KiProfileSourceListHead);\r
-\r
- /* Loop the timer table */\r
- for (i = 0; i < TIMER_TABLE_SIZE; i++)\r
- {\r
- /* Initialize the list and entries */\r
- InitializeListHead(&KiTimerTableListHead[i].Entry);\r
- KiTimerTableListHead[i].Time.HighPart = 0xFFFFFFFF;\r
- KiTimerTableListHead[i].Time.LowPart = 0;\r
- }\r
-\r
- /* Initialize old-style list */\r
- InitializeListHead(&KiTimerListHead);\r
-\r
- /* Initialize the Swap event and all swap lists */\r
- KeInitializeEvent(&KiSwapEvent, SynchronizationEvent, FALSE);\r
- InitializeListHead(&KiProcessInSwapListHead);\r
- InitializeListHead(&KiProcessOutSwapListHead);\r
- InitializeListHead(&KiStackInSwapListHead);\r
-\r
- /* Initialize the mutex for generic DPC calls */\r
- KeInitializeMutex(&KiGenericCallDpcMutex, 0);\r
-\r
- /* Initialize the syscall table */\r
- KeServiceDescriptorTable[0].Base = MainSSDT;\r
- KeServiceDescriptorTable[0].Count = NULL;\r
- KeServiceDescriptorTable[0].Limit = NUMBER_OF_SYSCALLS;\r
- KeServiceDescriptorTable[1].Limit = 0;\r
- KeServiceDescriptorTable[0].Number = MainSSPT;\r
-\r
- /* Copy the the current table into the shadow table for win32k */\r
- RtlCopyMemory(KeServiceDescriptorTableShadow,\r
- KeServiceDescriptorTable,\r
- sizeof(KeServiceDescriptorTable));\r
-}\r
-\r
-LARGE_INTEGER\r
-NTAPI\r
-KiComputeReciprocal(IN LONG Divisor,\r
- OUT PUCHAR Shift)\r
-{\r
- LARGE_INTEGER Reciprocal = {{0}};\r
- LONG BitCount = 0, Remainder = 1;\r
-\r
- /* Start by calculating the remainder */\r
- while (Reciprocal.HighPart >= 0)\r
- {\r
- /* Increase the loop (bit) count */\r
- BitCount++;\r
-\r
- /* Calculate the current fraction */\r
- Reciprocal.HighPart = (Reciprocal.HighPart << 1) |\r
- (Reciprocal.LowPart >> 31);\r
- Reciprocal.LowPart <<= 1;\r
-\r
- /* Double the remainder and see if we went past the divisor */\r
- Remainder <<= 1;\r
- if (Remainder >= Divisor)\r
- {\r
- /* Set the low-bit and calculate the new remainder */\r
- Remainder -= Divisor;\r
- Reciprocal.LowPart |= 1;\r
- }\r
- }\r
-\r
- /* Check if we have a remainder */\r
- if (Remainder)\r
- {\r
- /* Check if the current fraction value is too large */\r
- if ((Reciprocal.LowPart == 0xFFFFFFFF) &&\r
- (Reciprocal.HighPart == 0xFFFFFFFF))\r
- {\r
- /* Set the high bit and reduce the bit count */\r
- Reciprocal.LowPart = 0;\r
- Reciprocal.HighPart = 0x80000000;\r
- BitCount--;\r
- }\r
- else\r
- {\r
- /* Check if only the lowest bits got too large */\r
- if (Reciprocal.LowPart == 0xFFFFFFFF)\r
- {\r
- /* Reset them and increase the high bits instead */\r
- Reciprocal.LowPart = 0;\r
- Reciprocal.HighPart++;\r
- }\r
- else\r
- {\r
- /* All is well, increase the low bits */\r
- Reciprocal.LowPart++;\r
- }\r
- }\r
- }\r
-\r
- /* Now calculate the actual shift and return the reciprocal */\r
- *Shift = (UCHAR)BitCount - 64;\r
- return Reciprocal;\r
-}\r
-\r
-VOID\r
-NTAPI\r
-KiInitSpinLocks(IN PKPRCB Prcb,\r
- IN CCHAR Number)\r
-{\r
- ULONG i;\r
-\r
- /* Initialize Dispatcher Fields */\r
- Prcb->QueueIndex = 1;\r
- Prcb->ReadySummary = 0;\r
- Prcb->DeferredReadyListHead.Next = NULL;\r
- for (i = 0; i < 32; i++)\r
- {\r
- /* Initialize the ready list */\r
- InitializeListHead(&Prcb->DispatcherReadyListHead[i]);\r
- }\r
-\r
- /* Initialize DPC Fields */\r
- InitializeListHead(&Prcb->DpcData[DPC_NORMAL].DpcListHead);\r
- KeInitializeSpinLock(&Prcb->DpcData[DPC_NORMAL].DpcLock);\r
- Prcb->DpcData[DPC_NORMAL].DpcQueueDepth = 0;\r
- Prcb->DpcData[DPC_NORMAL].DpcCount = 0;\r
- Prcb->DpcRoutineActive = FALSE;\r
- Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth;\r
- Prcb->MinimumDpcRate = KiMinimumDpcRate;\r
- Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;\r
- KeInitializeDpc(&Prcb->CallDpc, NULL, NULL);\r
- KeSetTargetProcessorDpc(&Prcb->CallDpc, Number);\r
- KeSetImportanceDpc(&Prcb->CallDpc, HighImportance);\r
-\r
- /* Initialize the Wait List Head */\r
- InitializeListHead(&Prcb->WaitListHead);\r
-\r
- /* Initialize Queued Spinlocks */\r
- Prcb->LockQueue[LockQueueDispatcherLock].Next = NULL;\r
- Prcb->LockQueue[LockQueueDispatcherLock].Lock = &KiDispatcherLock;\r
- Prcb->LockQueue[LockQueueExpansionLock].Next = NULL;\r
- Prcb->LockQueue[LockQueueExpansionLock].Lock = NULL;\r
- Prcb->LockQueue[LockQueuePfnLock].Next = NULL;\r
- Prcb->LockQueue[LockQueuePfnLock].Lock = &MmPfnLock;\r
- Prcb->LockQueue[LockQueueSystemSpaceLock].Next = NULL;\r
- Prcb->LockQueue[LockQueueSystemSpaceLock].Lock = &MmSystemSpaceLock;\r
- Prcb->LockQueue[LockQueueBcbLock].Next = NULL;\r
- Prcb->LockQueue[LockQueueBcbLock].Lock = &CcBcbSpinLock;\r
- Prcb->LockQueue[LockQueueMasterLock].Next = NULL;\r
- Prcb->LockQueue[LockQueueMasterLock].Lock = &CcMasterSpinLock;\r
- Prcb->LockQueue[LockQueueVacbLock].Next = NULL;\r
- Prcb->LockQueue[LockQueueVacbLock].Lock = &CcVacbSpinLock;\r
- Prcb->LockQueue[LockQueueWorkQueueLock].Next = NULL;\r
- Prcb->LockQueue[LockQueueWorkQueueLock].Lock = &CcWorkQueueSpinLock;\r
- Prcb->LockQueue[LockQueueNonPagedPoolLock].Next = NULL;\r
- Prcb->LockQueue[LockQueueNonPagedPoolLock].Lock = &NonPagedPoolLock;\r
- Prcb->LockQueue[LockQueueMmNonPagedPoolLock].Next = NULL;\r
- Prcb->LockQueue[LockQueueMmNonPagedPoolLock].Lock = &MmNonPagedPoolLock;\r
- Prcb->LockQueue[LockQueueIoCancelLock].Next = NULL;\r
- Prcb->LockQueue[LockQueueIoCancelLock].Lock = &IopCancelSpinLock;\r
- Prcb->LockQueue[LockQueueIoVpbLock].Next = NULL;\r
- Prcb->LockQueue[LockQueueIoVpbLock].Lock = &IopVpbSpinLock;\r
- Prcb->LockQueue[LockQueueIoDatabaseLock].Next = NULL;\r
- Prcb->LockQueue[LockQueueIoDatabaseLock].Lock = &IopDatabaseLock;\r
- Prcb->LockQueue[LockQueueIoCompletionLock].Next = NULL;\r
- Prcb->LockQueue[LockQueueIoCompletionLock].Lock = &IopCompletionLock;\r
- Prcb->LockQueue[LockQueueNtfsStructLock].Next = NULL;\r
- Prcb->LockQueue[LockQueueNtfsStructLock].Lock = &NtfsStructLock;\r
- Prcb->LockQueue[LockQueueAfdWorkQueueLock].Next = NULL;\r
- Prcb->LockQueue[LockQueueAfdWorkQueueLock].Lock = &AfdWorkQueueSpinLock;\r
- Prcb->LockQueue[LockQueueUnusedSpare16].Next = NULL;\r
- Prcb->LockQueue[LockQueueUnusedSpare16].Lock = NULL;\r
-\r
- /* Loop timer locks */\r
- for (i = 0; i < LOCK_QUEUE_TIMER_TABLE_LOCKS; i++)\r
- {\r
- /* Initialize the lock and setup the Queued Spinlock */\r
- KeInitializeSpinLock(&KiTimerTableLock[i]);\r
- Prcb->LockQueue[i].Next = NULL;\r
- Prcb->LockQueue[i].Lock = &KiTimerTableLock[i];\r
- }\r
-\r
- /* Check if this is the boot CPU */\r
- if (!Number)\r
- {\r
- /* Initialize the lock themselves */\r
- KeInitializeSpinLock(&KiDispatcherLock);\r
- KeInitializeSpinLock(&KiReverseStallIpiLock);\r
- KeInitializeSpinLock(&MmPfnLock);\r
- KeInitializeSpinLock(&MmSystemSpaceLock);\r
- KeInitializeSpinLock(&CcBcbSpinLock);\r
- KeInitializeSpinLock(&CcMasterSpinLock);\r
- KeInitializeSpinLock(&CcVacbSpinLock);\r
- KeInitializeSpinLock(&CcWorkQueueSpinLock);\r
- KeInitializeSpinLock(&IopCancelSpinLock);\r
- KeInitializeSpinLock(&IopCompletionLock);\r
- KeInitializeSpinLock(&IopDatabaseLock);\r
- KeInitializeSpinLock(&IopVpbSpinLock);\r
- KeInitializeSpinLock(&NonPagedPoolLock);\r
- KeInitializeSpinLock(&MmNonPagedPoolLock);\r
- KeInitializeSpinLock(&NtfsStructLock);\r
- KeInitializeSpinLock(&AfdWorkQueueSpinLock);\r
- KeInitializeDispatcher(); // ROS OLD DISPATCHER\r
- }\r
-}\r
-\r
-/* FIXME: Rename and make portable */\r
-VOID\r
-NTAPI\r
-KeInit2(VOID)\r
-{\r
- ULONG Protect;\r
-\r
-#ifdef _M_IX86\r
- /* Check if Fxsr was found */\r
- if (KeI386FxsrPresent)\r
- {\r
- /* Enable it. FIXME: Send an IPI */\r
- Ke386SetCr4(Ke386GetCr4() | X86_CR4_OSFXSR);\r
-\r
- /* Check if XMM was found too */\r
- if (KeI386XMMIPresent)\r
- {\r
- /* Enable it: FIXME: Send an IPI. */\r
- Ke386SetCr4(Ke386GetCr4() | X86_CR4_OSXMMEXCPT);\r
-\r
- /* FIXME: Implement and enable XMM Page Zeroing for Mm */\r
- }\r
- }\r
-\r
- if (KeFeatureBits & KF_GLOBAL_PAGE)\r
- {\r
- ULONG Flags;\r
- /* Enable global pages */\r
- Ke386GlobalPagesEnabled = TRUE;\r
- Ke386SaveFlags(Flags);\r
- Ke386DisableInterrupts();\r
- Ke386SetCr4(Ke386GetCr4() | X86_CR4_PGE);\r
- Ke386RestoreFlags(Flags);\r
- }\r
-\r
- if (KeFeatureBits & KF_FAST_SYSCALL)\r
- {\r
- extern void KiFastCallEntry(void);\r
-\r
- /* CS Selector of the target segment. */\r
- Ke386Wrmsr(0x174, KGDT_R0_CODE, 0);\r
- /* Target ESP. */\r
- Ke386Wrmsr(0x175, 0, 0);\r
- /* Target EIP. */\r
- Ke386Wrmsr(0x176, (ULONG_PTR)KiFastCallEntry, 0);\r
- }\r
-#endif\r
-\r
- /* Does the CPU Support 'prefetchnta' (SSE) */\r
- if(KeFeatureBits & KF_XMMI)\r
- {\r
- Protect = MmGetPageProtect(NULL, (PVOID)RtlPrefetchMemoryNonTemporal);\r
- MmSetPageProtect(NULL, (PVOID)RtlPrefetchMemoryNonTemporal, Protect | PAGE_IS_WRITABLE);\r
- /* Replace the ret by a nop */\r
- *(PCHAR)RtlPrefetchMemoryNonTemporal = 0x90;\r
- MmSetPageProtect(NULL, (PVOID)RtlPrefetchMemoryNonTemporal, Protect);\r
- }\r
-\r
- /* Set IDT to writable */\r
-#ifdef _M_IX86\r
- Protect = MmGetPageProtect(NULL, (PVOID)KiIdt);\r
- MmSetPageProtect(NULL, (PVOID)KiIdt, Protect | PAGE_IS_WRITABLE);\r
-#endif\r
-}\r
+/*
+ * PROJECT: ReactOS Kernel
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: ntoskrnl/ke/krnlinit.c
+ * PURPOSE: Portable part of kernel initialization
+ * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <ntoskrnl.h>
+#define NDEBUG
+#include <debug.h>
+#include <internal/napi.h>
+
+/* GLOBALS *******************************************************************/
+
+/* System call count */
+ULONG KiServiceLimit = NUMBER_OF_SYSCALLS;
+
+/* ARC Loader Block */
+PLOADER_PARAMETER_BLOCK KeLoaderBlock;
+
+/* PRCB Array */
+PKPRCB KiProcessorBlock[MAXIMUM_PROCESSORS];
+
+/* NUMA Node Support */
+KNODE KiNode0;
+PKNODE KeNodeBlock[1];
+UCHAR KeNumberNodes = 1;
+UCHAR KeProcessNodeSeed;
+
+/* Initial Process and Thread */
+ETHREAD KiInitialThread;
+EPROCESS KiInitialProcess;
+
+/* System-defined Spinlocks */
+KSPIN_LOCK KiDispatcherLock;
+KSPIN_LOCK MmPfnLock;
+KSPIN_LOCK MmSystemSpaceLock;
+KSPIN_LOCK CcBcbSpinLock;
+KSPIN_LOCK CcMasterSpinLock;
+KSPIN_LOCK CcVacbSpinLock;
+KSPIN_LOCK CcWorkQueueSpinLock;
+KSPIN_LOCK NonPagedPoolLock;
+KSPIN_LOCK MmNonPagedPoolLock;
+KSPIN_LOCK IopCancelSpinLock;
+KSPIN_LOCK IopVpbSpinLock;
+KSPIN_LOCK IopDatabaseLock;
+KSPIN_LOCK IopCompletionLock;
+KSPIN_LOCK NtfsStructLock;
+KSPIN_LOCK AfdWorkQueueSpinLock;
+KSPIN_LOCK KiTimerTableLock[16];
+KSPIN_LOCK KiReverseStallIpiLock;
+
+/* FUNCTIONS *****************************************************************/
+
+VOID
+NTAPI
+KiInitSystem(VOID)
+{
+ ULONG i;
+
+ /* Initialize Bugcheck Callback data */
+ InitializeListHead(&BugcheckCallbackListHead);
+ InitializeListHead(&BugcheckReasonCallbackListHead);
+ KeInitializeSpinLock(&BugCheckCallbackLock);
+
+ /* Initialize the Timer Expiration DPC */
+ KeInitializeDpc(&KiExpireTimerDpc, KiExpireTimers, NULL);
+ KeSetTargetProcessorDpc(&KiExpireTimerDpc, 0);
+
+ /* Initialize Profiling data */
+ KeInitializeSpinLock(&KiProfileLock);
+ InitializeListHead(&KiProfileListHead);
+ InitializeListHead(&KiProfileSourceListHead);
+
+ /* Loop the timer table */
+ for (i = 0; i < TIMER_TABLE_SIZE; i++)
+ {
+ /* Initialize the list and entries */
+ InitializeListHead(&KiTimerTableListHead[i].Entry);
+ KiTimerTableListHead[i].Time.HighPart = 0xFFFFFFFF;
+ KiTimerTableListHead[i].Time.LowPart = 0;
+ }
+
+ /* Initialize old-style list */
+ InitializeListHead(&KiTimerListHead);
+
+ /* Initialize the Swap event and all swap lists */
+ KeInitializeEvent(&KiSwapEvent, SynchronizationEvent, FALSE);
+ InitializeListHead(&KiProcessInSwapListHead);
+ InitializeListHead(&KiProcessOutSwapListHead);
+ InitializeListHead(&KiStackInSwapListHead);
+
+ /* Initialize the mutex for generic DPC calls */
+ KeInitializeMutex(&KiGenericCallDpcMutex, 0);
+
+ /* Initialize the syscall table */
+ KeServiceDescriptorTable[0].Base = MainSSDT;
+ KeServiceDescriptorTable[0].Count = NULL;
+ KeServiceDescriptorTable[0].Limit = KiServiceLimit;
+ KeServiceDescriptorTable[1].Limit = 0;
+ KeServiceDescriptorTable[0].Number = MainSSPT;
+
+ /* Copy the the current table into the shadow table for win32k */
+ RtlCopyMemory(KeServiceDescriptorTableShadow,
+ KeServiceDescriptorTable,
+ sizeof(KeServiceDescriptorTable));
+}
+
+LARGE_INTEGER
+NTAPI
+KiComputeReciprocal(IN LONG Divisor,
+ OUT PUCHAR Shift)
+{
+ LARGE_INTEGER Reciprocal = {{0}};
+ LONG BitCount = 0, Remainder = 1;
+
+ /* Start by calculating the remainder */
+ while (Reciprocal.HighPart >= 0)
+ {
+ /* Increase the loop (bit) count */
+ BitCount++;
+
+ /* Calculate the current fraction */
+ Reciprocal.HighPart = (Reciprocal.HighPart << 1) |
+ (Reciprocal.LowPart >> 31);
+ Reciprocal.LowPart <<= 1;
+
+ /* Double the remainder and see if we went past the divisor */
+ Remainder <<= 1;
+ if (Remainder >= Divisor)
+ {
+ /* Set the low-bit and calculate the new remainder */
+ Remainder -= Divisor;
+ Reciprocal.LowPart |= 1;
+ }
+ }
+
+ /* Check if we have a remainder */
+ if (Remainder)
+ {
+ /* Check if the current fraction value is too large */
+ if ((Reciprocal.LowPart == 0xFFFFFFFF) &&
+ (Reciprocal.HighPart == 0xFFFFFFFF))
+ {
+ /* Set the high bit and reduce the bit count */
+ Reciprocal.LowPart = 0;
+ Reciprocal.HighPart = 0x80000000;
+ BitCount--;
+ }
+ else
+ {
+ /* Check if only the lowest bits got too large */
+ if (Reciprocal.LowPart == 0xFFFFFFFF)
+ {
+ /* Reset them and increase the high bits instead */
+ Reciprocal.LowPart = 0;
+ Reciprocal.HighPart++;
+ }
+ else
+ {
+ /* All is well, increase the low bits */
+ Reciprocal.LowPart++;
+ }
+ }
+ }
+
+ /* Now calculate the actual shift and return the reciprocal */
+ *Shift = (UCHAR)BitCount - 64;
+ return Reciprocal;
+}
+
+VOID
+NTAPI
+KiInitSpinLocks(IN PKPRCB Prcb,
+ IN CCHAR Number)
+{
+ ULONG i;
+
+ /* Initialize Dispatcher Fields */
+ Prcb->QueueIndex = 1;
+ Prcb->ReadySummary = 0;
+ Prcb->DeferredReadyListHead.Next = NULL;
+ for (i = 0; i < 32; i++)
+ {
+ /* Initialize the ready list */
+ InitializeListHead(&Prcb->DispatcherReadyListHead[i]);
+ }
+
+ /* Initialize DPC Fields */
+ InitializeListHead(&Prcb->DpcData[DPC_NORMAL].DpcListHead);
+ KeInitializeSpinLock(&Prcb->DpcData[DPC_NORMAL].DpcLock);
+ Prcb->DpcData[DPC_NORMAL].DpcQueueDepth = 0;
+ Prcb->DpcData[DPC_NORMAL].DpcCount = 0;
+ Prcb->DpcRoutineActive = FALSE;
+ Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth;
+ Prcb->MinimumDpcRate = KiMinimumDpcRate;
+ Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;
+ KeInitializeDpc(&Prcb->CallDpc, NULL, NULL);
+ KeSetTargetProcessorDpc(&Prcb->CallDpc, Number);
+ KeSetImportanceDpc(&Prcb->CallDpc, HighImportance);
+
+ /* Initialize the Wait List Head */
+ InitializeListHead(&Prcb->WaitListHead);
+
+ /* Initialize Queued Spinlocks */
+ Prcb->LockQueue[LockQueueDispatcherLock].Next = NULL;
+ Prcb->LockQueue[LockQueueDispatcherLock].Lock = &KiDispatcherLock;
+ Prcb->LockQueue[LockQueueExpansionLock].Next = NULL;
+ Prcb->LockQueue[LockQueueExpansionLock].Lock = NULL;
+ Prcb->LockQueue[LockQueuePfnLock].Next = NULL;
+ Prcb->LockQueue[LockQueuePfnLock].Lock = &MmPfnLock;
+ Prcb->LockQueue[LockQueueSystemSpaceLock].Next = NULL;
+ Prcb->LockQueue[LockQueueSystemSpaceLock].Lock = &MmSystemSpaceLock;
+ Prcb->LockQueue[LockQueueBcbLock].Next = NULL;
+ Prcb->LockQueue[LockQueueBcbLock].Lock = &CcBcbSpinLock;
+ Prcb->LockQueue[LockQueueMasterLock].Next = NULL;
+ Prcb->LockQueue[LockQueueMasterLock].Lock = &CcMasterSpinLock;
+ Prcb->LockQueue[LockQueueVacbLock].Next = NULL;
+ Prcb->LockQueue[LockQueueVacbLock].Lock = &CcVacbSpinLock;
+ Prcb->LockQueue[LockQueueWorkQueueLock].Next = NULL;
+ Prcb->LockQueue[LockQueueWorkQueueLock].Lock = &CcWorkQueueSpinLock;
+ Prcb->LockQueue[LockQueueNonPagedPoolLock].Next = NULL;
+ Prcb->LockQueue[LockQueueNonPagedPoolLock].Lock = &NonPagedPoolLock;
+ Prcb->LockQueue[LockQueueMmNonPagedPoolLock].Next = NULL;
+ Prcb->LockQueue[LockQueueMmNonPagedPoolLock].Lock = &MmNonPagedPoolLock;
+ Prcb->LockQueue[LockQueueIoCancelLock].Next = NULL;
+ Prcb->LockQueue[LockQueueIoCancelLock].Lock = &IopCancelSpinLock;
+ Prcb->LockQueue[LockQueueIoVpbLock].Next = NULL;
+ Prcb->LockQueue[LockQueueIoVpbLock].Lock = &IopVpbSpinLock;
+ Prcb->LockQueue[LockQueueIoDatabaseLock].Next = NULL;
+ Prcb->LockQueue[LockQueueIoDatabaseLock].Lock = &IopDatabaseLock;
+ Prcb->LockQueue[LockQueueIoCompletionLock].Next = NULL;
+ Prcb->LockQueue[LockQueueIoCompletionLock].Lock = &IopCompletionLock;
+ Prcb->LockQueue[LockQueueNtfsStructLock].Next = NULL;
+ Prcb->LockQueue[LockQueueNtfsStructLock].Lock = &NtfsStructLock;
+ Prcb->LockQueue[LockQueueAfdWorkQueueLock].Next = NULL;
+ Prcb->LockQueue[LockQueueAfdWorkQueueLock].Lock = &AfdWorkQueueSpinLock;
+ Prcb->LockQueue[LockQueueUnusedSpare16].Next = NULL;
+ Prcb->LockQueue[LockQueueUnusedSpare16].Lock = NULL;
+
+ /* Loop timer locks */
+ for (i = 0; i < LOCK_QUEUE_TIMER_TABLE_LOCKS; i++)
+ {
+ /* Initialize the lock and setup the Queued Spinlock */
+ KeInitializeSpinLock(&KiTimerTableLock[i]);
+ Prcb->LockQueue[i].Next = NULL;
+ Prcb->LockQueue[i].Lock = &KiTimerTableLock[i];
+ }
+
+ /* Check if this is the boot CPU */
+ if (!Number)
+ {
+ /* Initialize the lock themselves */
+ KeInitializeSpinLock(&KiDispatcherLock);
+ KeInitializeSpinLock(&KiReverseStallIpiLock);
+ KeInitializeSpinLock(&MmPfnLock);
+ KeInitializeSpinLock(&MmSystemSpaceLock);
+ KeInitializeSpinLock(&CcBcbSpinLock);
+ KeInitializeSpinLock(&CcMasterSpinLock);
+ KeInitializeSpinLock(&CcVacbSpinLock);
+ KeInitializeSpinLock(&CcWorkQueueSpinLock);
+ KeInitializeSpinLock(&IopCancelSpinLock);
+ KeInitializeSpinLock(&IopCompletionLock);
+ KeInitializeSpinLock(&IopDatabaseLock);
+ KeInitializeSpinLock(&IopVpbSpinLock);
+ KeInitializeSpinLock(&NonPagedPoolLock);
+ KeInitializeSpinLock(&MmNonPagedPoolLock);
+ KeInitializeSpinLock(&NtfsStructLock);
+ KeInitializeSpinLock(&AfdWorkQueueSpinLock);
+ }
+}
+
+BOOLEAN
+NTAPI
+KeInitSystem(VOID)
+{
+ /* Check if Threaded DPCs are enabled */
+ if (KeThreadDpcEnable)
+ {
+ /* FIXME: TODO */
+ DPRINT1("Threaded DPCs not yet supported\n");
+ }
+
+ /* Initialize non-portable parts of the kernel */
+ KiInitMachineDependent();
+ return TRUE;
+}
+