diff --git a/reactos/ntoskrnl/ex/init.c b/reactos/ntoskrnl/ex/init.c index 52e38c48692..7412853c26b 100644 --- a/reactos/ntoskrnl/ex/init.c +++ b/reactos/ntoskrnl/ex/init.c @@ -15,9 +15,6 @@ /* DATA **********************************************************************/ -/* HACK */ -extern BOOLEAN KiClockSetupComplete; - #define BUILD_OSCSDVERSION(major, minor) (((major & 0xFF) << 8) | (minor & 0xFF)) /* NT Version Info */ @@ -1127,9 +1124,6 @@ Phase1InitializationDiscard(PVOID Context) KeBootTimeBias = 0; } - /* The clock is ready now (FIXME: HACK FOR OLD HAL) */ - KiClockSetupComplete = TRUE; - /* Initialize all processors */ if (!HalAllProcessorsStarted()) KeBugCheck(HAL1_INITIALIZATION_FAILED); diff --git a/reactos/ntoskrnl/ex/time.c b/reactos/ntoskrnl/ex/time.c index 9acd4b18eaa..e3a6963b8af 100644 --- a/reactos/ntoskrnl/ex/time.c +++ b/reactos/ntoskrnl/ex/time.c @@ -82,7 +82,7 @@ ExRefreshTimeZoneInformation(IN PLARGE_INTEGER CurrentBootTime) NTSTATUS ExpSetTimeZoneInformation(PTIME_ZONE_INFORMATION TimeZoneInformation) { - LARGE_INTEGER LocalTime, SystemTime; + LARGE_INTEGER LocalTime, SystemTime, OldTime; TIME_FIELDS TimeFields; DPRINT("ExpSetTimeZoneInformation() called\n"); @@ -123,7 +123,7 @@ ExpSetTimeZoneInformation(PTIME_ZONE_INFORMATION TimeZoneInformation) ExLocalTimeToSystemTime(&LocalTime, &SystemTime); /* Set the new system time */ - KeSetSystemTime(&SystemTime, NULL, FALSE, NULL); + KeSetSystemTime(&SystemTime, &OldTime, FALSE, NULL); /* Return success */ DPRINT("ExpSetTimeZoneInformation() done\n"); @@ -184,16 +184,13 @@ NtSetSystemTime(IN PLARGE_INTEGER SystemTime, return STATUS_PRIVILEGE_NOT_HELD; } - /* Check if caller wants the old time */ - if(PreviousTime) KeQuerySystemTime(&OldSystemTime); - /* Convert the time and set it in HAL */ ExSystemTimeToLocalTime(&NewSystemTime, &LocalTime); RtlTimeToTimeFields(&LocalTime, &TimeFields); HalSetRealTimeClock(&TimeFields); /* Now set system time */ - KeSetSystemTime(&NewSystemTime, NULL, FALSE, NULL); + KeSetSystemTime(&NewSystemTime, &OldSystemTime, FALSE, NULL); /* Check if caller wanted previous time */ if(PreviousTime) diff --git a/reactos/ntoskrnl/include/internal/ke.h b/reactos/ntoskrnl/include/internal/ke.h index 40ba45824ea..14001887d16 100644 --- a/reactos/ntoskrnl/include/internal/ke.h +++ b/reactos/ntoskrnl/include/internal/ke.h @@ -85,7 +85,8 @@ extern PVOID KeUserCallbackDispatcher; extern PVOID KeUserExceptionDispatcher; extern PVOID KeRaiseUserExceptionDispatcher; extern LARGE_INTEGER KeBootTime; -extern ULONG KeBootTimeBias; +extern ULONGLONG KeBootTimeBias; +extern BOOLEAN ExCmosClockIsSane; extern ULONG KeI386NpxPresent; extern ULONG KeI386XMMIPresent; extern ULONG KeI386FxsrPresent; diff --git a/reactos/ntoskrnl/ke/clock.c b/reactos/ntoskrnl/ke/clock.c index cee80f92f6f..7f67a5e35ac 100644 --- a/reactos/ntoskrnl/ke/clock.c +++ b/reactos/ntoskrnl/ke/clock.c @@ -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 - * PURPOSE: Handle System Clock - * - * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) - Created - * David Welch & Phillip Susi - Implementation (?) + * PURPOSE: System Clock Support + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) */ - /* NOTES ******************************************************************/ -/* - * System time units are 100-nanosecond intervals - */ - -/* INCLUDES ***************************************************************/ +/* INCLUDES ******************************************************************/ #include - #define NDEBUG -#include +#include -#if defined (ALLOC_PRAGMA) -#pragma alloc_text(INIT, KiInitializeSystemClock) -#endif - -/* GLOBALS ****************************************************************/ +/* GLOBALS *******************************************************************/ LARGE_INTEGER KeBootTime; -ULONG KeBootTimeBias; -KDPC KiTimerExpireDpc; -BOOLEAN KiClockSetupComplete = FALSE; -ULONG KiTimeLimitIsrMicroseconds; - -/* - * Number of timer interrupts since initialisation - */ +ULONGLONG KeBootTimeBias; volatile KSYSTEM_TIME KeTickCount = {0}; volatile ULONG KiRawTicks = 0; +ULONG KeMaximumIncrement; +ULONG KeMinimumIncrement; +ULONG KeTimeAdjustment; +ULONG KeTimeIncrement; LONG KiTickOffset = 0; -/* - * 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 **************************************************************/ +/* PRIVATE FUNCTIONS *********************************************************/ VOID NTAPI -KeSetSystemTime(IN PLARGE_INTEGER NewSystemTime, +KeSetSystemTime(IN PLARGE_INTEGER NewTime, OUT PLARGE_INTEGER OldTime, IN BOOLEAN FixInterruptTime, - IN PLARGE_INTEGER HalTime) + IN PLARGE_INTEGER HalTime OPTIONAL) { - LARGE_INTEGER OldSystemTime; - LARGE_INTEGER DeltaTime; - KIRQL OldIrql; + TIME_FIELDS TimeFields; + KIRQL OldIrql, OldIrql2; + 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; - OldSystemTime.u.LowPart = SharedUserData->SystemTime.LowPart; + /* Loop the entries in this table and lock the timers */ + 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 */ - SharedUserData->SystemTime.LowPart = NewSystemTime->u.LowPart; - SharedUserData->SystemTime.High1Time = NewSystemTime->u.HighPart; - SharedUserData->SystemTime.High2Time = NewSystemTime->u.HighPart; + /* Setup a temporary list of expired timers */ + InitializeListHead(&TempList2); - /* Calculate the difference between the new and the old time */ - DeltaTime.QuadPart = NewSystemTime->QuadPart - OldSystemTime.QuadPart; + /* Loop absolute timers */ + while (TempList.Flink != &TempList) + { + /* Get the timer */ + Timer = CONTAINING_RECORD(TempList.Flink, KTIMER, TimerListEntry); + RemoveEntryList(&Timer->TimerListEntry); - /* Update system boot time */ - KeBootTime.QuadPart += DeltaTime.QuadPart; + /* Update the due time and handle */ + Timer->DueTime.QuadPart -= DeltaTime.QuadPart; + Hand = KiComputeTimerTableIndex(Timer->DueTime.QuadPart); + Timer->Header.Hand = (UCHAR)Hand; - /* Update absolute timers */ - DPRINT1("FIXME: TIMER UPDATE NOT DONE!!!\n"); + /* Lock the timer and re-insert it */ + 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); + } - /* - * NOTE: Expired timers will be processed at the next clock tick! - */ + /* Release the lock */ + KiReleaseTimerLock(LockQueue); + } + + /* FIXME: Process expired timers! */ + KiReleaseDispatcherLock(OldIrql); + + /* Revert affinity */ + KeRevertToUserAffinityThread(); } +/* PUBLIC FUNCTIONS **********************************************************/ + /* * @implemented */ ULONG -STDCALL +NTAPI 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; } @@ -121,47 +185,60 @@ KeQueryTimeIncrement(VOID) */ #undef KeQueryTickCount VOID -STDCALL -KeQueryTickCount(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 - */ +NTAPI +KeQueryTickCount(IN PLARGE_INTEGER TickCount) { - 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 */ VOID -STDCALL -KeQuerySystemTime(PLARGE_INTEGER CurrentTime) +NTAPI +KeQuerySystemTime(OUT PLARGE_INTEGER CurrentTime) { - do { - CurrentTime->u.HighPart = SharedUserData->SystemTime.High1Time; - CurrentTime->u.LowPart = SharedUserData->SystemTime.LowPart; - } while (CurrentTime->u.HighPart != SharedUserData->SystemTime.High2Time); + /* Loop until we get a perfect match */ + for (;;) + { + /* Read the time value */ + CurrentTime->HighPart = SharedUserData->SystemTime.High1Time; + CurrentTime->LowPart = SharedUserData->SystemTime.LowPart; + if (CurrentTime->HighPart == + SharedUserData->SystemTime.High2Time) break; + YieldProcessor(); + } } +/* + * @implemented + */ ULONGLONG -STDCALL +NTAPI KeQueryInterruptTime(VOID) { LARGE_INTEGER CurrentTime; - do { - CurrentTime.u.HighPart = SharedUserData->InterruptTime.High1Time; - CurrentTime.u.LowPart = SharedUserData->InterruptTime.LowPart; - } while (CurrentTime.u.HighPart != SharedUserData->InterruptTime.High2Time); + /* Loop until we get a perfect match */ + for (;;) + { + /* 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; } @@ -169,32 +246,20 @@ KeQueryInterruptTime(VOID) * @implemented */ VOID -STDCALL -KeSetTimeIncrement( - IN ULONG MaxIncrement, - IN ULONG MinIncrement) +NTAPI +KeSetTimeIncrement(IN ULONG MaxIncrement, + IN ULONG MinIncrement) { /* Set some Internal Variables */ - /* FIXME: We use a harcoded CLOCK_INCREMENT. That *must* be changed */ KeMaximumIncrement = MaxIncrement; - KeMinimumIncrement = MinIncrement; -} - -/* - * @implemented - */ -ULONG -STDCALL -NtGetTickCount(VOID) -{ - LARGE_INTEGER TickCount; - - KeQueryTickCount(&TickCount); - return TickCount.u.LowPart; + KeMinimumIncrement = max(MinIncrement, 10000); + KeTimeAdjustment = MaxIncrement; + KeTimeIncrement = MaxIncrement; + KiTickOffset = MaxIncrement; } NTSTATUS -STDCALL +NTAPI NtQueryTimerResolution(OUT PULONG MinimumResolution, OUT PULONG MaximumResolution, OUT PULONG ActualResolution) @@ -204,7 +269,7 @@ NtQueryTimerResolution(OUT PULONG MinimumResolution, } NTSTATUS -STDCALL +NTAPI NtSetTimerResolution(IN ULONG DesiredResolution, IN BOOLEAN SetResolution, OUT PULONG CurrentResolution) diff --git a/reactos/ntoskrnl/ke/dpc.c b/reactos/ntoskrnl/ke/dpc.c index 6e481eef1ca..0835f620a85 100644 --- a/reactos/ntoskrnl/ke/dpc.c +++ b/reactos/ntoskrnl/ke/dpc.c @@ -22,6 +22,8 @@ ULONG KiAdjustDpcThreshold = 20; ULONG KiIdealDpcRate = 20; BOOLEAN KeThreadDpcEnable; FAST_MUTEX KiGenericCallDpcMutex; +KDPC KiTimerExpireDpc; +ULONG KiTimeLimitIsrMicroseconds; /* PRIVATE FUNCTIONS *********************************************************/ diff --git a/reactos/ntoskrnl/mm/pagefile.c b/reactos/ntoskrnl/mm/pagefile.c index e9e14bb056b..3b5fed1dc03 100644 --- a/reactos/ntoskrnl/mm/pagefile.c +++ b/reactos/ntoskrnl/mm/pagefile.c @@ -363,7 +363,11 @@ MmReserveSwapPages(ULONG Nr) KIRQL oldIrql; ULONG MiAvailSwapPages; - if (!PagingReady) KEBUGCHECK(0); + if (!PagingReady) + { + DPRINT1("PAGING USED TOO SOON!!!\n"); + while (TRUE); + } KeAcquireSpinLock(&PagingFileListLock, &oldIrql); MiAvailSwapPages = (MiFreeSwapPages * MM_PAGEFILE_COMMIT_RATIO) + MM_PAGEFILE_COMMIT_GRACE; @@ -383,7 +387,11 @@ MmDereserveSwapPages(ULONG Nr) { KIRQL oldIrql; - if (!PagingReady) KEBUGCHECK(0); + if (!PagingReady) + { + DPRINT1("PAGING USED TOO SOON!!!\n"); + while (TRUE); + } KeAcquireSpinLock(&PagingFileListLock, &oldIrql); MiReservedSwapPages = MiReservedSwapPages - Nr; KeReleaseSpinLock(&PagingFileListLock, oldIrql); @@ -395,7 +403,11 @@ MiAllocPageFromPagingFile(PPAGINGFILE PagingFile) KIRQL oldIrql; ULONG i, j; - if (!PagingReady) KEBUGCHECK(0); + if (!PagingReady) + { + DPRINT1("PAGING USED TOO SOON!!!\n"); + while (TRUE); + } KeAcquireSpinLock(&PagingFile->AllocMapLock, &oldIrql); for (i = 0; i < PagingFile->AllocMapSize; i++) @@ -425,7 +437,11 @@ MmFreeSwapPage(SWAPENTRY Entry) ULONG off; KIRQL oldIrql; - if (!PagingReady) KEBUGCHECK(0); + if (!PagingReady) + { + DPRINT1("PAGING USED TOO SOON!!!\n"); + while (TRUE); + } i = FILE_FROM_ENTRY(Entry); off = OFFSET_FROM_ENTRY(Entry); @@ -470,7 +486,11 @@ MmAllocSwapPage(VOID) ULONG off; SWAPENTRY entry; - if (!PagingReady) KEBUGCHECK(0); + if (!PagingReady) + { + DPRINT1("PAGING USED TOO SOON!!!\n"); + while (TRUE); + } KeAcquireSpinLock(&PagingFileListLock, &oldIrql); if (MiFreeSwapPages == 0) diff --git a/reactos/ntoskrnl/mm/pageop.c b/reactos/ntoskrnl/mm/pageop.c index 4f33d07f0a7..9dd84c4e240 100644 --- a/reactos/ntoskrnl/mm/pageop.c +++ b/reactos/ntoskrnl/mm/pageop.c @@ -149,7 +149,11 @@ MmGetPageOp(PMEMORY_AREA MArea, HANDLE Pid, PVOID Address, KIRQL oldIrql; PMM_PAGEOP PageOp; - if (!PageOpReady) KEBUGCHECK(0); + if (!PageOpReady) + { + DPRINT1("PAGEOPS USED TOO SOON!!!\n"); + while (TRUE); + } /* * Calcuate the hash value for pageop structure @@ -269,3 +273,4 @@ MmInitializePageOp(VOID) + diff --git a/reactos/ntoskrnl/mm/rmap.c b/reactos/ntoskrnl/mm/rmap.c index cbd879ae642..19a96fc0aa2 100644 --- a/reactos/ntoskrnl/mm/rmap.c +++ b/reactos/ntoskrnl/mm/rmap.c @@ -390,7 +390,11 @@ MmInsertRmap(PFN_TYPE Page, PEPROCESS Process, PMM_RMAP_ENTRY new_entry; ULONG PrevSize; - if (!RmapReady) KEBUGCHECK(0); + if (!RmapReady) + { + DPRINT1("RMAPS USED TOO SOON!!!\n"); + while (TRUE); + } Address = (PVOID)PAGE_ROUND_DOWN(Address); @@ -459,6 +463,12 @@ MmDeleteAllRmaps(PFN_TYPE Page, PVOID Context, PMM_RMAP_ENTRY previous_entry; PEPROCESS Process; + if (!RmapReady) + { + DPRINT1("RMAPS USED TOO SOON!!!\n"); + while (TRUE); + } + ExAcquireFastMutex(&RmapListLock); current_entry = MmGetRmapListHeadPage(Page); if (current_entry == NULL) @@ -497,6 +507,12 @@ MmDeleteRmap(PFN_TYPE Page, PEPROCESS Process, { PMM_RMAP_ENTRY current_entry, previous_entry; + if (!RmapReady) + { + DPRINT1("RMAPS USED TOO SOON!!!\n"); + while (TRUE); + } + ExAcquireFastMutex(&RmapListLock); previous_entry = NULL; current_entry = MmGetRmapListHeadPage(Page);