- Implement KeUpdateSystemTime properly, it now saves and returns the old time, supports HAL time, as well as loops the timer list to fixup relative timers and expired timers after the time has changed.

- Replace mm failure detection code by dprint + while loop to avoid bugchecks which might make the error worse to see.
- Remove some deprecated code/functions and cleanup clock.c entirely.

svn path=/trunk/; revision=25626
This commit is contained in:
Alex Ionescu 2007-01-25 05:14:55 +00:00
parent 2691e0994a
commit 92208d72a8
8 changed files with 242 additions and 142 deletions

View file

@ -15,9 +15,6 @@
/* DATA **********************************************************************/ /* DATA **********************************************************************/
/* HACK */
extern BOOLEAN KiClockSetupComplete;
#define BUILD_OSCSDVERSION(major, minor) (((major & 0xFF) << 8) | (minor & 0xFF)) #define BUILD_OSCSDVERSION(major, minor) (((major & 0xFF) << 8) | (minor & 0xFF))
/* NT Version Info */ /* NT Version Info */
@ -1127,9 +1124,6 @@ Phase1InitializationDiscard(PVOID Context)
KeBootTimeBias = 0; KeBootTimeBias = 0;
} }
/* The clock is ready now (FIXME: HACK FOR OLD HAL) */
KiClockSetupComplete = TRUE;
/* Initialize all processors */ /* Initialize all processors */
if (!HalAllProcessorsStarted()) KeBugCheck(HAL1_INITIALIZATION_FAILED); if (!HalAllProcessorsStarted()) KeBugCheck(HAL1_INITIALIZATION_FAILED);

View file

