update for HEAD-2003021201
[reactos.git] / ntoskrnl / ke / timer.c
index d66ef4a..500e80b 100644 (file)
@@ -35,8 +35,8 @@
 /*
  * Current time
  */
-static unsigned long long boot_time = 0;
-static unsigned long long system_time = 0;
+static LARGE_INTEGER boot_time = (LARGE_INTEGER)0LL;
+static LARGE_INTEGER system_time = (LARGE_INTEGER)0LL;
 
 /*
  * Number of timer interrupts since initialisation
@@ -58,9 +58,10 @@ volatile ULONG KiRawTicks = 0;
  */
 static LIST_ENTRY TimerListHead;
 static KSPIN_LOCK TimerListLock;
+static KSPIN_LOCK TimerValueLock;
 static KDPC ExpireTimerDpc;
 
-/* must raise IRQL to HIGH_LEVEL and grab spin lock there, to sync with ISR */
+/* must raise IRQL to PROFILE_LEVEL and grab spin lock there, to sync with ISR */
 
 extern ULONG PiNrRunnableThreads;
 
@@ -96,7 +97,18 @@ NTSTATUS STDCALL
 NtQueryPerformanceCounter(IN PLARGE_INTEGER Counter,
                          IN PLARGE_INTEGER Frequency)
 {
-  UNIMPLEMENTED;
+  LARGE_INTEGER PerfCounter;
+  LARGE_INTEGER PerfFrequency;
+
+  PerfCounter = KeQueryPerformanceCounter(&PerfFrequency);
+
+  if (Counter != NULL)
+    Counter->QuadPart = PerfCounter.QuadPart;
+
+  if (Frequency != NULL)
+    Frequency->QuadPart = PerfFrequency.QuadPart;
+
+  return(STATUS_SUCCESS);
 }
 
 
@@ -166,7 +178,12 @@ KeQuerySystemTime(PLARGE_INTEGER CurrentTime)
  * 1st of January, 1601.
  */
 {
-  CurrentTime->QuadPart = system_time;
+  KIRQL oldIrql;
+
+  KeRaiseIrql(PROFILE_LEVEL, &oldIrql);
+  KeAcquireSpinLockAtDpcLevel(&TimerValueLock);
+  *CurrentTime = system_time;
+  KeReleaseSpinLock(&TimerValueLock, oldIrql);
 }
 
 
@@ -221,14 +238,23 @@ KeSetTimerEx (PKTIMER             Timer,
  */
 {
    KIRQL oldlvl;
+   LARGE_INTEGER SystemTime;
    
    DPRINT("KeSetTimerEx(Timer %x), DueTime: \n",Timer);
-   KeAcquireSpinLock( &TimerListLock, &oldlvl );
-   
+
+   KeRaiseIrql(PROFILE_LEVEL, &oldlvl);
+   KeAcquireSpinLockAtDpcLevel(&TimerValueLock);
+
+   SystemTime = system_time;
+
+   KeReleaseSpinLock(&TimerValueLock, DISPATCH_LEVEL);
+   KeAcquireSpinLockAtDpcLevel(&TimerListLock);
+
    Timer->Dpc = Dpc;
    if (DueTime.QuadPart < 0)
      {
-       Timer->DueTime.QuadPart = system_time - DueTime.QuadPart;
+        
+       Timer->DueTime.QuadPart = SystemTime.QuadPart - DueTime.QuadPart;
      }
    else
      {
@@ -261,8 +287,7 @@ KeCancelTimer (PKTIMER      Timer)
    
    DPRINT("KeCancelTimer(Timer %x)\n",Timer);
    
-   KeRaiseIrql(HIGH_LEVEL, &oldlvl);
-   KeAcquireSpinLockAtDpcLevel( &TimerListLock );
+   KeAcquireSpinLock(&TimerListLock, &oldlvl);
                     
    if (Timer->TimerListEntry.Flink == NULL)
      {
@@ -380,20 +405,34 @@ KeExpireTimers(PKDPC Dpc,
    PLIST_ENTRY current_entry = NULL;
    PKTIMER current = NULL;
    ULONG Eip = (ULONG)Arg1;
+   KIRQL oldIrql;
+   LARGE_INTEGER SystemTime;
 
    DPRINT("KeExpireTimers()\n");
-   
-   current_entry = TimerListHead.Flink;
-   
+
+   KeRaiseIrql(PROFILE_LEVEL, &oldIrql);
+   KeAcquireSpinLockAtDpcLevel(&TimerValueLock);
+
+   SystemTime = system_time;
+
+   KeReleaseSpinLock(&TimerValueLock, oldIrql);
    KeAcquireSpinLockAtDpcLevel(&TimerListLock);
-   
+
+   if (KeGetCurrentIrql() > DISPATCH_LEVEL)
+   {
+       DPRINT1("-----------------------------\n");
+       KeBugCheck(0);
+   }
+
+
+   current_entry = TimerListHead.Flink;
+
    while (current_entry != &TimerListHead)
      {
        current = CONTAINING_RECORD(current_entry, KTIMER, TimerListEntry);
        
        current_entry = current_entry->Flink;
-       
-       if (system_time >= current->DueTime.QuadPart)
+       if ((ULONGLONG) SystemTime.QuadPart >= current->DueTime.QuadPart)
         {
           HandleExpiredTimer(current);
         }
@@ -412,6 +451,9 @@ KiUpdateSystemTime(KIRQL oldIrql,
  * FUNCTION: Handles a timer interrupt
  */
 {
+
+   assert(KeGetCurrentIrql() == PROFILE_LEVEL);
+
    KiRawTicks++;
    
    if (TimerInitDone == FALSE)
@@ -423,7 +465,10 @@ KiUpdateSystemTime(KIRQL oldIrql,
     */
    KeTickCount++;
    SharedUserData->TickCountLow++;
-   system_time = system_time + CLOCK_INCREMENT;
+
+   KeAcquireSpinLockAtDpcLevel(&TimerValueLock);
+   system_time.QuadPart += CLOCK_INCREMENT;
+   KeReleaseSpinLockFromDpcLevel(&TimerValueLock);
    
    /*
     * Queue a DPC that will expire timers
@@ -445,6 +490,7 @@ KeInitializeTimerImpl(VOID)
    DPRINT("KeInitializeTimerImpl()\n");
    InitializeListHead(&TimerListHead);
    KeInitializeSpinLock(&TimerListLock);
+   KeInitializeSpinLock(&TimerValueLock);
    KeInitializeDpc(&ExpireTimerDpc, KeExpireTimers, 0);
    TimerInitDone = TRUE;
    /*
@@ -452,7 +498,7 @@ KeInitializeTimerImpl(VOID)
     */
    HalQueryRealTimeClock(&TimeFields);
    RtlTimeFieldsToTime(&TimeFields, &SystemBootTime);
-   boot_time=SystemBootTime.QuadPart;
+   boot_time=SystemBootTime;
    system_time=boot_time;
 
    DPRINT("Finished KeInitializeTimerImpl()\n");