ReactOS  r75907
dpc.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
Include dependency graph for dpc.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

VOID NTAPI KiCheckTimerTable (IN ULARGE_INTEGER CurrentTime)
 
VOID NTAPI KiTimerExpiration (IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
 
VOID FASTCALL KiTimerListExpire (IN PLIST_ENTRY ExpiredListHead, IN KIRQL OldIrql)
 
VOID NTAPI KiQuantumEnd (VOID)
 
VOID FASTCALL KiRetireDpcList (IN PKPRCB Prcb)
 
VOID NTAPI KiInitializeDpc (IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DeferredRoutine, IN PVOID DeferredContext, IN KOBJECTS Type)
 
VOID NTAPI KeInitializeThreadedDpc (IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DeferredRoutine, IN PVOID DeferredContext)
 
VOID NTAPI KeInitializeDpc (IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DeferredRoutine, IN PVOID DeferredContext)
 
BOOLEAN NTAPI KeInsertQueueDpc (IN PKDPC Dpc, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
 
BOOLEAN NTAPI KeRemoveQueueDpc (IN PKDPC Dpc)
 
VOID NTAPI KeFlushQueuedDpcs (VOID)
 
BOOLEAN NTAPI KeIsExecutingDpc (VOID)
 
VOID NTAPI KeSetImportanceDpc (IN PKDPC Dpc, IN KDPC_IMPORTANCE Importance)
 
VOID NTAPI KeSetTargetProcessorDpc (IN PKDPC Dpc, IN CCHAR Number)
 
VOID NTAPI KeGenericCallDpc (IN PKDEFERRED_ROUTINE Routine, IN PVOID Context)
 
VOID NTAPI KeSignalCallDpcDone (IN PVOID SystemArgument1)
 
BOOLEAN NTAPI KeSignalCallDpcSynchronize (IN PVOID SystemArgument2)
 

Variables

ULONG KiMaximumDpcQueueDepth = 4
 
ULONG KiMinimumDpcRate = 3
 
ULONG KiAdjustDpcThreshold = 20
 
ULONG KiIdealDpcRate = 20
 
BOOLEAN KeThreadDpcEnable
 
FAST_MUTEX KiGenericCallDpcMutex
 
KDPC KiTimerExpireDpc
 
ULONG KiTimeLimitIsrMicroseconds
 
ULONG KiDPCTimeout = 110
 

Macro Definition Documentation

#define NDEBUG

Definition at line 14 of file dpc.c.

Function Documentation

VOID NTAPI KeFlushQueuedDpcs ( VOID  )

Definition at line 918 of file dpc.c.

Referenced by ExpDeleteTimer(), and MmPageEntireDriver().

919 {
920  PKPRCB CurrentPrcb = KeGetCurrentPrcb();
921  PAGED_CODE();
922 
923  /* Check if this is an UP machine */
924  if (KeActiveProcessors == 1)
925  {
926  /* Check if there are DPCs on either queues */
927  if ((CurrentPrcb->DpcData[DPC_NORMAL].DpcQueueDepth > 0) ||
928  (CurrentPrcb->DpcData[DPC_THREADED].DpcQueueDepth > 0))
929  {
930  /* Request an interrupt */
932  }
933  }
934  else
935  {
936  /* FIXME: SMP support required */
937  ASSERT(FALSE);
938  }
939 }
#define DPC_NORMAL
KDPC_DATA DpcData[2]
Definition: ketypes.h:676
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1054
#define FALSE
Definition: types.h:117
#define PAGED_CODE()
Definition: video.h:57
KAFFINITY KeActiveProcessors
Definition: krnlinit.c:23
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
VOID FASTCALL HalRequestSoftwareInterrupt(IN KIRQL Irql)
Definition: pic.c:271
volatile ULONG DpcQueueDepth
Definition: ketypes.h:746
#define DPC_THREADED
VOID NTAPI KeGenericCallDpc ( IN PKDEFERRED_ROUTINE  Routine,
IN PVOID  Context 
)

Definition at line 983 of file dpc.c.

Referenced by ExGetPoolTagInfo().

985 {
986  ULONG Barrier = KeNumberProcessors;
987  KIRQL OldIrql;
988  DEFERRED_REVERSE_BARRIER ReverseBarrier;
990 
991  //
992  // The barrier is the number of processors, each processor will decrement it
993  // by one, so when all processors have run the DPC, the barrier reaches zero
994  //
995  ReverseBarrier.Barrier = Barrier;
996  ReverseBarrier.TotalProcessors = Barrier;
997 
998  //
999  // But we don't need the barrier on UP, since we can simply call the routine
1000  // directly while at DISPATCH_LEVEL and not worry about anything else
1001  //
1002  KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
1003  Routine(&KeGetCurrentPrcb()->CallDpc, Context, &Barrier, &ReverseBarrier);
1004  KeLowerIrql(OldIrql);
1005 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1054
UCHAR KIRQL
Definition: env_spec_w32.h:591
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
ULONG TotalProcessors
Definition: ke.h:42
CCHAR KeNumberProcessors
Definition: krnlinit.c:35
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
unsigned int ULONG
Definition: retypes.h:1
VOID NTAPI KeInitializeDpc ( IN PKDPC  Dpc,
IN PKDEFERRED_ROUTINE  DeferredRoutine,
IN PVOID  DeferredContext 
)

Definition at line 711 of file dpc.c.

Referenced by acpi_bus_init(), AddControllers(), AfdSelect(), ClassPnpStartDevice(), CmpCmdInit(), CmpInitDelayDerefKCBEngine(), CmpInitializeDelayedCloseTable(), CServiceGroup::CServiceGroup(), CTEInitTimer(), DriverEntry(), Ext2StartFloppyFlushDpc(), FFSStartFloppyFlushDpc(), FreeBT_AddDevice(), i8042KbdInternalDeviceControl(), i8042MouInternalDeviceControl(), InitController(), InitializeDeviceData(), InitPiceRunningTimer(), IntVideoPortCreateAdapterDeviceObject(), IoInitializeDpcRequest(), IoInitSystem(), IopRestartLogWorker(), KdInitSystem(), KeBalanceSetManager(), KeyboardDeviceWorker(), KiInitializeKernel(), KiInitSpinLocks(), KiInitSystem(), KsCreateBusEnumObject(), MsfsRead(), NdisIAddDevice(), NdisInitializeTimer(), NdisMInitializeTimer(), NdisMRegisterInterrupt(), NpAddWaiter(), NtCreateTimer(), PoInitializePrcb(), RetryTransferPacket(), RfsdStartFloppyFlushDpc(), RxInitializeRxTimer(), ScsiPortInitialize(), SerialAddDeviceInternal(), START_TEST(), StreamClassAddDevice(), TCPAllocateConnectionEndpoint(), USBH_SyncSubmitUrb(), USBPORT_RequestAsyncCallback(), USBPORT_SoftInterrupt(), USBPORT_StartDevice(), and USBPORT_StartTimer().

714 {
715  /* Call the internal routine */
716  KiInitializeDpc(Dpc, DeferredRoutine, DeferredContext, DpcObject);
717 }
VOID NTAPI KiInitializeDpc(IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DeferredRoutine, IN PVOID DeferredContext, IN KOBJECTS Type)
Definition: dpc.c:677
_In_ LARGE_INTEGER _In_opt_ PKDPC Dpc
Definition: kefuncs.h:524
_In_opt_ PVOID DeferredContext
Definition: ketypes.h:660
VOID NTAPI KeInitializeThreadedDpc ( IN PKDPC  Dpc,
IN PKDEFERRED_ROUTINE  DeferredRoutine,
IN PVOID  DeferredContext 
)

Definition at line 698 of file dpc.c.

Referenced by IoInitializeThreadedDpcRequest().

701 {
702  /* Call the internal routine */
704 }
VOID NTAPI KiInitializeDpc(IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DeferredRoutine, IN PVOID DeferredContext, IN KOBJECTS Type)
Definition: dpc.c:677
_In_ LARGE_INTEGER _In_opt_ PKDPC Dpc
Definition: kefuncs.h:524
_In_opt_ PVOID DeferredContext
Definition: ketypes.h:660
BOOLEAN NTAPI KeInsertQueueDpc ( IN PKDPC  Dpc,
IN PVOID  SystemArgument1,
IN PVOID  SystemArgument2 
)

Definition at line 724 of file dpc.c.

Referenced by acpi_bus_generate_event(), i8042KbdInterruptService(), i8042KbdQueuePacket(), i8042MouInterruptService(), i8042MouQueuePacket(), InterruptServiceRoutine(), IoRequestDpc(), Isr(), KdExitDebugger(), KeUpdateSystemTime(), KeyboardDeviceWorker(), KiSignalTimer(), KiTimerExpiration(), KiTimerListExpire(), KsGenerateEvent(), SerialInterruptService(), ServiceRoutine(), START_TEST(), StreamClassInterruptRoutine(), USBPORT_HcQueueWakeDpc(), USBPORT_InterruptService(), USBPORT_InvalidateEndpointHandler(), USBPORT_IsrDpcHandler(), USBPORT_QueueDoneTransfer(), USBPORT_SoftInterruptDpc(), and VideoPortQueueDpc().

727 {
728  KIRQL OldIrql;
729  PKPRCB Prcb, CurrentPrcb;
730  ULONG Cpu;
731  PKDPC_DATA DpcData;
732  BOOLEAN DpcConfigured = FALSE, DpcInserted = FALSE;
733  ASSERT_DPC(Dpc);
734 
735  /* Check IRQL and Raise it to HIGH_LEVEL */
736  KeRaiseIrql(HIGH_LEVEL, &OldIrql);
737  CurrentPrcb = KeGetCurrentPrcb();
738 
739  /* Check if the DPC has more then the maximum number of CPUs */
740  if (Dpc->Number >= MAXIMUM_PROCESSORS)
741  {
742  /* Then substract the maximum and get that PRCB. */
743  Cpu = Dpc->Number - MAXIMUM_PROCESSORS;
744  Prcb = KiProcessorBlock[Cpu];
745  }
746  else
747  {
748  /* Use the current one */
749  Prcb = CurrentPrcb;
750  Cpu = Prcb->Number;
751  }
752 
753  /* ROS Sanity Check */
754  ASSERT(Prcb == CurrentPrcb);
755 
756  /* Check if this is a threaded DPC and threaded DPCs are enabled */
757  if ((Dpc->Type == ThreadedDpcObject) && (Prcb->ThreadDpcEnable))
758  {
759  /* Then use the threaded data */
760  DpcData = &Prcb->DpcData[DPC_THREADED];
761  }
762  else
763  {
764  /* Otherwise, use the regular data */
765  DpcData = &Prcb->DpcData[DPC_NORMAL];
766  }
767 
768  /* Acquire the DPC lock */
769  KiAcquireSpinLock(&DpcData->DpcLock);
770 
771  /* Get the DPC Data */
772  if (!InterlockedCompareExchangePointer(&Dpc->DpcData, DpcData, NULL))
773  {
774  /* Now we can play with the DPC safely */
775  Dpc->SystemArgument1 = SystemArgument1;
776  Dpc->SystemArgument2 = SystemArgument2;
777  DpcData->DpcQueueDepth++;
778  DpcData->DpcCount++;
779  DpcConfigured = TRUE;
780 
781  /* Check if this is a high importance DPC */
782  if (Dpc->Importance == HighImportance)
783  {
784  /* Pre-empty other DPCs */
785  InsertHeadList(&DpcData->DpcListHead, &Dpc->DpcListEntry);
786  }
787  else
788  {
789  /* Add it at the end */
790  InsertTailList(&DpcData->DpcListHead, &Dpc->DpcListEntry);
791  }
792 
793  /* Check if this is the DPC on the threaded list */
794  if (&Prcb->DpcData[DPC_THREADED] == DpcData)
795  {
796  /* Make sure a threaded DPC isn't already active */
797  if (!(Prcb->DpcThreadActive) && !(Prcb->DpcThreadRequested))
798  {
799  /* FIXME: Setup Threaded DPC */
800  UNIMPLEMENTED_FATAL("Threaded DPC not supported\n");
801  }
802  }
803  else
804  {
805  /* Make sure a DPC isn't executing already */
806  if (!(Prcb->DpcRoutineActive) && !(Prcb->DpcInterruptRequested))
807  {
808  /* Check if this is the same CPU */
809  if (Prcb != CurrentPrcb)
810  {
811  /*
812  * Check if the DPC is of high importance or above the
813  * maximum depth. If it is, then make sure that the CPU
814  * isn't idle, or that it's sleeping.
815  */
816  if (((Dpc->Importance == HighImportance) ||
817  (DpcData->DpcQueueDepth >=
818  Prcb->MaximumDpcQueueDepth)) &&
819  (!(AFFINITY_MASK(Cpu) & KiIdleSummary) ||
820  (Prcb->Sleeping)))
821  {
822  /* Set interrupt requested */
823  Prcb->DpcInterruptRequested = TRUE;
824 
825  /* Set DPC inserted */
826  DpcInserted = TRUE;
827  }
828  }
829  else
830  {
831  /* Check if the DPC is of anything but low importance */
832  if ((Dpc->Importance != LowImportance) ||
833  (DpcData->DpcQueueDepth >=
834  Prcb->MaximumDpcQueueDepth) ||
835  (Prcb->DpcRequestRate < Prcb->MinimumDpcRate))
836  {
837  /* Set interrupt requested */
838  Prcb->DpcInterruptRequested = TRUE;
839 
840  /* Set DPC inserted */
841  DpcInserted = TRUE;
842  }
843  }
844  }
845  }
846  }
847 
848  /* Release the lock */
849  KiReleaseSpinLock(&DpcData->DpcLock);
850 
851  /* Check if the DPC was inserted */
852  if (DpcInserted)
853  {
854  /* Check if this was SMP */
855  if (Prcb != CurrentPrcb)
856  {
857  /* It was, request and IPI */
859  }
860  else
861  {
862  /* It wasn't, request an interrupt from HAL */
864  }
865  }
866 
867  /* Lower IRQL */
868  KeLowerIrql(OldIrql);
869  return DpcConfigured;
870 }
#define MAXIMUM_PROCESSORS
Definition: rwlock.h:5
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define TRUE
Definition: types.h:120
ULONG MinimumDpcRate
Definition: ketypes.h:685
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define DPC_NORMAL
UCHAR DpcThreadRequested
Definition: ketypes.h:687
KDPC_DATA DpcData[2]
Definition: ketypes.h:676
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1054
#define AFFINITY_MASK(Id)
Definition: ke.h:148
#define InsertTailList(ListHead, Entry)
#define ASSERT_DPC(Object)
ULONG_PTR DpcLock
Definition: ketypes.h:742
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define FALSE
Definition: types.h:117
VOID FASTCALL KiReleaseSpinLock(IN PKSPIN_LOCK SpinLock)
Definition: ntoskrnl.c:39
#define InterlockedCompareExchangePointer
Definition: interlocked.h:129
smooth NULL
Definition: ftsmooth.c:513
#define IPI_DPC
Definition: ketypes.h:233
ULONG DpcCount
Definition: ketypes.h:748
_In_opt_ PVOID _In_opt_ PVOID SystemArgument1
Definition: ketypes.h:660
unsigned char BOOLEAN
_In_ LARGE_INTEGER _In_opt_ PKDPC Dpc
Definition: kefuncs.h:524
UCHAR DpcRoutineActive
Definition: ketypes.h:688
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
UCHAR DpcInterruptRequested
Definition: ketypes.h:686
ULONG_PTR KiIdleSummary
Definition: thrdschd.c:25
VOID FASTCALL KiIpiSend(KAFFINITY TargetSet, ULONG IpiRequest)
UCHAR ThreadDpcEnable
Definition: ketypes.h:695
_In_opt_ PVOID _In_opt_ PVOID _In_opt_ PVOID SystemArgument2
Definition: ketypes.h:660
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
VOID FASTCALL HalRequestSoftwareInterrupt(IN KIRQL Irql)
Definition: pic.c:271
volatile ULONG DpcQueueDepth
Definition: ketypes.h:746
#define HIGH_LEVEL
Definition: env_spec_w32.h:703
#define DPC_THREADED
LONG Sleeping
Definition: ketypes.h:762
PKPRCB KiProcessorBlock[]
Definition: krnlinit.c:32
VOID FASTCALL KiAcquireSpinLock(IN PKSPIN_LOCK SpinLock)
Definition: ntoskrnl.c:32
UCHAR DpcThreadActive
Definition: ketypes.h:689
#define UNIMPLEMENTED_FATAL(...)
Definition: debug.h:243
USHORT Number
Definition: ketypes.h:559
unsigned int ULONG
Definition: retypes.h:1
ULONG DpcRequestRate
Definition: ketypes.h:684
LONG MaximumDpcQueueDepth
Definition: ketypes.h:683
BOOLEAN NTAPI KeRemoveQueueDpc ( IN PKDPC  Dpc)

Definition at line 877 of file dpc.c.

Referenced by ExTimerRundown(), NtCancelTimer(), NtSetTimer(), and START_TEST().

878 {
879  PKDPC_DATA DpcData;
880  BOOLEAN Enable;
881  ASSERT_DPC(Dpc);
882 
883  /* Disable interrupts */
884  Enable = KeDisableInterrupts();
885 
886  /* Get DPC data */
887  DpcData = Dpc->DpcData;
888  if (DpcData)
889  {
890  /* Acquire the DPC lock */
891  KiAcquireSpinLock(&DpcData->DpcLock);
892 
893  /* Make sure that the data didn't change */
894  if (DpcData == Dpc->DpcData)
895  {
896  /* Remove the DPC */
897  DpcData->DpcQueueDepth--;
898  RemoveEntryList(&Dpc->DpcListEntry);
899  Dpc->DpcData = NULL;
900  }
901 
902  /* Release the lock */
903  KiReleaseSpinLock(&DpcData->DpcLock);
904  }
905 
906  /* Re-enable interrupts */
907  if (Enable) _enable();
908 
909  /* Return if the DPC was in the queue or not */
910  return DpcData ? TRUE : FALSE;
911 }
#define TRUE
Definition: types.h:120
BOOLEAN Enable
Definition: acefiex.h:245
void __cdecl _enable(void)
Definition: intrin_arm.h:373
#define ASSERT_DPC(Object)
ULONG_PTR DpcLock
Definition: ketypes.h:742
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
#define FALSE
Definition: types.h:117
VOID FASTCALL KiReleaseSpinLock(IN PKSPIN_LOCK SpinLock)
Definition: ntoskrnl.c:39
smooth NULL
Definition: ftsmooth.c:513
FORCEINLINE BOOLEAN KeDisableInterrupts(VOID)
Definition: ke.h:152
unsigned char BOOLEAN
_In_ LARGE_INTEGER _In_opt_ PKDPC Dpc
Definition: kefuncs.h:524
volatile ULONG DpcQueueDepth
Definition: ketypes.h:746
VOID FASTCALL KiAcquireSpinLock(IN PKSPIN_LOCK SpinLock)
Definition: ntoskrnl.c:32
VOID NTAPI KeSetImportanceDpc ( IN PKDPC  Dpc,
IN KDPC_IMPORTANCE  Importance 
)

Definition at line 957 of file dpc.c.

Referenced by CServiceGroup::CServiceGroup(), and KiInitSpinLocks().

959 {
960  /* Set the DPC Importance */
961  ASSERT_DPC(Dpc);
962  Dpc->Importance = Importance;
963 }
#define ASSERT_DPC(Object)
_In_ LARGE_INTEGER _In_opt_ PKDPC Dpc
Definition: kefuncs.h:524
_In_ KDPC_IMPORTANCE Importance
Definition: kefuncs.h:93
VOID NTAPI KeSetTargetProcessorDpc ( IN PKDPC  Dpc,
IN CCHAR  Number 
)

Definition at line 970 of file dpc.c.

Referenced by KiInitializeKernel(), KiInitSpinLocks(), KiInitSystem(), and PoInitializePrcb().

972 {
973  /* Set a target CPU */
974  ASSERT_DPC(Dpc);
975  Dpc->Number = Number + MAXIMUM_PROCESSORS;
976 }
#define MAXIMUM_PROCESSORS
Definition: rwlock.h:5
#define ASSERT_DPC(Object)
_In_ LARGE_INTEGER _In_opt_ PKDPC Dpc
Definition: kefuncs.h:524
_In_opt_ PENTER_STATE_SYSTEM_HANDLER _In_opt_ PVOID _In_ LONG _In_opt_ LONG volatile * Number
Definition: ntpoapi.h:204
VOID NTAPI KeSignalCallDpcDone ( IN PVOID  SystemArgument1)

Definition at line 1012 of file dpc.c.

Referenced by ExpGetPoolTagInfoTarget().

1013 {
1014  //
1015  // Decrement the barrier, which is actually the processor count
1016  //
1018 }
_In_opt_ PVOID _In_opt_ PVOID SystemArgument1
Definition: ketypes.h:660
#define InterlockedDecrement
Definition: armddk.h:52
signed int * PLONG
Definition: retypes.h:5
BOOLEAN NTAPI KeSignalCallDpcSynchronize ( IN PVOID  SystemArgument2)

Definition at line 1025 of file dpc.c.

Referenced by ExpGetPoolTagInfoTarget().

1026 {
1027  //
1028  // There is nothing to do on UP systems -- the processor calling this wins
1029  //
1031  return TRUE;
1032 }
#define TRUE
Definition: types.h:120
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:315
_In_opt_ PVOID _In_opt_ PVOID _In_opt_ PVOID SystemArgument2
Definition: ketypes.h:660
VOID NTAPI KiCheckTimerTable ( IN ULARGE_INTEGER  CurrentTime)

Definition at line 33 of file dpc.c.

Referenced by KiTimerExpiration().

34 {
35 #if DBG
36  ULONG i = 0;
37  PLIST_ENTRY ListHead, NextEntry;
38  KIRQL OldIrql;
39  PKTIMER Timer;
40 
41  /* Raise IRQL to high and loop timers */
42  KeRaiseIrql(HIGH_LEVEL, &OldIrql);
43  do
44  {
45  /* Loop the current list */
46  ListHead = &KiTimerTableListHead[i].Entry;
47  NextEntry = ListHead->Flink;
48  while (NextEntry != ListHead)
49  {
50  /* Get the timer and move to the next one */
51  Timer = CONTAINING_RECORD(NextEntry, KTIMER, TimerListEntry);
52  NextEntry = NextEntry->Flink;
53 
54  /* Check if it expired */
55  if (Timer->DueTime.QuadPart <= CurrentTime.QuadPart)
56  {
57  /* Check if the DPC was queued, but didn't run */
58  if (!(KeGetCurrentPrcb()->TimerRequest) &&
59  !(*((volatile PULONG*)(&KiTimerExpireDpc.DpcData))))
60  {
61  /* This is bad, breakpoint! */
62  DPRINT1("Invalid timer state!\n");
63  DbgBreakPoint();
64  }
65  }
66  }
67 
68  /* Move to the next timer */
69  i++;
70  } while(i < TIMER_TABLE_SIZE);
71 
72  /* Lower IRQL and return */
73  KeLowerIrql(OldIrql);
74 #endif
75 }
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1054
void DbgBreakPoint()
Definition: mach.c:558
UCHAR KIRQL
Definition: env_spec_w32.h:591
GLenum GLclampf GLint i
Definition: glfuncs.h:14
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
struct _LIST_ENTRY * Flink
Definition: typedefs.h:120
KDPC KiTimerExpireDpc
Definition: dpc.c:25
#define TIMER_TABLE_SIZE
Definition: ketypes.h:821
LIST_ENTRY Entry
Definition: ketypes.h:666
ULARGE_INTEGER DueTime
Definition: ketypes.h:826
KTIMER_TABLE_ENTRY KiTimerTableListHead[TIMER_TABLE_SIZE]
Definition: timerobj.c:17
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
Definition: typedefs.h:118
#define HIGH_LEVEL
Definition: env_spec_w32.h:703
UINT Timer
Definition: capclock.c:11
unsigned int * PULONG
Definition: retypes.h:1
#define DPRINT1
Definition: precomp.h:8
unsigned int ULONG
Definition: retypes.h:1
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
volatile PVOID DpcData
Definition: ketypes.h:681
VOID NTAPI KiInitializeDpc ( IN PKDPC  Dpc,
IN PKDEFERRED_ROUTINE  DeferredRoutine,
IN PVOID  DeferredContext,
IN KOBJECTS  Type 
)

Definition at line 677 of file dpc.c.

Referenced by KeInitializeDpc(), and KeInitializeThreadedDpc().

681 {
682  /* Setup the DPC Object */
683  Dpc->Type = Type;
684  Dpc->Number = 0;
685  Dpc->Importance= MediumImportance;
686  Dpc->DeferredRoutine = DeferredRoutine;
687  Dpc->DeferredContext = DeferredContext;
688  Dpc->DpcData = NULL;
689 }
Type
Definition: Type.h:6
smooth NULL
Definition: ftsmooth.c:513
_In_ LARGE_INTEGER _In_opt_ PKDPC Dpc
Definition: kefuncs.h:524
_In_opt_ PVOID DeferredContext
Definition: ketypes.h:660
VOID NTAPI KiQuantumEnd ( VOID  )

Definition at line 465 of file dpc.c.

Referenced by KiDispatchInterrupt(), and KiDpcInterruptHandler().

466 {
467  PKPRCB Prcb = KeGetCurrentPrcb();
468  PKTHREAD NextThread, Thread = Prcb->CurrentThread;
469 
470  /* Check if a DPC Event was requested to be signaled */
472  {
473  /* Signal it */
474  KeSetEvent(&Prcb->DpcEvent, 0, 0);
475  }
476 
477  /* Raise to synchronization level and lock the PRCB and thread */
479  KiAcquireThreadLock(Thread);
480  KiAcquirePrcbLock(Prcb);
481 
482  /* Check if Quantum expired */
483  if (Thread->Quantum <= 0)
484  {
485  /* Check if we're real-time and with quantums disabled */
486  if ((Thread->Priority >= LOW_REALTIME_PRIORITY) &&
487  (Thread->ApcState.Process->DisableQuantum))
488  {
489  /* Otherwise, set maximum quantum */
490  Thread->Quantum = MAX_QUANTUM;
491  }
492  else
493  {
494  /* Reset the new Quantum */
495  Thread->Quantum = Thread->QuantumReset;
496 
497  /* Calculate new priority */
498  Thread->Priority = KiComputeNewPriority(Thread, 1);
499 
500  /* Check if a new thread is scheduled */
501  if (!Prcb->NextThread)
502  {
503  /* Get a new ready thread */
504  NextThread = KiSelectReadyThread(Thread->Priority, Prcb);
505  if (NextThread)
506  {
507  /* Found one, set it on standby */
508  NextThread->State = Standby;
509  Prcb->NextThread = NextThread;
510  }
511  }
512  else
513  {
514  /* Otherwise, make sure that this thread doesn't get preempted */
515  Thread->Preempted = FALSE;
516  }
517  }
518  }
519 
520  /* Release the thread lock */
521  KiReleaseThreadLock(Thread);
522 
523  /* Check if there's no thread scheduled */
524  if (!Prcb->NextThread)
525  {
526  /* Just leave now */
527  KiReleasePrcbLock(Prcb);
529  return;
530  }
531 
532  /* Get the next thread now */
533  NextThread = Prcb->NextThread;
534 
535  /* Set current thread's swap busy to true */
536  KiSetThreadSwapBusy(Thread);
537 
538  /* Switch threads in PRCB */
539  Prcb->NextThread = NULL;
540  Prcb->CurrentThread = NextThread;
541 
542  /* Set thread to running and the switch reason to Quantum End */
543  NextThread->State = Running;
544  Thread->WaitReason = WrQuantumEnd;
545 
546  /* Queue it on the ready lists */
547  KxQueueReadyThread(Thread, Prcb);
548 
549  /* Set wait IRQL to APC_LEVEL */
550  Thread->WaitIrql = APC_LEVEL;
551 
552  /* Swap threads */
553  KiSwapContext(APC_LEVEL, Thread);
554 
555  /* Lower IRQL back to DISPATCH_LEVEL */
557 }
FORCEINLINE VOID KiReleaseThreadLock(IN PKTHREAD Thread)
Definition: ke_x.h:244
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
FORCEINLINE VOID KiReleasePrcbLock(IN PKPRCB Prcb)
Definition: ke_x.h:224
FORCEINLINE VOID KiSetThreadSwapBusy(IN PKTHREAD Thread)
Definition: ke_x.h:204
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1054
SCHAR Priority
Definition: ketypes.h:974
#define MAX_QUANTUM
Definition: ketypes.h:136
#define LOW_REALTIME_PRIORITY
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
BOOLEAN Preempted
Definition: ketypes.h:1212
struct _KTHREAD * NextThread
Definition: ketypes.h:567
BOOLEAN FASTCALL KiSwapContext(IN KIRQL WaitIrql, IN PKTHREAD CurrentThread)
FORCEINLINE SCHAR KiComputeNewPriority(IN PKTHREAD Thread, IN SCHAR Adjustment)
Definition: ke_x.h:1458
FORCEINLINE VOID KxQueueReadyThread(IN PKTHREAD Thread, IN PKPRCB Prcb)
Definition: ke_x.h:1343
#define FALSE
Definition: types.h:117
KAPC_STATE ApcState
Definition: ketypes.h:969
struct _KTHREAD * CurrentThread
Definition: ketypes.h:566
FORCEINLINE VOID KiAcquirePrcbLock(IN PKPRCB Prcb)
Definition: ke_x.h:214
smooth NULL
Definition: ftsmooth.c:513
UCHAR WaitReason
Definition: ketypes.h:1249
KEVENT DpcEvent
Definition: ketypes.h:706
FORCEINLINE VOID KiAcquireThreadLock(IN PKTHREAD Thread)
Definition: ke_x.h:234
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
#define InterlockedExchange
Definition: armddk.h:54
UCHAR QuantumReset
Definition: ketypes.h:1300
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
FORCEINLINE PKTHREAD KiSelectReadyThread(IN KPRIORITY Priority, IN PKPRCB Prcb)
Definition: ke_x.h:1408
LONG DpcSetEventRequest
Definition: ketypes.h:699
volatile UCHAR State
Definition: ketypes.h:997
#define APC_LEVEL
Definition: env_spec_w32.h:695
KIRQL WaitIrql
Definition: ketypes.h:999
KIRQL NTAPI KeRaiseIrqlToSynchLevel(VOID)
Definition: pic.c:156
VOID FASTCALL KiRetireDpcList ( IN PKPRCB  Prcb)

Definition at line 561 of file dpc.c.

Referenced by KiDispatchInterrupt(), and KiIdleLoop().

562 {
563  PKDPC_DATA DpcData;
564  PLIST_ENTRY ListHead, DpcEntry;
565  PKDPC Dpc;
566  PKDEFERRED_ROUTINE DeferredRoutine;
568  ULONG_PTR TimerHand;
569 #ifdef CONFIG_SMP
570  KIRQL OldIrql;
571 #endif
572 
573  /* Get data and list variables before starting anything else */
574  DpcData = &Prcb->DpcData[DPC_NORMAL];
575  ListHead = &DpcData->DpcListHead;
576 
577  /* Main outer loop */
578  do
579  {
580  /* Set us as active */
581  Prcb->DpcRoutineActive = TRUE;
582 
583  /* Check if this is a timer expiration request */
584  if (Prcb->TimerRequest)
585  {
586  /* It is, get the timer hand and disable timer request */
587  TimerHand = Prcb->TimerHand;
588  Prcb->TimerRequest = 0;
589 
590  /* Expire timers with interrups enabled */
591  _enable();
592  KiTimerExpiration(NULL, NULL, (PVOID)TimerHand, NULL);
593  _disable();
594  }
595 
596  /* Loop while we have entries in the queue */
597  while (DpcData->DpcQueueDepth != 0)
598  {
599  /* Lock the DPC data and get the DPC entry*/
601  DpcEntry = ListHead->Flink;
602 
603  /* Make sure we have an entry */
604  if (DpcEntry != ListHead)
605  {
606  /* Remove the DPC from the list */
607  RemoveEntryList(DpcEntry);
608  Dpc = CONTAINING_RECORD(DpcEntry, KDPC, DpcListEntry);
609 
610  /* Clear its DPC data and save its parameters */
611  Dpc->DpcData = NULL;
612  DeferredRoutine = Dpc->DeferredRoutine;
613  DeferredContext = Dpc->DeferredContext;
614  SystemArgument1 = Dpc->SystemArgument1;
615  SystemArgument2 = Dpc->SystemArgument2;
616 
617  /* Decrease the queue depth */
618  DpcData->DpcQueueDepth--;
619 
620 #if DBG
621  /* Clear DPC Time */
622  Prcb->DebugDpcTime = 0;
623 #endif
624 
625  /* Release the lock */
627 
628  /* Re-enable interrupts */
629  _enable();
630 
631  /* Call the DPC */
632  DeferredRoutine(Dpc,
633  DeferredContext,
634  SystemArgument1,
635  SystemArgument2);
637 
638  /* Disable interrupts and keep looping */
639  _disable();
640  }
641  else
642  {
643  /* The queue should be flushed now */
644  ASSERT(DpcData->DpcQueueDepth == 0);
645 
646  /* Release DPC Lock */
648  }
649  }
650 
651  /* Clear DPC Flags */
652  Prcb->DpcRoutineActive = FALSE;
653  Prcb->DpcInterruptRequested = FALSE;
654 
655 #ifdef CONFIG_SMP
656  /* Check if we have deferred threads */
657  if (Prcb->DeferredReadyListHead.Next)
658  {
659 
660  /* Re-enable interrupts and raise to synch */
661  _enable();
662  OldIrql = KeRaiseIrqlToSynchLevel();
663 
664  /* Process deferred threads */
666 
667  /* Lower IRQL back and disable interrupts */
668  KeLowerIrql(OldIrql);
669  _disable();
670  }
671 #endif
672  } while (DpcData->DpcQueueDepth != 0);
673 }
DWORD *typedef PVOID
Definition: winlogon.h:52
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define TRUE
Definition: types.h:120
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
VOID NTAPI KiTimerExpiration(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
Definition: dpc.c:79
#define DPC_NORMAL
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
void __cdecl _enable(void)
Definition: intrin_arm.h:373
VOID NTAPI KeAcquireSpinLockAtDpcLevel(IN PKSPIN_LOCK SpinLock)
Definition: spinlock.c:192
ULONG_PTR DpcLock
Definition: ketypes.h:742
uint32_t ULONG_PTR
Definition: typedefs.h:64
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define FALSE
Definition: types.h:117
smooth NULL
Definition: ftsmooth.c:513
_In_opt_ PVOID _In_opt_ PVOID SystemArgument1
Definition: ketypes.h:660
struct _LIST_ENTRY * Flink
Definition: typedefs.h:120
_In_ LARGE_INTEGER _In_opt_ PKDPC Dpc
Definition: kefuncs.h:524
VOID NTAPI KeReleaseSpinLockFromDpcLevel(IN PKSPIN_LOCK SpinLock)
Definition: spinlock.c:215
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
Definition: ketypes.h:672
KDEFERRED_ROUTINE * PKDEFERRED_ROUTINE
Definition: ketypes.h:663
PVOID SystemArgument1
Definition: ketypes.h:679
Definition: typedefs.h:118
_In_opt_ PVOID _In_opt_ PVOID _In_opt_ PVOID SystemArgument2
Definition: ketypes.h:660
PVOID SystemArgument2
Definition: ketypes.h:680
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
volatile ULONG DpcQueueDepth
Definition: ketypes.h:746
void __cdecl _disable(void)
Definition: intrin_arm.h:365
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
volatile PVOID DpcData
Definition: ketypes.h:681
PKDEFERRED_ROUTINE DeferredRoutine
Definition: ketypes.h:677
PVOID DeferredContext
Definition: ketypes.h:678
KIRQL NTAPI KeRaiseIrqlToSynchLevel(VOID)
Definition: pic.c:156
VOID FASTCALL KiProcessDeferredReadyList(IN PKPRCB Prcb)
Definition: thrdschd.c:41
_In_opt_ PVOID DeferredContext
Definition: ketypes.h:660
VOID NTAPI KiTimerExpiration ( IN PKDPC  Dpc,
IN PVOID  DeferredContext,
IN PVOID  SystemArgument1,
IN PVOID  SystemArgument2 
)

Definition at line 79 of file dpc.c.

Referenced by KiInitializeKernel(), KiInitSystem(), and KiRetireDpcList().

83 {
84  ULARGE_INTEGER SystemTime, InterruptTime;
86  LONG Limit, Index, i;
87  ULONG Timers, ActiveTimers, DpcCalls;
88  PLIST_ENTRY ListHead, NextEntry;
89  KIRQL OldIrql;
90  PKTIMER Timer;
91  PKDPC TimerDpc;
92  ULONG Period;
94  PKSPIN_LOCK_QUEUE LockQueue;
95  PKPRCB Prcb = KeGetCurrentPrcb();
96 
97  /* Disable interrupts */
98  _disable();
99 
100  /* Query system and interrupt time */
101  KeQuerySystemTime((PLARGE_INTEGER)&SystemTime);
102  InterruptTime.QuadPart = KeQueryInterruptTime();
103  Limit = KeTickCount.LowPart;
104 
105  /* Bring interrupts back */
106  _enable();
107 
108  /* Get the index of the timer and normalize it */
109  Index = PtrToLong(SystemArgument1);
110  if ((Limit - Index) >= TIMER_TABLE_SIZE)
111  {
112  /* Normalize it */
113  Limit = Index + TIMER_TABLE_SIZE - 1;
114  }
115 
116  /* Setup index and actual limit */
117  Index--;
118  Limit &= (TIMER_TABLE_SIZE - 1);
119 
120  /* Setup accounting data */
121  DpcCalls = 0;
122  Timers = 24;
123  ActiveTimers = 4;
124 
125  /* Lock the Database and Raise IRQL */
126  OldIrql = KiAcquireDispatcherLock();
127 
128  /* Start expiration loop */
129  do
130  {
131  /* Get the current index */
132  Index = (Index + 1) & (TIMER_TABLE_SIZE - 1);
133 
134  /* Get list pointers and loop the list */
135  ListHead = &KiTimerTableListHead[Index].Entry;
136  while (ListHead != ListHead->Flink)
137  {
138  /* Lock the timer and go to the next entry */
139  LockQueue = KiAcquireTimerLock(Index);
140  NextEntry = ListHead->Flink;
141 
142  /* Get the current timer and check its due time */
143  Timers--;
144  Timer = CONTAINING_RECORD(NextEntry, KTIMER, TimerListEntry);
145  if ((NextEntry != ListHead) &&
146  (Timer->DueTime.QuadPart <= InterruptTime.QuadPart))
147  {
148  /* It's expired, remove it */
149  ActiveTimers--;
150  KiRemoveEntryTimer(Timer);
151 
152  /* Make it non-inserted, unlock it, and signal it */
153  Timer->Header.Inserted = FALSE;
154  KiReleaseTimerLock(LockQueue);
155  Timer->Header.SignalState = 1;
156 
157  /* Get the DPC and period */
158  TimerDpc = Timer->Dpc;
159  Period = Timer->Period;
160 
161  /* Check if there's any waiters */
162  if (!IsListEmpty(&Timer->Header.WaitListHead))
163  {
164  /* Check the type of event */
165  if (Timer->Header.Type == TimerNotificationObject)
166  {
167  /* Unwait the thread */
169  }
170  else
171  {
172  /* Otherwise unwait the thread and signal the timer */
174  }
175  }
176 
177  /* Check if we have a period */
178  if (Period)
179  {
180  /* Calculate the interval and insert the timer */
181  Interval.QuadPart = Int32x32To64(Period, -10000);
182  while (!KiInsertTreeTimer(Timer, Interval));
183  }
184 
185  /* Check if we have a DPC */
186  if (TimerDpc)
187  {
188 #ifdef CONFIG_SMP
189  /*
190  * If the DPC is targeted to another processor,
191  * then insert it into that processor's DPC queue
192  * instead of delivering it now.
193  * If the DPC is a threaded DPC, and the current CPU
194  * has threaded DPCs enabled (KiExecuteDpc is actively parsing DPCs),
195  * then also insert it into the DPC queue for threaded delivery,
196  * instead of doing it here.
197  */
198  if (((TimerDpc->Number >= MAXIMUM_PROCESSORS) &&
199  ((TimerDpc->Number - MAXIMUM_PROCESSORS) != Prcb->Number)) ||
200  ((TimerDpc->Type == ThreadedDpcObject) && (Prcb->ThreadDpcEnable)))
201  {
202  /* Queue it */
203  KeInsertQueueDpc(TimerDpc,
204  UlongToPtr(SystemTime.LowPart),
205  UlongToPtr(SystemTime.HighPart));
206  }
207  else
208 #endif
209  {
210  /* Setup the DPC Entry */
211  DpcEntry[DpcCalls].Dpc = TimerDpc;
212  DpcEntry[DpcCalls].Routine = TimerDpc->DeferredRoutine;
213  DpcEntry[DpcCalls].Context = TimerDpc->DeferredContext;
214  DpcCalls++;
215  ASSERT(DpcCalls < MAX_TIMER_DPCS);
216  }
217  }
218 
219  /* Check if we're done processing */
220  if (!(ActiveTimers) || !(Timers))
221  {
222  /* Release the dispatcher while doing DPCs */
224 
225  /* Start looping all DPC Entries */
226  for (i = 0; DpcCalls; DpcCalls--, i++)
227  {
228 #if DBG
229  /* Clear DPC Time */
230  Prcb->DebugDpcTime = 0;
231 #endif
232 
233  /* Call the DPC */
234  DpcEntry[i].Routine(DpcEntry[i].Dpc,
235  DpcEntry[i].Context,
236  UlongToPtr(SystemTime.LowPart),
237  UlongToPtr(SystemTime.HighPart));
238  }
239 
240  /* Reset accounting */
241  Timers = 24;
242  ActiveTimers = 4;
243 
244  /* Lock the dispatcher database */
246  }
247  }
248  else
249  {
250  /* Check if the timer list is empty */
251  if (NextEntry != ListHead)
252  {
253  /* Sanity check */
255  Timer->DueTime.QuadPart);
256 
257  /* Update the time */
258  _disable();
260  Timer->DueTime.QuadPart;
261  _enable();
262  }
263 
264  /* Release the lock */
265  KiReleaseTimerLock(LockQueue);
266 
267  /* Check if we've scanned all the timers we could */
268  if (!Timers)
269  {
270  /* Release the dispatcher while doing DPCs */
272 
273  /* Start looping all DPC Entries */
274  for (i = 0; DpcCalls; DpcCalls--, i++)
275  {
276 #if DBG
277  /* Clear DPC Time */
278  Prcb->DebugDpcTime = 0;
279 #endif
280 
281  /* Call the DPC */
282  DpcEntry[i].Routine(DpcEntry[i].Dpc,
283  DpcEntry[i].Context,
284  UlongToPtr(SystemTime.LowPart),
285  UlongToPtr(SystemTime.HighPart));
286  }
287 
288  /* Reset accounting */
289  Timers = 24;
290  ActiveTimers = 4;
291 
292  /* Lock the dispatcher database */
294  }
295 
296  /* Done looping */
297  break;
298  }
299  }
300  } while (Index != Limit);
301 
302  /* Verify the timer table, on debug builds */
303  if (KeNumberProcessors == 1) KiCheckTimerTable(InterruptTime);
304 
305  /* Check if we still have DPC entries */
306  if (DpcCalls)
307  {
308  /* Release the dispatcher while doing DPCs */
310 
311  /* Start looping all DPC Entries */
312  for (i = 0; DpcCalls; DpcCalls--, i++)
313  {
314 #if DBG
315  /* Clear DPC Time */
316  Prcb->DebugDpcTime = 0;
317 #endif
318 
319  /* Call the DPC */
320  DpcEntry[i].Routine(DpcEntry[i].Dpc,
321  DpcEntry[i].Context,
322  UlongToPtr(SystemTime.LowPart),
323  UlongToPtr(SystemTime.HighPart));
324  }
325 
326  /* Lower IRQL if we need to */
327  if (OldIrql != DISPATCH_LEVEL) KeLowerIrql(OldIrql);
328  }
329  else
330  {
331  /* Unlock the dispatcher */
332  KiReleaseDispatcherLock(OldIrql);
333  }
334 }
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
#define MAXIMUM_PROCESSORS
Definition: rwlock.h:5
ULONG LowPart
Definition: ketypes.h:895
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
FORCEINLINE VOID KxUnwaitThreadForEvent(IN PKEVENT Event, IN KPRIORITY Increment)
Definition: ke_x.h:1295
void __cdecl _enable(void)
Definition: intrin_arm.h:373
FORCEINLINE PKSPIN_LOCK_QUEUE KiAcquireTimerLock(IN ULONG Hand)
Definition: ke_x.h:280
#define PtrToLong(p)
Definition: basetsd.h:83
BOOLEAN NTAPI KeInsertQueueDpc(IN PKDPC Dpc, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
Definition: dpc.c:724
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1054
_In_ LARGE_INTEGER _In_ ULONG Period
Definition: kefuncs.h:1268
$ULONG LowPart
Definition: ntbasedef.h:568
_Must_inspect_result_ _In_ ULONG Index
Definition: fltkernel.h:1824
VOID NTAPI KiCheckTimerTable(IN ULARGE_INTEGER CurrentTime)
Definition: dpc.c:33
ULONG Period
Definition: ketypes.h:832
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
ULONG DebugDpcTime
Definition: ketypes.h:516
static LIST_ENTRY Timers
Definition: clock.c:40
UCHAR KIRQL
Definition: env_spec_w32.h:591
GLenum GLclampf GLint i
Definition: glfuncs.h:14
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
#define FALSE
Definition: types.h:117
long LONG
Definition: pedump.c:60
DISPATCHER_HEADER Header
Definition: ketypes.h:825
#define MAX_TIMER_DPCS
Definition: ke.h:57
Definition: ke.h:59
PKDPC Dpc
Definition: ke.h:61
ULARGE_INTEGER Time
Definition: ketypes.h:667
DWORD Interval
Definition: netstat.c:30
UCHAR Type
Definition: ketypes.h:673
_In_opt_ PVOID _In_opt_ PVOID SystemArgument1
Definition: ketypes.h:660
struct _LIST_ENTRY * Flink
Definition: typedefs.h:120
struct _KDPC * Dpc
Definition: ketypes.h:828
#define UlongToPtr(ul)
Definition: basetsd.h:97
_In_ LARGE_INTEGER _In_opt_ PKDPC Dpc
Definition: kefuncs.h:524
#define TIMER_TABLE_SIZE
Definition: ketypes.h:821
LIST_ENTRY Entry
Definition: ketypes.h:666
$ULONG HighPart
Definition: ntbasedef.h:569
BOOLEAN FASTCALL KiInsertTreeTimer(IN PKTIMER Timer, IN LARGE_INTEGER Interval)
Definition: timerobj.c:26
ULARGE_INTEGER DueTime
Definition: ketypes.h:826
KTIMER_TABLE_ENTRY KiTimerTableListHead[TIMER_TABLE_SIZE]
Definition: timerobj.c:17
NTKERNELAPI volatile KSYSTEM_TIME KeTickCount
Definition: clock.c:19
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
Definition: ketypes.h:672
Definition: typedefs.h:118
UCHAR ThreadDpcEnable
Definition: ketypes.h:695
CCHAR KeNumberProcessors
Definition: krnlinit.c:35
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
UINT Timer
Definition: capclock.c:11
FORCEINLINE VOID KiReleaseDispatcherLock(IN KIRQL OldIrql)
Definition: ke_x.h:152
FORCEINLINE KIRQL KiAcquireDispatcherLock(VOID)
Definition: ke_x.h:144
PKDEFERRED_ROUTINE Routine
Definition: ke.h:62
PVOID Context
Definition: ke.h:63
FORCEINLINE VOID KiRemoveEntryTimer(IN PKTIMER Timer)
Definition: ke_x.h:884
USHORT Number
Definition: ketypes.h:559
void __cdecl _disable(void)
Definition: intrin_arm.h:365
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:565
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
LIST_ENTRY WaitListHead
Definition: ketypes.h:781
volatile USHORT Number
Definition: ketypes.h:675
FORCEINLINE VOID KxUnwaitThread(IN DISPATCHER_HEADER *Object, IN KPRIORITY Increment)
Definition: ke_x.h:1250
PKDEFERRED_ROUTINE DeferredRoutine
Definition: ketypes.h:677
PVOID DeferredContext
Definition: ketypes.h:678
_In_ LONG _In_ LONG Limit
Definition: kefuncs.h:328
ULONGLONG NTAPI KeQueryInterruptTime(VOID)
Definition: clock.c:203
static PLARGE_INTEGER Time
Definition: time.c:28
#define Int32x32To64(a, b)
FORCEINLINE VOID KiReleaseTimerLock(IN PKSPIN_LOCK_QUEUE LockQueue)
Definition: ke_x.h:291
LONGLONG QuadPart
Definition: typedefs.h:113
VOID FASTCALL KiTimerListExpire ( IN PLIST_ENTRY  ExpiredListHead,
IN KIRQL  OldIrql 
)

Definition at line 338 of file dpc.c.

Referenced by KeSetSystemTime().

340 {
341  ULARGE_INTEGER SystemTime;
343  LONG i;
344  ULONG DpcCalls = 0;
345  PKTIMER Timer;
346  PKDPC TimerDpc;
347  ULONG Period;
349  PKPRCB Prcb = KeGetCurrentPrcb();
350 
351  /* Query system */
352  KeQuerySystemTime((PLARGE_INTEGER)&SystemTime);
353 
354  /* Loop expired list */
355  while (ExpiredListHead->Flink != ExpiredListHead)
356  {
357  /* Get the current timer */
358  Timer = CONTAINING_RECORD(ExpiredListHead->Flink, KTIMER, TimerListEntry);
359 
360  /* Remove it */
362 
363  /* Not inserted */
364  Timer->Header.Inserted = FALSE;
365 
366  /* Signal it */
367  Timer->Header.SignalState = 1;
368 
369  /* Get the DPC and period */
370  TimerDpc = Timer->Dpc;
371  Period = Timer->Period;
372 
373  /* Check if there's any waiters */
374  if (!IsListEmpty(&Timer->Header.WaitListHead))
375  {
376  /* Check the type of event */
377  if (Timer->Header.Type == TimerNotificationObject)
378  {
379  /* Unwait the thread */
381  }
382  else
383  {
384  /* Otherwise unwait the thread and signal the timer */
386  }
387  }
388 
389  /* Check if we have a period */
390  if (Period)
391  {
392  /* Calculate the interval and insert the timer */
393  Interval.QuadPart = Int32x32To64(Period, -10000);
394  while (!KiInsertTreeTimer(Timer, Interval));
395  }
396 
397  /* Check if we have a DPC */
398  if (TimerDpc)
399  {
400 #ifdef CONFIG_SMP
401  /*
402  * If the DPC is targeted to another processor,
403  * then insert it into that processor's DPC queue
404  * instead of delivering it now.
405  * If the DPC is a threaded DPC, and the current CPU
406  * has threaded DPCs enabled (KiExecuteDpc is actively parsing DPCs),
407  * then also insert it into the DPC queue for threaded delivery,
408  * instead of doing it here.
409  */
410  if (((TimerDpc->Number >= MAXIMUM_PROCESSORS) &&
411  ((TimerDpc->Number - MAXIMUM_PROCESSORS) != Prcb->Number)) ||
412  ((TimerDpc->Type == ThreadedDpcObject) && (Prcb->ThreadDpcEnable)))
413  {
414  /* Queue it */
415  KeInsertQueueDpc(TimerDpc,
416  UlongToPtr(SystemTime.LowPart),
417  UlongToPtr(SystemTime.HighPart));
418  }
419  else
420 #endif
421  {
422  /* Setup the DPC Entry */
423  DpcEntry[DpcCalls].Dpc = TimerDpc;
424  DpcEntry[DpcCalls].Routine = TimerDpc->DeferredRoutine;
425  DpcEntry[DpcCalls].Context = TimerDpc->DeferredContext;
426  DpcCalls++;
427  ASSERT(DpcCalls < MAX_TIMER_DPCS);
428  }
429  }
430  }
431 
432  /* Check if we still have DPC entries */
433  if (DpcCalls)
434  {
435  /* Release the dispatcher while doing DPCs */
437 
438  /* Start looping all DPC Entries */
439  for (i = 0; DpcCalls; DpcCalls--, i++)
440  {
441 #if DBG
442  /* Clear DPC Time */
443  Prcb->DebugDpcTime = 0;
444 #endif
445 
446  /* Call the DPC */
447  DpcEntry[i].Routine(DpcEntry[i].Dpc,
448  DpcEntry[i].Context,
449  UlongToPtr(SystemTime.LowPart),
450  UlongToPtr(SystemTime.HighPart));
451  }
452 
453  /* Lower IRQL */
455  }
456  else
457  {
458  /* Unlock the dispatcher */
460  }
461 }
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
#define MAXIMUM_PROCESSORS
Definition: rwlock.h:5
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
FORCEINLINE VOID KxUnwaitThreadForEvent(IN PKEVENT Event, IN KPRIORITY Increment)
Definition: ke_x.h:1295
BOOLEAN NTAPI KeInsertQueueDpc(IN PKDPC Dpc, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
Definition: dpc.c:724
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1054
_In_ LARGE_INTEGER _In_ ULONG Period
Definition: kefuncs.h:1268
$ULONG LowPart
Definition: ntbasedef.h:568
LIST_ENTRY TimerListEntry
Definition: ketypes.h:827
ULONG Period
Definition: ketypes.h:832
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
ULONG DebugDpcTime
Definition: ketypes.h:516
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
GLenum GLclampf GLint i
Definition: glfuncs.h:14
#define FALSE
Definition: types.h:117
long LONG
Definition: pedump.c:60
DISPATCHER_HEADER Header
Definition: ketypes.h:825
#define MAX_TIMER_DPCS
Definition: ke.h:57
Definition: ke.h:59
PKDPC Dpc
Definition: ke.h:61
DWORD Interval
Definition: netstat.c:30
UCHAR Type
Definition: ketypes.h:673
struct _KDPC * Dpc
Definition: ketypes.h:828
#define UlongToPtr(ul)
Definition: basetsd.h:97
_In_ LARGE_INTEGER _In_opt_ PKDPC Dpc
Definition: kefuncs.h:524
$ULONG HighPart
Definition: ntbasedef.h:569
BOOLEAN FASTCALL KiInsertTreeTimer(IN PKTIMER Timer, IN LARGE_INTEGER Interval)
Definition: timerobj.c:26
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
Definition: ketypes.h:672
UCHAR ThreadDpcEnable
Definition: ketypes.h:695
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
UINT Timer
Definition: capclock.c:11
FORCEINLINE VOID KiReleaseDispatcherLock(IN KIRQL OldIrql)
Definition: ke_x.h:152
PKDEFERRED_ROUTINE Routine
Definition: ke.h:62
PVOID Context
Definition: ke.h:63
USHORT Number
Definition: ketypes.h:559
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:565
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
LIST_ENTRY WaitListHead
Definition: ketypes.h:781
volatile USHORT Number
Definition: ketypes.h:675
FORCEINLINE VOID KxUnwaitThread(IN DISPATCHER_HEADER *Object, IN KPRIORITY Increment)
Definition: ke_x.h:1250
PKDEFERRED_ROUTINE DeferredRoutine
Definition: ketypes.h:677
PVOID DeferredContext
Definition: ketypes.h:678
#define Int32x32To64(a, b)
LONGLONG QuadPart
Definition: typedefs.h:113

Variable Documentation

BOOLEAN KeThreadDpcEnable

Definition at line 23 of file dpc.c.

Referenced by KeInitSystem().

ULONG KiAdjustDpcThreshold = 20

Definition at line 21 of file dpc.c.

Referenced by KeUpdateRunTime(), KiInitializeKernel(), and KiInitSpinLocks().

ULONG KiDPCTimeout = 110

Definition at line 27 of file dpc.c.

Referenced by KeUpdateRunTime().

FAST_MUTEX KiGenericCallDpcMutex

Definition at line 24 of file dpc.c.

Referenced by KiInitializeKernel(), and KiInitSystem().

ULONG KiIdealDpcRate = 20

Definition at line 22 of file dpc.c.

Referenced by KeUpdateRunTime().

ULONG KiMaximumDpcQueueDepth = 4

Definition at line 19 of file dpc.c.

Referenced by KeUpdateRunTime(), KiInitializeKernel(), and KiInitSpinLocks().

ULONG KiMinimumDpcRate = 3

Definition at line 20 of file dpc.c.

Referenced by KiInitializeKernel(), and KiInitSpinLocks().

ULONG KiTimeLimitIsrMicroseconds

Definition at line 26 of file dpc.c.

Referenced by KiInitMachineDependent().

KDPC KiTimerExpireDpc

Definition at line 25 of file dpc.c.

Referenced by KiInitializeKernel(), and KiInitSystem().