ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

time.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         ReactOS Kernel
00003  * LICENSE:         BSD - See COPYING.ARM in the top level directory
00004  * FILE:            ntoskrnl/ke/time.c
00005  * PURPOSE:         Implements timebase functionality
00006  * PROGRAMMERS:     ReactOS Portable Systems Group
00007  */
00008 
00009 /* INCLUDES *******************************************************************/
00010 
00011 #include <ntoskrnl.h>
00012 #define NDEBUG
00013 #include <debug.h>
00014 
00015 /* GLOBALS ********************************************************************/
00016 
00017 LONG KiTickOffset;
00018 ULONG KeTimeAdjustment;
00019 BOOLEAN KiTimeAdjustmentEnabled = FALSE;
00020 
00021 /* FUNCTIONS ******************************************************************/
00022 
00023 VOID
00024 FORCEINLINE
00025 KiWriteSystemTime(volatile KSYSTEM_TIME *SystemTime, ULARGE_INTEGER NewTime)
00026 {
00027 #ifdef _WIN64
00028     /* Do a single atomic write */
00029     *(ULONGLONG*)SystemTime = NewTime.QuadPart;
00030 #else
00031     /* Update in 3 steps, so that a reader can recognize partial updates */
00032     SystemTime->High1Time = NewTime.HighPart;
00033     SystemTime->LowPart = NewTime.LowPart;
00034     SystemTime->High2Time = NewTime.HighPart;
00035 #endif
00036 }
00037 
00038 VOID
00039 FORCEINLINE
00040 KiCheckForTimerExpiration(
00041     PKPRCB Prcb,
00042     PKTRAP_FRAME TrapFrame,
00043     ULARGE_INTEGER InterruptTime)
00044 {
00045     ULONG Hand;
00046 
00047     /* Check for timer expiration */
00048     Hand = KeTickCount.LowPart & (TIMER_TABLE_SIZE - 1);
00049     if (KiTimerTableListHead[Hand].Time.QuadPart <= InterruptTime.QuadPart)
00050     {
00051         /* Check if we are already doing expiration */
00052         if (!Prcb->TimerRequest)
00053         {
00054             /* Request a DPC to handle this */
00055             Prcb->TimerRequest = (ULONG_PTR)TrapFrame;
00056             Prcb->TimerHand = Hand;
00057             HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
00058         }
00059     }
00060 }
00061 
00062 VOID
00063 FASTCALL
00064 KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame,
00065                    IN ULONG Increment,
00066                    IN KIRQL Irql)
00067 {
00068     PKPRCB Prcb = KeGetCurrentPrcb();
00069     ULARGE_INTEGER CurrentTime, InterruptTime;
00070     LONG OldTickOffset;
00071 
00072     /* Check if this tick is being skipped */
00073     if (Prcb->SkipTick)
00074     {
00075         /* Handle it next time */
00076         Prcb->SkipTick = FALSE;
00077 
00078         /* Increase interrupt count and end the interrupt */
00079         Prcb->InterruptCount++;
00080         KiEndInterrupt(Irql, TrapFrame);
00081     }
00082 
00083     /* Add the increment time to the shared data */
00084     InterruptTime.QuadPart = *(ULONGLONG*)&SharedUserData->InterruptTime;
00085     InterruptTime.QuadPart += Increment;
00086     KiWriteSystemTime(&SharedUserData->InterruptTime, InterruptTime);
00087 
00088     /* Check for timer expiration */
00089     KiCheckForTimerExpiration(Prcb, TrapFrame, InterruptTime);
00090 
00091     /* Update the tick offset */
00092     OldTickOffset = InterlockedExchangeAdd(&KiTickOffset, -(LONG)Increment);
00093 
00094     /* If the debugger is enabled, check for break-in request */
00095     if (KdDebuggerEnabled && KdPollBreakIn())
00096     {
00097         /* Break-in requested! */
00098         DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
00099     }
00100 
00101     /* Check for full tick */
00102     if (OldTickOffset <= (LONG)Increment)
00103     {
00104         /* Update the system time */
00105         CurrentTime.QuadPart = *(ULONGLONG*)&SharedUserData->SystemTime;
00106         CurrentTime.QuadPart += KeTimeAdjustment;
00107         KiWriteSystemTime(&SharedUserData->SystemTime, CurrentTime);
00108 
00109         /* Update the tick count */
00110         CurrentTime.QuadPart = (*(ULONGLONG*)&KeTickCount) + 1;
00111         KiWriteSystemTime(&KeTickCount, CurrentTime);
00112 
00113         /* Update it in the shared user data */
00114         KiWriteSystemTime(&SharedUserData->TickCount, CurrentTime);
00115 
00116         /* Check for expiration with the new tick count as well */
00117         KiCheckForTimerExpiration(Prcb, TrapFrame, InterruptTime);
00118 
00119         /* Reset the tick offset */
00120         KiTickOffset += KeMaximumIncrement;
00121 
00122         /* Update processor/thread runtime */
00123         KeUpdateRunTime(TrapFrame, Irql);
00124     }
00125     else
00126     {
00127         /* Increase interrupt count only */
00128         Prcb->InterruptCount++;
00129     }
00130 
00131     /* Disable interrupts and end the interrupt */
00132     KiEndInterrupt(Irql, TrapFrame);
00133 }
00134 
00135 VOID
00136 NTAPI
00137 KeUpdateRunTime(IN PKTRAP_FRAME TrapFrame,
00138                 IN KIRQL Irql)
00139 {
00140     PKTHREAD Thread = KeGetCurrentThread();
00141     PKPRCB Prcb = KeGetCurrentPrcb();
00142 
00143     /* Check if this tick is being skipped */
00144     if (Prcb->SkipTick)
00145     {
00146         /* Handle it next time */
00147         Prcb->SkipTick = FALSE;
00148         return;
00149     }
00150 
00151     /* Increase interrupt count */
00152     Prcb->InterruptCount++;
00153 
00154     /* Check if we came from user mode */
00155 #ifndef _M_ARM
00156     if ((TrapFrame->SegCs & MODE_MASK) || (TrapFrame->EFlags & EFLAGS_V86_MASK))
00157 #else
00158     if (TrapFrame->PreviousMode == UserMode)
00159 #endif
00160     {
00161         /* Increase thread user time */
00162         Prcb->UserTime++;
00163         Thread->UserTime++;
00164     }
00165     else
00166     {
00167         /* See if we were in an ISR */
00168         Prcb->KernelTime++;
00169         if (Irql > DISPATCH_LEVEL)
00170         {
00171             /* Handle that */
00172             Prcb->InterruptTime++;
00173         }
00174         else if ((Irql < DISPATCH_LEVEL) || !(Prcb->DpcRoutineActive))
00175         {
00176             /* Handle being in kernel mode */
00177             Thread->KernelTime++;
00178         }
00179         else
00180         {
00181             /* Handle being in a DPC */
00182             Prcb->DpcTime++;
00183 
00184 #if 0 //DBG
00185             /* Update the DPC time */
00186             Prcb->DebugDpcTime++;
00187 
00188             /* Check if we have timed out */
00189             if (Prcb->DebugDpcTime == KiDPCTimeout);
00190             {
00191                 /* We did! */
00192                 DbgPrint("*** DPC routine > 1 sec --- This is not a break in KeUpdateSystemTime\n");
00193 
00194                 /* Break if debugger is enabled */
00195                 if (KdDebuggerEnabled) DbgBreakPoint();
00196 
00197                 /* Clear state */
00198                 Prcb->DebugDpcTime = 0;
00199             }
00200 #endif
00201         }
00202     }
00203 
00204     /* Update DPC rates */
00205     Prcb->DpcRequestRate = ((Prcb->DpcData[0].DpcCount - Prcb->DpcLastCount) +
00206                             Prcb->DpcRequestRate) >> 1;
00207     Prcb->DpcLastCount = Prcb->DpcData[0].DpcCount;
00208 
00209     /* Check if the queue is large enough */
00210     if ((Prcb->DpcData[0].DpcQueueDepth) && !(Prcb->DpcRoutineActive))
00211     {
00212         /* Request a DPC */
00213         Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;
00214         HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
00215 
00216         /* Fix the maximum queue depth */
00217         if ((Prcb->DpcRequestRate < KiIdealDpcRate) &&
00218             (Prcb->MaximumDpcQueueDepth > 1))
00219         {
00220             /* Make it smaller */
00221             Prcb->MaximumDpcQueueDepth--;
00222         }
00223     }
00224     else
00225     {
00226         /* Check if we've reached the adjustment limit */
00227         if (!(--Prcb->AdjustDpcThreshold))
00228         {
00229             /* Reset it, and check the queue maximum */
00230             Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;
00231             if (KiMaximumDpcQueueDepth != Prcb->MaximumDpcQueueDepth)
00232             {
00233                 /* Increase it */
00234                 Prcb->MaximumDpcQueueDepth++;
00235             }
00236         }
00237     }
00238 
00239     /* Decrement the thread quantum */
00240     Thread->Quantum -= CLOCK_QUANTUM_DECREMENT;
00241 
00242     /* Check if the time expired */
00243     if ((Thread->Quantum <= 0) && (Thread != Prcb->IdleThread))
00244     {
00245         /* Schedule a quantum end */
00246         Prcb->QuantumEnd = 1;
00247         HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
00248     }
00249 }

Generated on Sat May 26 2012 04:17:07 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.