ReactOS  0.4.15-dev-3294-ge98684e
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)
 
 _Requires_lock_not_held_ (Prcb->PrcbLock) 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

◆ NDEBUG

#define NDEBUG

Definition at line 14 of file dpc.c.

Function Documentation

◆ _Requires_lock_not_held_()

_Requires_lock_not_held_ ( Prcb->  PrcbLock)

Definition at line 463 of file dpc.c.

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

◆ KeFlushQueuedDpcs()

VOID NTAPI KeFlushQueuedDpcs ( VOID  )

Definition at line 919 of file dpc.c.

920 {
921  PKPRCB CurrentPrcb = KeGetCurrentPrcb();
922  PAGED_CODE();
923 
924  /* Check if this is an UP machine */
925  if (KeActiveProcessors == 1)
926  {
927  /* Check if there are DPCs on either queues */
928  if ((CurrentPrcb->DpcData[DPC_NORMAL].DpcQueueDepth > 0) ||
929  (CurrentPrcb->DpcData[DPC_THREADED].DpcQueueDepth > 0))
930  {
931  /* Request an interrupt */
933  }
934  }
935  else
936  {
937  /* FIXME: SMP support required */
938  ASSERT(FALSE);
939  }
940 }
#define DPC_NORMAL
KDPC_DATA DpcData[2]
Definition: ketypes.h:680
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1079
#define FALSE
Definition: types.h:117
#define ASSERT(a)
Definition: mode.c:44
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:788
#define DPC_THREADED
#define PAGED_CODE()

Referenced by FxDpc::Cancel(), DeviceEvtSelfManagedIoCleanup(), FxUsbDevice::Dispose(), ExpDeleteTimer(), FxDpc::FlushAndRundown(), FxInterrupt::FlushQueuedDpcs(), InPortRemoveDevice(), MmPageEntireDriver(), and Mx::MxFlushQueuedDpcs().

◆ KeGenericCallDpc()

VOID NTAPI KeGenericCallDpc ( IN PKDEFERRED_ROUTINE  Routine,
IN PVOID  Context 
)

Definition at line 984 of file dpc.c.