@ -82,7 +82,7 @@ ExRefreshTimeZoneInformation(IN PLARGE_INTEGER CurrentBootTime)
NTSTATUS NTSTATUS
ExpSetTimeZoneInformation(PTIME_ZONE_INFORMATION TimeZoneInformation) ExpSetTimeZoneInformation(PTIME_ZONE_INFORMATION TimeZoneInformation)
{ {
LARGE_INTEGER LocalTime, SystemTime; LARGE_INTEGER LocalTime, SystemTime, OldTime;
TIME_FIELDS TimeFields; TIME_FIELDS TimeFields;
DPRINT("ExpSetTimeZoneInformation() called\n"); DPRINT("ExpSetTimeZoneInformation() called\n");
@ -123,7 +123,7 @@ ExpSetTimeZoneInformation(PTIME_ZONE_INFORMATION TimeZoneInformation)
ExLocalTimeToSystemTime(&LocalTime, &SystemTime); ExLocalTimeToSystemTime(&LocalTime, &SystemTime);
/* Set the new system time */ /* Set the new system time */
KeSetSystemTime(&SystemTime, NULL, FALSE, NULL); KeSetSystemTime(&SystemTime, &OldTime, FALSE, NULL);
/* Return success */ /* Return success */
DPRINT("ExpSetTimeZoneInformation() done\n"); DPRINT("ExpSetTimeZoneInformation() done\n");
@ -184,16 +184,13 @@ NtSetSystemTime(IN PLARGE_INTEGER SystemTime,
return STATUS_PRIVILEGE_NOT_HELD; return STATUS_PRIVILEGE_NOT_HELD;
} }
/* Check if caller wants the old time */
if(PreviousTime) KeQuerySystemTime(&OldSystemTime);
/* Convert the time and set it in HAL */ /* Convert the time and set it in HAL */
ExSystemTimeToLocalTime(&NewSystemTime, &LocalTime); ExSystemTimeToLocalTime(&NewSystemTime, &LocalTime);
RtlTimeToTimeFields(&LocalTime, &TimeFields); RtlTimeToTimeFields(&LocalTime, &TimeFields);
HalSetRealTimeClock(&TimeFields); HalSetRealTimeClock(&TimeFields);
/* Now set system time */ /* Now set system time */
KeSetSystemTime(&NewSystemTime, NULL, FALSE, NULL); KeSetSystemTime(&NewSystemTime, &OldSystemTime, FALSE, NULL);
/* Check if caller wanted previous time */ /* Check if caller wanted previous time */
if(PreviousTime) if(PreviousTime)

View file

@ -85,7 +85,8 @@ extern PVOID KeUserCallbackDispatcher;
extern PVOID KeUserExceptionDispatcher; extern PVOID KeUserExceptionDispatcher;
extern PVOID KeRaiseUserExceptionDispatcher; extern PVOID KeRaiseUserExceptionDispatcher;
extern LARGE_INTEGER KeBootTime; extern LARGE_INTEGER KeBootTime;
extern ULONG KeBootTimeBias; extern ULONGLONG KeBootTimeBias;
extern BOOLEAN ExCmosClockIsSane;
extern ULONG KeI386NpxPresent; extern ULONG KeI386NpxPresent;
extern ULONG KeI386XMMIPresent; extern ULONG KeI386XMMIPresent;
extern ULONG KeI386FxsrPresent; extern ULONG KeI386FxsrPresent;

View file

@ -1,118 +1,182 @@
/* /*
* COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS Kernel
* PROJECT: ReactOS kernel * LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/ke/clock.c * FILE: ntoskrnl/ke/clock.c
* PURPOSE: Handle System Clock * PURPOSE: System Clock Support
* * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net) - Created
* David Welch & Phillip Susi - Implementation (?)
*/ */
/* NOTES ******************************************************************/ /* INCLUDES ******************************************************************/
/*
* System time units are 100-nanosecond intervals
*/
/* INCLUDES ***************************************************************/
#include <ntoskrnl.h> #include <ntoskrnl.h>
#define NDEBUG #define NDEBUG
#include <internal/debug.h> #include <debug.h>
#if defined (ALLOC_PRAGMA) /* GLOBALS *******************************************************************/
#pragma alloc_text(INIT, KiInitializeSystemClock)
#endif
/* GLOBALS ****************************************************************/
LARGE_INTEGER KeBootTime; LARGE_INTEGER KeBootTime;
ULONG KeBootTimeBias; ULONGLONG KeBootTimeBias;
KDPC KiTimerExpireDpc;
BOOLEAN KiClockSetupComplete = FALSE;
ULONG KiTimeLimitIsrMicroseconds;
/*
* Number of timer interrupts since initialisation
*/
volatile KSYSTEM_TIME KeTickCount = {0}; volatile KSYSTEM_TIME KeTickCount = {0};
volatile ULONG KiRawTicks = 0; volatile ULONG KiRawTicks = 0;
ULONG KeMaximumIncrement;
ULONG KeMinimumIncrement;
ULONG KeTimeAdjustment;
ULONG KeTimeIncrement;
LONG KiTickOffset = 0; LONG KiTickOffset = 0;
/* /* PRIVATE FUNCTIONS *********************************************************/
* The increment in the system clock every timer tick (in system time units)
*
* = (1/18.2)*10^9
*
* RJJ was 54945055
*/
#define CLOCK_INCREMENT (100000)
ULONG KeMaximumIncrement = 100000;
ULONG KeMinimumIncrement = 100000;
ULONG KeTimeAdjustment = 100000;
#define MICROSECONDS_PER_TICK (10000)
#define TICKS_TO_CALIBRATE (1)
#define CALIBRATE_PERIOD (MICROSECONDS_PER_TICK * TICKS_TO_CALIBRATE)
/* FUNCTIONS **************************************************************/
VOID VOID
NTAPI NTAPI
KeSetSystemTime(IN PLARGE_INTEGER NewSystemTime, KeSetSystemTime(IN PLARGE_INTEGER NewTime,
OUT PLARGE_INTEGER OldTime, OUT PLARGE_INTEGER OldTime,
IN BOOLEAN FixInterruptTime, IN BOOLEAN FixInterruptTime,
IN PLARGE_INTEGER HalTime) IN PLARGE_INTEGER HalTime OPTIONAL)
{ {
LARGE_INTEGER OldSystemTime; TIME_FIELDS TimeFields;
LARGE_INTEGER DeltaTime; KIRQL OldIrql, OldIrql2;
KIRQL OldIrql; LARGE_INTEGER DeltaTime;
PLIST_ENTRY ListHead, NextEntry;
PKTIMER Timer;
PKSPIN_LOCK_QUEUE LockQueue;
LIST_ENTRY TempList, TempList2;
ULONG Hand, i;
PKTIMER_TABLE_ENTRY TimerEntry;
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); /* Sanity checks */
ASSERT((NewTime->HighPart & 0xF0000000) == 0);
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
OldIrql = KiAcquireDispatcherLock(); /* Check if this is for the HAL */
if (HalTime) RtlTimeToTimeFields(HalTime, &TimeFields);
do /* Set affinity to this CPU, lock the dispatcher, and raise IRQL */
KeSetSystemAffinityThread(1);
OldIrql = KiAcquireDispatcherLock();
KeRaiseIrql(HIGH_LEVEL, &OldIrql2);
/* Query the system time now */
KeQuerySystemTime(OldTime);
/* Set the new system time */
SharedUserData->SystemTime.LowPart = NewTime->LowPart;
SharedUserData->SystemTime.High1Time = NewTime->HighPart;
SharedUserData->SystemTime.High2Time = NewTime->HighPart;
/* Check if this was for the HAL and set the RTC time */
if (HalTime) ExCmosClockIsSane = HalSetRealTimeClock(&TimeFields);
/* Calculate the difference between the new and the old time */
DeltaTime.QuadPart = NewTime->QuadPart - OldTime->QuadPart;
/* Update system boot time */
KeBootTime.QuadPart += DeltaTime.QuadPart;
KeBootTimeBias = KeBootTimeBias + DeltaTime.QuadPart;
/* Lower IRQL back */
KeLowerIrql(OldIrql2);
/* Check if we need to adjust interrupt time */
if (FixInterruptTime) KEBUGCHECK(0);
/* Setup a temporary list of absolute timers */
InitializeListHead(&TempList);
/* Loop current timers */
for (i = 0; i < TIMER_TABLE_SIZE; i++)
{ {
OldSystemTime.u.HighPart = SharedUserData->SystemTime.High1Time; /* Loop the entries in this table and lock the timers */
OldSystemTime.u.LowPart = SharedUserData->SystemTime.LowPart; ListHead = &KiTimerTableListHead[i].Entry;
LockQueue = KiAcquireTimerLock(i);
NextEntry = ListHead->Flink;
while (NextEntry != ListHead)
{
/* Get the timer */
Timer = CONTAINING_RECORD(NextEntry, KTIMER, TimerListEntry);
NextEntry = NextEntry->Flink;
/* Is is absolute? */
if (Timer->Header.Absolute)
{
/* Remove it from the timer list */
if (RemoveEntryList(&Timer->TimerListEntry))
{
/* Get the entry and check if it's empty */
TimerEntry = &KiTimerTableListHead[Timer->Header.Hand];
if (IsListEmpty(&TimerEntry->Entry))
{
/* Clear the time then */
TimerEntry->Time.HighPart = 0xFFFFFFFF;
}
}
/* Insert it into our temporary list */
DPRINT1("Adding a timer!\n");
InsertTailList(&TempList, &Timer->TimerListEntry);
}
}
/* Release the lock */
KiReleaseTimerLock(LockQueue);
} }
while (OldSystemTime.u.HighPart != SharedUserData->SystemTime.High2Time);
/* Set the new system time */ /* Setup a temporary list of expired timers */
SharedUserData->SystemTime.LowPart = NewSystemTime->u.LowPart; InitializeListHead(&TempList2);
SharedUserData->SystemTime.High1Time = NewSystemTime->u.HighPart;
SharedUserData->SystemTime.High2Time = NewSystemTime->u.HighPart;
/* Calculate the difference between the new and the old time */ /* Loop absolute timers */
DeltaTime.QuadPart = NewSystemTime->QuadPart - OldSystemTime.QuadPart; while (TempList.Flink != &TempList)
{
/* Get the timer */
Timer = CONTAINING_RECORD(TempList.Flink, KTIMER, TimerListEntry);
RemoveEntryList(&Timer->TimerListEntry);
/* Update system boot time */ /* Update the due time and handle */
KeBootTime.QuadPart += DeltaTime.QuadPart; Timer->DueTime.QuadPart -= DeltaTime.QuadPart;
Hand = KiComputeTimerTableIndex(Timer->DueTime.QuadPart);
Timer->Header.Hand = (UCHAR)Hand;
/* Update absolute timers */ /* Lock the timer and re-insert it */
DPRINT1("FIXME: TIMER UPDATE NOT DONE!!!\n"); LockQueue = KiAcquireTimerLock(Hand);
if (KiInsertTimerTable(Timer, Hand))
{
/* Remove it from the timer list */
if (RemoveEntryList(&Timer->TimerListEntry))
{
/* Get the entry and check if it's empty */
TimerEntry = &KiTimerTableListHead[Timer->Header.Hand];
if (IsListEmpty(&TimerEntry->Entry))
{
/* Clear the time then */
TimerEntry->Time.HighPart = 0xFFFFFFFF;
}
}
KiReleaseDispatcherLock(OldIrql); /* Insert it into our temporary list */
DPRINT1("Adding a timer 2!\n");
InsertTailList(&TempList2, &Timer->TimerListEntry);
}
/* /* Release the lock */
* NOTE: Expired timers will be processed at the next clock tick! KiReleaseTimerLock(LockQueue);
*/ }
/* FIXME: Process expired timers! */
KiReleaseDispatcherLock(OldIrql);
/* Revert affinity */
KeRevertToUserAffinityThread();
} }
/* PUBLIC FUNCTIONS **********************************************************/
/* /*
* @implemented * @implemented
*/ */
ULONG ULONG
STDCALL NTAPI
KeQueryTimeIncrement(VOID) KeQueryTimeIncrement(VOID)
/*
* FUNCTION: Gets the increment (in 100-nanosecond units) that is added to
* the system clock every time the clock interrupts
* RETURNS: The increment
*/
{ {
/* Return the increment */
return KeMaximumIncrement; return KeMaximumIncrement;
} }
@ -121,47 +185,60 @@ KeQueryTimeIncrement(VOID)
*/ */
#undef KeQueryTickCount #undef KeQueryTickCount
VOID VOID
STDCALL NTAPI
KeQueryTickCount(PLARGE_INTEGER TickCount) KeQueryTickCount(IN PLARGE_INTEGER TickCount)
/*
* FUNCTION: Returns the number of ticks since the system was booted
* ARGUMENTS:
* TickCount (OUT) = Points to storage for the number of ticks
*/
{ {
TickCount->QuadPart = *(PULONGLONG)&KeTickCount; /* Loop until we get a perfect match */
for (;;)
{
/* Read the tick count value */
TickCount->HighPart = KeTickCount.High1Time;
TickCount->LowPart = KeTickCount.LowPart;
if (TickCount->HighPart == KeTickCount.High2Time) break;
YieldProcessor();
}
} }
/* /*
* FUNCTION: Gets the current system time
* ARGUMENTS:
* CurrentTime (OUT) = The routine stores the current time here
* NOTE: The time is the number of 100-nanosecond intervals since the
* 1st of January, 1601.
*
* @implemented * @implemented
*/ */
VOID VOID
STDCALL NTAPI
KeQuerySystemTime(PLARGE_INTEGER CurrentTime) KeQuerySystemTime(OUT PLARGE_INTEGER CurrentTime)
{ {
do { /* Loop until we get a perfect match */
CurrentTime->u.HighPart = SharedUserData->SystemTime.High1Time; for (;;)
CurrentTime->u.LowPart = SharedUserData->SystemTime.LowPart; {
} while (CurrentTime->u.HighPart != SharedUserData->SystemTime.High2Time); /* Read the time value */
CurrentTime->HighPart = SharedUserData->SystemTime.High1Time;
CurrentTime->LowPart = SharedUserData->SystemTime.LowPart;
if (CurrentTime->HighPart ==
SharedUserData->SystemTime.High2Time) break;
YieldProcessor();
}
} }
/*
* @implemented
*/
ULONGLONG ULONGLONG
STDCALL NTAPI
KeQueryInterruptTime(VOID) KeQueryInterruptTime(VOID)
{ {
LARGE_INTEGER CurrentTime; LARGE_INTEGER CurrentTime;
do { /* Loop until we get a perfect match */
CurrentTime.u.HighPart = SharedUserData->InterruptTime.High1Time; for (;;)
CurrentTime.u.LowPart = SharedUserData->InterruptTime.LowPart; {
} while (CurrentTime.u.HighPart != SharedUserData->InterruptTime.High2Time); /* Read the time value */
CurrentTime.HighPart = SharedUserData->InterruptTime.High1Time;
CurrentTime.LowPart = SharedUserData->InterruptTime.LowPart;
if (CurrentTime.HighPart ==
SharedUserData->InterruptTime.High2Time) break;
YieldProcessor();
}
/* Return the time value */
return CurrentTime.QuadPart; return CurrentTime.QuadPart;
} }
@ -169,32 +246,20 @@ KeQueryInterruptTime(VOID)
* @implemented * @implemented
*/ */
VOID VOID
STDCALL NTAPI
KeSetTimeIncrement( KeSetTimeIncrement(IN ULONG MaxIncrement,
IN ULONG MaxIncrement, IN ULONG MinIncrement)
IN ULONG MinIncrement)
{ {
/* Set some Internal Variables */ /* Set some Internal Variables */
/* FIXME: We use a harcoded CLOCK_INCREMENT. That *must* be changed */
KeMaximumIncrement = MaxIncrement; KeMaximumIncrement = MaxIncrement;
KeMinimumIncrement = MinIncrement; KeMinimumIncrement = max(MinIncrement, 10000);
} KeTimeAdjustment = MaxIncrement;
KeTimeIncrement = MaxIncrement;
/* KiTickOffset = MaxIncrement;
* @implemented
*/
ULONG
STDCALL
NtGetTickCount(VOID)
{
LARGE_INTEGER TickCount;
KeQueryTickCount(&TickCount);
return TickCount.u.LowPart;
} }
NTSTATUS NTSTATUS
STDCALL NTAPI
NtQueryTimerResolution(OUT PULONG MinimumResolution, NtQueryTimerResolution(OUT PULONG MinimumResolution,
OUT PULONG MaximumResolution, OUT PULONG MaximumResolution,
OUT PULONG ActualResolution) OUT PULONG ActualResolution)
@ -204,7 +269,7 @@ NtQueryTimerResolution(OUT PULONG MinimumResolution,
} }
NTSTATUS NTSTATUS
STDCALL NTAPI
NtSetTimerResolution(IN ULONG DesiredResolution, NtSetTimerResolution(IN ULONG DesiredResolution,
IN BOOLEAN SetResolution, IN BOOLEAN SetResolution,
OUT PULONG CurrentResolution) OUT PULONG CurrentResolution)