986 {
987  ULONG Barrier = KeNumberProcessors;
988  KIRQL OldIrql;
989  DEFERRED_REVERSE_BARRIER ReverseBarrier;
991 
992  //
993  // The barrier is the number of processors, each processor will decrement it
994  // by one, so when all processors have run the DPC, the barrier reaches zero
995  //
996  ReverseBarrier.Barrier = Barrier;
997  ReverseBarrier.TotalProcessors = Barrier;
998 
999  //
1000  // But we don't need the barrier on UP, since we can simply call the routine
1001  // directly while at DISPATCH_LEVEL and not worry about anything else
1002  //
1004  Routine(&KeGetCurrentPrcb()->CallDpc, Context, &Barrier, &ReverseBarrier);
1006 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1079
UCHAR KIRQL
Definition: env_spec_w32.h:591
KIRQL OldIrql
Definition: mm.h:1502
#define ASSERT(a)
Definition: mode.c:44
ULONG TotalProcessors
Definition: ke.h:54
CCHAR KeNumberProcessors
Definition: krnlinit.c:35
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
VOID NTAPI KeRaiseIrql(KIRQL NewIrql, PKIRQL OldIrql)
Definition: spinlock.c:27
unsigned int ULONG
Definition: retypes.h:1
VOID NTAPI KeLowerIrql(KIRQL NewIrql)
Definition: spinlock.c:39

Referenced by ExGetPoolTagInfo().

◆ KeInitializeDpc()

VOID NTAPI KeInitializeDpc ( IN PKDPC  Dpc,
IN PKDEFERRED_ROUTINE  DeferredRoutine,
IN PVOID  DeferredContext 
)

Definition at line 712 of file dpc.c.

715 {
716  /* Call the internal routine */
717  KiInitializeDpc(Dpc, DeferredRoutine, DeferredContext, DpcObject);
718 }
_Must_inspect_result_ _In_ PWDF_DPC_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFDPC * Dpc
Definition: wdfdpc.h:107
VOID NTAPI KiInitializeDpc(IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DeferredRoutine, IN PVOID DeferredContext, IN KOBJECTS Type)
Definition: dpc.c:678
_In_opt_ PVOID DeferredContext
Definition: ketypes.h:675

Referenced by _Requires_lock_held_(), acpi_bus_init(), AddControllers(), AfdSelect(), CcInitializeCacheManager(), ClasspInitializeIdleTimer(), ClasspInitializeTimer(), ClassPnpStartDevice(), CmpCmdInit(), CmpInitDelayDerefKCBEngine(), CmpInitializeDelayedCloseTable(), FxUsbPipeContinuousReader::Config(), CServiceGroup::CServiceGroup(), CTEInitTimer(), DispEchoRequest(), DriverEntry(), Ext2StartFloppyFlushDpc(), FreeBT_AddDevice(), FxInterrupt::FxInterrupt(), FxIoQueue::FxIoQueue(), i8042KbdInternalDeviceControl(), i8042MouInternalDeviceControl(), InitController(), MxTimer::Initialize(), FxDpc::Initialize(), InitializeDeviceData(), InitPiceRunningTimer(), IntVideoPortCreateAdapterDeviceObject(), IoInitializeDpcRequest(), IoInitSystem(), IopRestartLogWorker(), KdInitSystem(), KeBalanceSetManager(), KeyboardDeviceWorker(), KiInitializeKernel(), KiInitSpinLocks(), KiInitSystem(), KsCreateBusEnumObject(), MsfsRead(), NdisIAddDevice(), NdisInitializeTimer(), NdisMInitializeTimer(), NdisMRegisterInterrupt(), NpAddWaiter(), NtCreateTimer(), PoInitializePrcb(), RxInitializeRxTimer(), ScratchBuffer_ReadWriteCompletionRoutine(), ScsiPortInitialize(), SerialAddDeviceInternal(), START_TEST(), StorPortNotification(), StreamClassAddDevice(), TCPAllocateConnectionEndpoint(), TransferPacketQueueRetryDpc(), USBH_SyncSubmitUrb(), USBPORT_RequestAsyncCallback(), USBPORT_SoftInterrupt(), USBPORT_StartDevice(), and USBPORT_StartTimer().

◆ KeInitializeThreadedDpc()

VOID NTAPI KeInitializeThreadedDpc ( IN PKDPC  Dpc,
IN PKDEFERRED_ROUTINE  DeferredRoutine,
IN PVOID  DeferredContext 
)

Definition at line 699 of file dpc.c.

702 {
703  /* Call the internal routine */
705 }
_Must_inspect_result_ _In_ PWDF_DPC_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFDPC * Dpc
Definition: wdfdpc.h:107
VOID NTAPI KiInitializeDpc(IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DeferredRoutine, IN PVOID DeferredContext, IN KOBJECTS Type)
Definition: dpc.c:678
_In_opt_ PVOID DeferredContext
Definition: ketypes.h:675

Referenced by IoInitializeThreadedDpcRequest().

◆ KeInsertQueueDpc()

BOOLEAN NTAPI KeInsertQueueDpc ( IN PKDPC  Dpc,
IN PVOID  SystemArgument1,
IN PVOID  SystemArgument2 
)

Definition at line 725 of file dpc.c.

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

Referenced by acpi_bus_generate_event(), i8042KbdInterruptService(), i8042KbdQueuePacket(), i8042MouInterruptService(), i8042MouQueuePacket(), IoRequestDpc(), Isr(), KdExitDebugger(), KeyboardDeviceWorker(), KiSignalTimer(), KiTimerExpiration(), KiTimerListExpire(), KsGenerateEvent(), Mx::MxInsertQueueDpc(), FxInterrupt::QueueDpcForIsr(), SerialInterruptService(), ServiceRoutine(), START_TEST(), StreamClassInterruptRoutine(), TransferPacketQueueRetryDpc(), USBPORT_HcQueueWakeDpc(), USBPORT_InterruptService(), USBPORT_InvalidateEndpointHandler(), USBPORT_IsrDpcHandler(), USBPORT_QueueDoneTransfer(), USBPORT_SoftInterruptDpc(), and VideoPortQueueDpc().

◆ KeIsExecutingDpc()

◆ KeRemoveQueueDpc()

BOOLEAN NTAPI KeRemoveQueueDpc ( IN PKDPC  Dpc)

Definition at line 878 of file dpc.c.

879 {
880  PKDPC_DATA DpcData;
881  BOOLEAN Enable;
882  ASSERT_DPC(Dpc);
883 
884  /* Disable interrupts */
886 
887  /* Get DPC data */
888  DpcData = Dpc->DpcData;
889  if (DpcData)
890  {
891  /* Acquire the DPC lock */
892  KiAcquireSpinLock(&DpcData->DpcLock);
893 
894  /* Make sure that the data didn't change */
895  if (DpcData == Dpc->DpcData)
896  {
897  /* Remove the DPC */
898  DpcData->DpcQueueDepth--;
899  RemoveEntryList(&Dpc->DpcListEntry);
900  Dpc->DpcData = NULL;
901  }
902 
903  /* Release the lock */
904  KiReleaseSpinLock(&DpcData->DpcLock);
905  }
906 
907  /* Re-enable interrupts */
908  if (Enable) _enable();
909 
910  /* Return if the DPC was in the queue or not */
911  return DpcData ? TRUE : FALSE;
912 }
_Must_inspect_result_ _In_ PWDF_DPC_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFDPC * Dpc
Definition: wdfdpc.h:107
#define TRUE
Definition: types.h:120
void __cdecl _enable(void)
Definition: intrin_arm.h:373
_In_ ULONGLONG _In_ ULONGLONG _In_ BOOLEAN Enable
Definition: ntddpcm.h:140
#define ASSERT_DPC(Object)
ULONG_PTR DpcLock
Definition: ketypes.h:784
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
#define FALSE
Definition: types.h:117
unsigned char BOOLEAN
FORCEINLINE BOOLEAN KeDisableInterrupts(VOID)
Definition: ke.h:235
volatile ULONG DpcQueueDepth
Definition: ketypes.h:788
VOID FASTCALL KiReleaseSpinLock(IN PKSPIN_LOCK SpinLock)
Definition: spinlock.c:298
#define NULL
Definition: types.h:112
VOID FASTCALL KiAcquireSpinLock(IN PKSPIN_LOCK SpinLock)
Definition: spinlock.c:287

Referenced by _Requires_lock_held_(), FxDpc::Cancel(), ExTimerRundown(), FatDeleteVcb(), NtCancelTimer(), NtSetTimer(), and START_TEST().

◆ KeSetImportanceDpc()

VOID NTAPI KeSetImportanceDpc ( IN PKDPC  Dpc,
IN KDPC_IMPORTANCE  Importance 
)

Definition at line 958 of file dpc.c.

960 {
961  /* Set the DPC Importance */
962  ASSERT_DPC(Dpc);
963  Dpc->Importance = Importance;
964 }
_Must_inspect_result_ _In_ PWDF_DPC_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFDPC * Dpc
Definition: wdfdpc.h:107
#define ASSERT_DPC(Object)
_In_ KDPC_IMPORTANCE Importance
Definition: kefuncs.h:80

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

◆ KeSetTargetProcessorDpc()

VOID NTAPI KeSetTargetProcessorDpc ( IN PKDPC  Dpc,
IN CCHAR  Number 
)

Definition at line 971 of file dpc.c.

973 {
974  /* Set a target CPU */
975  ASSERT_DPC(Dpc);
976  Dpc->Number = Number + MAXIMUM_PROCESSORS;
977 }
#define MAXIMUM_PROCESSORS
Definition: rwlock.h:5
_Must_inspect_result_ _In_ PWDF_DPC_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFDPC * Dpc
Definition: wdfdpc.h:107
#define ASSERT_DPC(Object)
_In_opt_ PENTER_STATE_SYSTEM_HANDLER _In_opt_ PVOID _In_ LONG _In_opt_ LONG volatile * Number
Definition: ntpoapi.h:204

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

◆ KeSignalCallDpcDone()

VOID NTAPI KeSignalCallDpcDone ( IN PVOID  SystemArgument1)

Definition at line 1013 of file dpc.c.

1014 {
1015  //
1016  // Decrement the barrier, which is actually the processor count
1017  //
1019 }
_In_opt_ PVOID _In_opt_ PVOID SystemArgument1
Definition: ketypes.h:675
#define InterlockedDecrement
Definition: armddk.h:52
signed int * PLONG
Definition: retypes.h:5

Referenced by ExpGetPoolTagInfoTarget().

◆ KeSignalCallDpcSynchronize()

BOOLEAN NTAPI KeSignalCallDpcSynchronize ( IN PVOID  SystemArgument2)

Definition at line 1026 of file dpc.c.

1027 {
1028  //
1029  // There is nothing to do on UP systems -- the processor calling this wins
1030  //
1032  return TRUE;
1033 }
#define TRUE
Definition: types.h:120
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
_In_opt_ PVOID _In_opt_ PVOID _In_opt_ PVOID SystemArgument2
Definition: ketypes.h:675

Referenced by ExpGetPoolTagInfoTarget().

◆ KiCheckTimerTable()

VOID NTAPI KiCheckTimerTable ( IN ULARGE_INTEGER  CurrentTime)

Definition at line 33 of file dpc.c.

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 */
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 */
74 #endif
75 }
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1079
UCHAR KIRQL
Definition: env_spec_w32.h:591
VOID NTAPI DbgBreakPoint(VOID)
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
KIRQL OldIrql
Definition: mm.h:1502
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
KDPC KiTimerExpireDpc
Definition: dpc.c:25
#define TIMER_TABLE_SIZE
Definition: ketypes.h:836
LIST_ENTRY Entry
Definition: ketypes.h:708
KTIMER_TABLE_ENTRY KiTimerTableListHead[TIMER_TABLE_SIZE]
Definition: timerobj.c:17
Definition: typedefs.h:119
_Must_inspect_result_ _In_ PWDF_TIMER_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFTIMER * Timer
Definition: wdftimer.h:153
#define HIGH_LEVEL
Definition: env_spec_w32.h:703
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
unsigned int * PULONG
Definition: retypes.h:1
VOID NTAPI KeRaiseIrql(KIRQL NewIrql, PKIRQL OldIrql)
Definition: spinlock.c:27
#define DPRINT1
Definition: precomp.h:8
unsigned int ULONG
Definition: retypes.h:1
VOID NTAPI KeLowerIrql(KIRQL NewIrql)
Definition: spinlock.c:39
volatile PVOID DpcData
Definition: ketypes.h:696