View file

@ -22,6 +22,8 @@ ULONG KiAdjustDpcThreshold = 20;
ULONG KiIdealDpcRate = 20; ULONG KiIdealDpcRate = 20;
BOOLEAN KeThreadDpcEnable; BOOLEAN KeThreadDpcEnable;
FAST_MUTEX KiGenericCallDpcMutex; FAST_MUTEX KiGenericCallDpcMutex;
KDPC KiTimerExpireDpc;
ULONG KiTimeLimitIsrMicroseconds;
/* PRIVATE FUNCTIONS *********************************************************/ /* PRIVATE FUNCTIONS *********************************************************/

View file

@ -363,7 +363,11 @@ MmReserveSwapPages(ULONG Nr)
KIRQL oldIrql; KIRQL oldIrql;
ULONG MiAvailSwapPages; ULONG MiAvailSwapPages;
if (!PagingReady) KEBUGCHECK(0); if (!PagingReady)
{
DPRINT1("PAGING USED TOO SOON!!!\n");
while (TRUE);
}
KeAcquireSpinLock(&PagingFileListLock, &oldIrql); KeAcquireSpinLock(&PagingFileListLock, &oldIrql);
MiAvailSwapPages = MiAvailSwapPages =
(MiFreeSwapPages * MM_PAGEFILE_COMMIT_RATIO) + MM_PAGEFILE_COMMIT_GRACE; (MiFreeSwapPages * MM_PAGEFILE_COMMIT_RATIO) + MM_PAGEFILE_COMMIT_GRACE;
@ -383,7 +387,11 @@ MmDereserveSwapPages(ULONG Nr)
{ {
KIRQL oldIrql; KIRQL oldIrql;
if (!PagingReady) KEBUGCHECK(0); if (!PagingReady)
{
DPRINT1("PAGING USED TOO SOON!!!\n");
while (TRUE);
}
KeAcquireSpinLock(&PagingFileListLock, &oldIrql); KeAcquireSpinLock(&PagingFileListLock, &oldIrql);
MiReservedSwapPages = MiReservedSwapPages - Nr; MiReservedSwapPages = MiReservedSwapPages - Nr;
KeReleaseSpinLock(&PagingFileListLock, oldIrql); KeReleaseSpinLock(&PagingFileListLock, oldIrql);
@ -395,7 +403,11 @@ MiAllocPageFromPagingFile(PPAGINGFILE PagingFile)
KIRQL oldIrql; KIRQL oldIrql;
ULONG i, j; ULONG i, j;
if (!PagingReady) KEBUGCHECK(0); if (!PagingReady)
{
DPRINT1("PAGING USED TOO SOON!!!\n");
while (TRUE);
}
KeAcquireSpinLock(&PagingFile->AllocMapLock, &oldIrql); KeAcquireSpinLock(&PagingFile->AllocMapLock, &oldIrql);
for (i = 0; i < PagingFile->AllocMapSize; i++) for (i = 0; i < PagingFile->AllocMapSize; i++)
@ -425,7 +437,11 @@ MmFreeSwapPage(SWAPENTRY Entry)
ULONG off; ULONG off;
KIRQL oldIrql; KIRQL oldIrql;
if (!PagingReady) KEBUGCHECK(0); if (!PagingReady)
{
DPRINT1("PAGING USED TOO SOON!!!\n");
while (TRUE);
}
i = FILE_FROM_ENTRY(Entry); i = FILE_FROM_ENTRY(Entry);
off = OFFSET_FROM_ENTRY(Entry); off = OFFSET_FROM_ENTRY(Entry);
@ -470,7 +486,11 @@ MmAllocSwapPage(VOID)
ULONG off; ULONG off;
SWAPENTRY entry; SWAPENTRY entry;
if (!PagingReady) KEBUGCHECK(0); if (!PagingReady)
{
DPRINT1("PAGING USED TOO SOON!!!\n");
while (TRUE);
}
KeAcquireSpinLock(&PagingFileListLock, &oldIrql); KeAcquireSpinLock(&PagingFileListLock, &oldIrql);
if (MiFreeSwapPages == 0) if (MiFreeSwapPages == 0)

View file

@ -149,7 +149,11 @@ MmGetPageOp(PMEMORY_AREA MArea, HANDLE Pid, PVOID Address,
KIRQL oldIrql; KIRQL oldIrql;
PMM_PAGEOP PageOp; PMM_PAGEOP PageOp;
if (!PageOpReady) KEBUGCHECK(0); if (!PageOpReady)
{
DPRINT1("PAGEOPS USED TOO SOON!!!\n");
while (TRUE);
}
/* /*
* Calcuate the hash value for pageop structure * Calcuate the hash value for pageop structure
@ -269,3 +273,4 @@ MmInitializePageOp(VOID)

View file

@ -390,7 +390,11 @@ MmInsertRmap(PFN_TYPE Page, PEPROCESS Process,
PMM_RMAP_ENTRY new_entry; PMM_RMAP_ENTRY new_entry;
ULONG PrevSize; ULONG PrevSize;
if (!RmapReady) KEBUGCHECK(0); if (!RmapReady)
{
DPRINT1("RMAPS USED TOO SOON!!!\n");
while (TRUE);
}
Address = (PVOID)PAGE_ROUND_DOWN(Address); Address = (PVOID)PAGE_ROUND_DOWN(Address);
@ -459,6 +463,12 @@ MmDeleteAllRmaps(PFN_TYPE Page, PVOID Context,
PMM_RMAP_ENTRY previous_entry; PMM_RMAP_ENTRY previous_entry;
PEPROCESS Process; PEPROCESS Process;
if (!RmapReady)
{
DPRINT1("RMAPS USED TOO SOON!!!\n");
while (TRUE);
}
ExAcquireFastMutex(&RmapListLock); ExAcquireFastMutex(&RmapListLock);
current_entry = MmGetRmapListHeadPage(Page); current_entry = MmGetRmapListHeadPage(Page);
if (current_entry == NULL) if (current_entry == NULL)
@ -497,6 +507,12 @@ MmDeleteRmap(PFN_TYPE Page, PEPROCESS Process,
{ {
PMM_RMAP_ENTRY current_entry, previous_entry; PMM_RMAP_ENTRY current_entry, previous_entry;
if (!RmapReady)
{
DPRINT1("RMAPS USED TOO SOON!!!\n");
while (TRUE);
}
ExAcquireFastMutex(&RmapListLock); ExAcquireFastMutex(&RmapListLock);
previous_entry = NULL; previous_entry = NULL;
current_entry = MmGetRmapListHeadPage(Page); current_entry = MmGetRmapListHeadPage(Page);