Referenced by KiTimerExpiration().

◆ KiInitializeDpc()

VOID NTAPI KiInitializeDpc ( IN PKDPC  Dpc,
IN PKDEFERRED_ROUTINE  DeferredRoutine,
IN PVOID  DeferredContext,
IN KOBJECTS  Type 
)

Definition at line 678 of file dpc.c.

682 {
683  /* Setup the DPC Object */
684  Dpc->Type = Type;
685  Dpc->Number = 0;
686  Dpc->Importance= MediumImportance;
687  Dpc->DeferredRoutine = DeferredRoutine;
688  Dpc->DeferredContext = DeferredContext;
689  Dpc->DpcData = NULL;
690 }
_Must_inspect_result_ _In_ PWDF_DPC_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFDPC * Dpc
Definition: wdfdpc.h:107
Type
Definition: Type.h:6
#define NULL
Definition: types.h:112
_In_opt_ PVOID DeferredContext
Definition: ketypes.h:675

Referenced by KeInitializeDpc(), and KeInitializeThreadedDpc().

◆ KiRetireDpcList()

VOID FASTCALL KiRetireDpcList ( IN PKPRCB  Prcb)

Definition at line 562 of file dpc.c.

563 {
564  PKDPC_DATA DpcData;
565  PLIST_ENTRY ListHead, DpcEntry;
566  PKDPC Dpc;
567  PKDEFERRED_ROUTINE DeferredRoutine;
569  ULONG_PTR TimerHand;
570 #ifdef CONFIG_SMP
571  KIRQL OldIrql;
572 #endif
573 
574  /* Get data and list variables before starting anything else */
575  DpcData = &Prcb->DpcData[DPC_NORMAL];
576  ListHead = &DpcData->DpcListHead;
577 
578  /* Main outer loop */
579  do
580  {
581  /* Set us as active */
582  Prcb->DpcRoutineActive = TRUE;
583 
584  /* Check if this is a timer expiration request */
585  if (Prcb->TimerRequest)
586  {
587  /* It is, get the timer hand and disable timer request */
588  TimerHand = Prcb->TimerHand;
589  Prcb->TimerRequest = 0;
590 
591  /* Expire timers with interrups enabled */
592  _enable();
593  KiTimerExpiration(NULL, NULL, (PVOID)TimerHand, NULL);
594  _disable();
595  }
596 
597  /* Loop while we have entries in the queue */
598  while (DpcData->DpcQueueDepth != 0)
599  {
600  /* Lock the DPC data and get the DPC entry*/
602  DpcEntry = ListHead->Flink;
603 
604  /* Make sure we have an entry */
605  if (DpcEntry != ListHead)
606  {
607  /* Remove the DPC from the list */
608  RemoveEntryList(DpcEntry);
609  Dpc = CONTAINING_RECORD(DpcEntry, KDPC, DpcListEntry);
610 
611  /* Clear its DPC data and save its parameters */
612  Dpc->DpcData = NULL;
613  DeferredRoutine = Dpc->DeferredRoutine;
614  DeferredContext = Dpc->DeferredContext;
615  SystemArgument1 = Dpc->SystemArgument1;
616  SystemArgument2 = Dpc->SystemArgument2;
617 
618  /* Decrease the queue depth */
619  DpcData->DpcQueueDepth--;
620 
621 #if DBG
622  /* Clear DPC Time */
623  Prcb->DebugDpcTime = 0;
624 #endif
625 
626  /* Release the lock */
628 
629  /* Re-enable interrupts */
630  _enable();
631 
632  /* Call the DPC */
633  DeferredRoutine(Dpc,
638 
639  /* Disable interrupts and keep looping */
640  _disable();
641  }
642  else
643  {
644  /* The queue should be flushed now */
645  ASSERT(DpcData->DpcQueueDepth == 0);
646 
647  /* Release DPC Lock */
649  }
650  }
651 
652  /* Clear DPC Flags */
653  Prcb->DpcRoutineActive = FALSE;
654  Prcb->DpcInterruptRequested = FALSE;
655 
656 #ifdef CONFIG_SMP
657  /* Check if we have deferred threads */
658  if (Prcb->DeferredReadyListHead.Next)
659  {
660 
661  /* Re-enable interrupts and raise to synch */
662  _enable();
664 
665  /* Process deferred threads */
667 
668  /* Lower IRQL back and disable interrupts */
670  _disable();
671  }
672 #endif
673  } while (DpcData->DpcQueueDepth != 0);
674 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
_Must_inspect_result_ _In_ PWDF_DPC_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFDPC * Dpc
Definition: wdfdpc.h:107
VOID NTAPI KiTimerExpiration(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
Definition: dpc.c:79
#define DPC_NORMAL
#define TRUE
Definition: types.h:120
void __cdecl _enable(void)
Definition: intrin_arm.h:373
VOID NTAPI KeAcquireSpinLockAtDpcLevel(IN PKSPIN_LOCK SpinLock)
Definition: spinlock.c:198
ULONG_PTR DpcLock
Definition: ketypes.h:784
uint32_t ULONG_PTR
Definition: typedefs.h:65
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
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
KIRQL OldIrql
Definition: mm.h:1502
_In_opt_ PVOID _In_opt_ PVOID SystemArgument1
Definition: ketypes.h:675
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define ASSERT(a)
Definition: mode.c:44
VOID NTAPI KeReleaseSpinLockFromDpcLevel(IN PKSPIN_LOCK SpinLock)
Definition: spinlock.c:221
Definition: ketypes.h:687
KDEFERRED_ROUTINE * PKDEFERRED_ROUTINE
Definition: ketypes.h:678
Definition: typedefs.h:119
_In_opt_ PVOID _In_opt_ PVOID _In_opt_ PVOID SystemArgument2
Definition: ketypes.h:675
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
volatile ULONG DpcQueueDepth
Definition: ketypes.h:788
#define NULL
Definition: types.h:112
void __cdecl _disable(void)
Definition: intrin_arm.h:365
VOID NTAPI KeLowerIrql(KIRQL NewIrql)
Definition: spinlock.c:39
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:675

Referenced by KiDispatchInterrupt(), and KiIdleLoop().

◆ KiTimerExpiration()

VOID NTAPI KiTimerExpiration ( IN PKDPC  Dpc,
IN PVOID  DeferredContext,
IN PVOID  SystemArgument1,
IN PVOID  SystemArgument2 
)

Definition at line 79 of file dpc.c.

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();
104 
105  /* Bring interrupts back */
106  _enable();
107 
108  /* Get the index of the timer and normalize it */
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 */
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--;
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 */
328  }
329  else
330  {
331  /* Unlock the dispatcher */
333  }
334 }
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
#define MAXIMUM_PROCESSORS
Definition: rwlock.h:5
ULONG LowPart
Definition: ketypes.h:917
_Must_inspect_result_ _In_ PWDF_DPC_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFDPC * Dpc
Definition: wdfdpc.h:107
FORCEINLINE VOID KxUnwaitThreadForEvent(IN PKEVENT Event, IN KPRIORITY Increment)
Definition: ke_x.h:1304
void __cdecl _enable(void)
Definition: intrin_arm.h:373
FORCEINLINE PKSPIN_LOCK_QUEUE KiAcquireTimerLock(IN ULONG Hand)
Definition: ke_x.h:286
#define PtrToLong(p)
Definition: basetsd.h:84
BOOLEAN NTAPI KeInsertQueueDpc(IN PKDPC Dpc, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
Definition: dpc.c:725
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1079
_In_ LARGE_INTEGER _In_ ULONG Period
Definition: kefuncs.h:1324
$ULONG LowPart
Definition: ntbasedef.h:569
VOID NTAPI KiCheckTimerTable(IN ULARGE_INTEGER CurrentTime)
Definition: dpc.c:33
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
ULONG DebugDpcTime
Definition: ketypes.h:518
static LIST_ENTRY Timers
Definition: clock.c:40
UCHAR KIRQL
Definition: env_spec_w32.h:591
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
#define FALSE
Definition: types.h:117
long LONG
Definition: pedump.c:60
#define MAX_TIMER_DPCS
Definition: ke.h:69
Definition: ke.h:71
PKDPC Dpc
Definition: ke.h:73
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define UlongToPtr(u)
Definition: config.h:106
ULARGE_INTEGER Time
Definition: ketypes.h:709
KIRQL OldIrql
Definition: mm.h:1502
DWORD Interval
Definition: netstat.c:33
UCHAR Type
Definition: ketypes.h:688
_In_opt_ PVOID _In_opt_ PVOID SystemArgument1
Definition: ketypes.h:675
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define TIMER_TABLE_SIZE
Definition: ketypes.h:836
LIST_ENTRY Entry
Definition: ketypes.h:708
$ULONG HighPart
Definition: ntbasedef.h:570
#define ASSERT(a)
Definition: mode.c:44
_In_ WDFCOLLECTION _In_ ULONG Index
BOOLEAN FASTCALL KiInsertTreeTimer(IN PKTIMER Timer, IN LARGE_INTEGER Interval)
Definition: timerobj.c:26
KTIMER_TABLE_ENTRY KiTimerTableListHead[TIMER_TABLE_SIZE]
Definition: timerobj.c:17
NTKERNELAPI volatile KSYSTEM_TIME KeTickCount
Definition: clock.c:19
Definition: ketypes.h:687
Definition: typedefs.h:119
UCHAR ThreadDpcEnable
Definition: ketypes.h:699
_Must_inspect_result_ _In_ PWDF_TIMER_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFTIMER * Timer
Definition: wdftimer.h:153
CCHAR KeNumberProcessors
Definition: krnlinit.c:35
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
FORCEINLINE VOID KiReleaseDispatcherLock(IN KIRQL OldIrql)
Definition: ke_x.h:157
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
FORCEINLINE KIRQL KiAcquireDispatcherLock(VOID)
Definition: ke_x.h:149
PKDEFERRED_ROUTINE Routine
Definition: ke.h:74
PVOID Context
Definition: ke.h:75
FORCEINLINE VOID KiRemoveEntryTimer(IN PKTIMER Timer)
Definition: ke_x.h:892
USHORT Number
Definition: ketypes.h:563
void __cdecl _disable(void)
Definition: intrin_arm.h:365
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:598
volatile USHORT Number
Definition: ketypes.h:690
FORCEINLINE VOID KxUnwaitThread(IN DISPATCHER_HEADER *Object, IN KPRIORITY Increment)
Definition: ke_x.h:1259
VOID NTAPI KeLowerIrql(KIRQL NewIrql)
Definition: spinlock.c:39
PKDEFERRED_ROUTINE DeferredRoutine
Definition: ketypes.h:692
PVOID DeferredContext
Definition: ketypes.h:693
_In_ LONG _In_ LONG Limit
Definition: kefuncs.h:315
ULONGLONG NTAPI KeQueryInterruptTime(VOID)
Definition: clock.c:203
static PLARGE_INTEGER Time
Definition: time.c:105
#define Int32x32To64(a, b)
FORCEINLINE VOID KiReleaseTimerLock(IN PKSPIN_LOCK_QUEUE LockQueue)
Definition: ke_x.h:297
LONGLONG QuadPart
Definition: typedefs.h:114

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

◆ KiTimerListExpire()

VOID FASTCALL KiTimerListExpire ( IN PLIST_ENTRY  ExpiredListHead,
IN KIRQL  OldIrql 
)

Definition at line 338 of file dpc.c.

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 */
361  RemoveEntryList(&Timer->TimerListEntry);
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
_Must_inspect_result_ _In_ PWDF_DPC_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFDPC * Dpc
Definition: wdfdpc.h:107
FORCEINLINE VOID KxUnwaitThreadForEvent(IN PKEVENT Event, IN KPRIORITY Increment)
Definition: ke_x.h:1304
BOOLEAN NTAPI KeInsertQueueDpc(IN PKDPC Dpc, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
Definition: dpc.c:725
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1079
_In_ LARGE_INTEGER _In_ ULONG Period
Definition: kefuncs.h:1324
$ULONG LowPart
Definition: ntbasedef.h:569
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
ULONG DebugDpcTime
Definition: ketypes.h:518
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
#define FALSE
Definition: types.h:117
long LONG
Definition: pedump.c:60
#define MAX_TIMER_DPCS
Definition: ke.h:69
Definition: ke.h:71
PKDPC Dpc
Definition: ke.h:73
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define UlongToPtr(u)
Definition: config.h:106
KIRQL OldIrql
Definition: mm.h:1502
DWORD Interval
Definition: netstat.c:33
UCHAR Type
Definition: ketypes.h:688
$ULONG HighPart
Definition: ntbasedef.h:570
#define ASSERT(a)
Definition: mode.c:44
BOOLEAN FASTCALL KiInsertTreeTimer(IN PKTIMER Timer, IN LARGE_INTEGER Interval)
Definition: timerobj.c:26
Definition: ketypes.h:687
UCHAR ThreadDpcEnable
Definition: ketypes.h:699
_Must_inspect_result_ _In_ PWDF_TIMER_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFTIMER * Timer
Definition: wdftimer.h:153
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
FORCEINLINE VOID KiReleaseDispatcherLock(IN KIRQL OldIrql)
Definition: ke_x.h:157
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
PKDEFERRED_ROUTINE Routine
Definition: ke.h:74
PVOID Context
Definition: ke.h:75
USHORT Number
Definition: ketypes.h:563
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:598
volatile USHORT Number
Definition: ketypes.h:690
FORCEINLINE VOID KxUnwaitThread(IN DISPATCHER_HEADER *Object, IN KPRIORITY Increment)
Definition: ke_x.h:1259
VOID NTAPI KeLowerIrql(KIRQL NewIrql)
Definition: spinlock.c:39
PKDEFERRED_ROUTINE DeferredRoutine
Definition: ketypes.h:692
PVOID DeferredContext
Definition: ketypes.h:693
#define Int32x32To64(a, b)

Referenced by KeSetSystemTime().

Variable Documentation

◆ KeThreadDpcEnable

BOOLEAN KeThreadDpcEnable

Definition at line 23 of file dpc.c.

Referenced by KeInitSystem().

◆ KiAdjustDpcThreshold

ULONG KiAdjustDpcThreshold = 20

Definition at line 21 of file dpc.c.

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

◆ KiDPCTimeout

ULONG KiDPCTimeout = 110

Definition at line 27 of file dpc.c.

Referenced by KeUpdateRunTime().

◆ KiGenericCallDpcMutex

FAST_MUTEX KiGenericCallDpcMutex

Definition at line 24 of file dpc.c.

Referenced by KiInitializeKernel(), and KiInitSystem().

◆ KiIdealDpcRate

ULONG KiIdealDpcRate = 20

Definition at line 22 of file dpc.c.

Referenced by KeUpdateRunTime(), and QSI_DEF().

◆ KiMaximumDpcQueueDepth

ULONG KiMaximumDpcQueueDepth = 4

Definition at line 19 of file dpc.c.

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

◆ KiMinimumDpcRate

ULONG KiMinimumDpcRate = 3

Definition at line 20 of file dpc.c.

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

◆ KiTimeLimitIsrMicroseconds

ULONG KiTimeLimitIsrMicroseconds

Definition at line 26 of file dpc.c.

Referenced by KiInitMachineDependent().

◆ KiTimerExpireDpc

KDPC KiTimerExpireDpc

Definition at line 25 of file dpc.c.

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