ReactOS 0.4.16-dev-340-g0540c21
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)
 
 _IRQL_requires_max_ (APC_LEVEL)
 
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

◆ _IRQL_requires_max_()

_IRQL_requires_max_ ( APC_LEVEL  )

Definition at line 917 of file dpc.c.

921{
922 ULONG ProcessorIndex;
923 PKPRCB TargetPrcb;
924
925 PAGED_CODE();
926 ASSERT(KeGetCurrentThread()->SystemAffinityActive == FALSE);
927
928 /* Loop all processors */
929 for (ProcessorIndex = 0; ProcessorIndex < KeNumberProcessors; ProcessorIndex++)
930 {
931 /* Get the target processor's PRCB */
932 TargetPrcb = KiProcessorBlock[ProcessorIndex];
933
934 /* Check if there are DPCs on either queues */
935 if ((TargetPrcb->DpcData[DPC_NORMAL].DpcQueueDepth > 0) ||
936 (TargetPrcb->DpcData[DPC_THREADED].DpcQueueDepth > 0))
937 {
938 /* Check if this is the current processor */
939 if (TargetPrcb == KeGetCurrentPrcb())
940 {
941 /* Request a DPC interrupt */
943 }
944 else
945 {
946 /* Attach to the target processor. This will cause a DPC
947 interrupt on the target processor and flush all DPCs. */
949 }
950 }
951 }
952
953 /* Revert back to user affinity */
954 if (KeGetCurrentThread()->SystemAffinityActive)
955 {
957 }
958}
#define PAGED_CODE()
#define FALSE
Definition: types.h:117
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
VOID FASTCALL HalRequestSoftwareInterrupt(IN KIRQL Irql)
Definition: pic.c:271
#define KeGetCurrentThread
Definition: hal.h:55
CCHAR KeNumberProcessors
Definition: krnlinit.c:35
#define ASSERT(a)
Definition: mode.c:44
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1150
PKPRCB KiProcessorBlock[]
Definition: krnlinit.c:32
volatile ULONG DpcQueueDepth
Definition: ketypes.h:858
KDPC_DATA DpcData[2]
Definition: ketypes.h:749
UINT64 SetMember
Definition: ketypes.h:651
VOID NTAPI KeSetSystemAffinityThread(IN KAFFINITY Affinity)
Definition: thrdobj.c:1107
VOID NTAPI KeRevertToUserAffinityThread(VOID)
Definition: thrdobj.c:1021
uint32_t ULONG
Definition: typedefs.h:59
#define DPC_NORMAL
#define DPC_THREADED

◆ _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}
#define InterlockedExchange
Definition: armddk.h:54
#define NULL
Definition: types.h:112
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
KIRQL NTAPI KeRaiseIrqlToSynchLevel(VOID)
Definition: pic.c:156
#define LOW_REALTIME_PRIORITY
FORCEINLINE PKTHREAD KiSelectReadyThread(IN KPRIORITY Priority, IN PKPRCB Prcb)
Definition: ke_x.h:1422
FORCEINLINE VOID KiSetThreadSwapBusy(IN PKTHREAD Thread)
Definition: ke_x.h:210
FORCEINLINE VOID KiReleasePrcbLock(IN PKPRCB Prcb)
Definition: ke_x.h:230
FORCEINLINE VOID KiAcquireThreadLock(IN PKTHREAD Thread)
Definition: ke_x.h:240
FORCEINLINE VOID KiReleaseThreadLock(IN PKTHREAD Thread)
Definition: ke_x.h:250
FORCEINLINE VOID KiAcquirePrcbLock(IN PKPRCB Prcb)
Definition: ke_x.h:220
FORCEINLINE SCHAR KiComputeNewPriority(IN PKTHREAD Thread, IN SCHAR Adjustment)
Definition: ke_x.h:1472
@ Running
Definition: ketypes.h:390
@ Standby
Definition: ketypes.h:391
#define MAX_QUANTUM
Definition: ketypes.h:136
BOOLEAN FASTCALL KiSwapContext(IN KIRQL WaitIrql, IN PKTHREAD CurrentThread)
struct _KTHREAD * CurrentThread
Definition: ketypes.h:639
struct _KTHREAD * NextThread
Definition: ketypes.h:640
LONG DpcSetEventRequest
Definition: ketypes.h:772
KEVENT DpcEvent
Definition: ketypes.h:779
volatile UCHAR State
Definition: ketypes.h:1789
@ WrQuantumEnd
Definition: ketypes.h:445

◆ KeGenericCallDpc()

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

Definition at line 1002 of file dpc.c.

1004{
1005 ULONG Barrier = KeNumberProcessors;
1006 KIRQL OldIrql;
1007 DEFERRED_REVERSE_BARRIER ReverseBarrier;
1009
1010 //
1011 // The barrier is the number of processors, each processor will decrement it
1012 // by one, so when all processors have run the DPC, the barrier reaches zero
1013 //
1014 ReverseBarrier.Barrier = Barrier;
1015 ReverseBarrier.TotalProcessors = Barrier;
1016
1017 //
1018 // But we don't need the barrier on UP, since we can simply call the routine
1019 // directly while at DISPATCH_LEVEL and not worry about anything else
1020 //
1022 Routine(&KeGetCurrentPrcb()->CallDpc, Context, &Barrier, &ReverseBarrier);
1024}
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
ULONG TotalProcessors
Definition: ke.h:54
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778

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}
VOID NTAPI KiInitializeDpc(IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DeferredRoutine, IN PVOID DeferredContext, IN KOBJECTS Type)
Definition: dpc.c:678
@ DpcObject
Definition: ketypes.h:425
_Must_inspect_result_ _In_ PWDF_DPC_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFDPC * Dpc
Definition: wdfdpc.h:112
_In_opt_ PVOID DeferredContext
Definition: ketypes.h:687

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(), FxDpc::Initialize(), MxTimer::Initialize(), InitializeDeviceData(), 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}
@ ThreadedDpcObject
Definition: ketypes.h:430

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{
730 PKPRCB Prcb, CurrentPrcb;
731 ULONG Cpu;
732 PKDPC_DATA DpcData;
733 BOOLEAN DpcConfigured = FALSE, DpcInserted = FALSE;
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 */
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 */
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}
unsigned char BOOLEAN
#define TRUE
Definition: types.h:120
#define InsertTailList(ListHead, Entry)
#define InsertHeadList(ListHead, Entry)
#define HIGH_LEVEL
Definition: env_spec_w32.h:703
#define MAXIMUM_PROCESSORS
Definition: rwlock.h:5
#define InterlockedCompareExchangePointer
Definition: interlocked.h:129
#define IPI_DPC
Definition: ketypes.h:287
FORCEINLINE KAFFINITY AFFINITY_MASK(ULONG Index)
Definition: kefuncs.h:39
KAFFINITY KiIdleSummary
Definition: thrdschd.c:25
VOID FASTCALL KiIpiSend(KAFFINITY TargetSet, ULONG IpiRequest)
VOID FASTCALL KiAcquireSpinLock(IN PKSPIN_LOCK SpinLock)
Definition: spinlock.c:287
VOID FASTCALL KiReleaseSpinLock(IN PKSPIN_LOCK SpinLock)
Definition: spinlock.c:298
#define UNIMPLEMENTED_FATAL(...)
Definition: debug.h:244
ULONG DpcCount
Definition: ketypes.h:860
ULONG_PTR DpcLock
Definition: ketypes.h:854
LONG Sleeping
Definition: ketypes.h:835
LONG MaximumDpcQueueDepth
Definition: ketypes.h:756
USHORT Number
Definition: ketypes.h:632
ULONG MinimumDpcRate
Definition: ketypes.h:758
UCHAR ThreadDpcEnable
Definition: ketypes.h:768
UCHAR DpcInterruptRequested
Definition: ketypes.h:759
UCHAR DpcThreadActive
Definition: ketypes.h:762
UCHAR DpcThreadRequested
Definition: ketypes.h:760
ULONG DpcRequestRate
Definition: ketypes.h:757
UCHAR DpcRoutineActive
Definition: ketypes.h:761
@ HighImportance
Definition: ketypes.h:695
@ LowImportance
Definition: ketypes.h:693
#define ASSERT_DPC(Object)
_In_opt_ PVOID _In_opt_ PVOID SystemArgument1
Definition: ketypes.h:688
_In_opt_ PVOID _In_opt_ PVOID _In_opt_ PVOID SystemArgument2
Definition: ketypes.h:689

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;
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}
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
void __cdecl _enable(void)
Definition: intrin_arm.h:373
_In_ ULONGLONG _In_ ULONGLONG _In_ BOOLEAN Enable
Definition: ntddpcm.h:142
FORCEINLINE BOOLEAN KeDisableInterrupts(VOID)
Definition: ke.h:239

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 976 of file dpc.c.

978{
979 /* Set the DPC Importance */
981 Dpc->Importance = Importance;
982}
_In_ KDPC_IMPORTANCE Importance
Definition: kefuncs.h:82

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

◆ KeSetTargetProcessorDpc()

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

Definition at line 989 of file dpc.c.

991{
992 /* Set a target CPU */
994 Dpc->Number = Number + MAXIMUM_PROCESSORS;
995}
_In_opt_ PENTER_STATE_SYSTEM_HANDLER _In_opt_ PVOID _In_ LONG _In_opt_ LONG volatile * Number
Definition: ntpoapi.h:207

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

◆ KeSignalCallDpcDone()

VOID NTAPI KeSignalCallDpcDone ( IN PVOID  SystemArgument1)

Definition at line 1031 of file dpc.c.

1032{
1033 //
1034 // Decrement the barrier, which is actually the processor count
1035 //
1037}
#define InterlockedDecrement
Definition: armddk.h:52
int32_t * PLONG
Definition: typedefs.h:58

Referenced by ExpGetPoolTagInfoTarget().

◆ KeSignalCallDpcSynchronize()

BOOLEAN NTAPI KeSignalCallDpcSynchronize ( IN PVOID  SystemArgument2)

Definition at line 1044 of file dpc.c.

1045{
1046 //
1047 // There is nothing to do on UP systems -- the processor calling this wins
1048 //
1050 return TRUE;
1051}
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:325

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;
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");
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}
#define DPRINT1
Definition: precomp.h:8
KDPC KiTimerExpireDpc
Definition: dpc.c:25
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
NTSYSAPI void WINAPI DbgBreakPoint(void)
KTIMER_TABLE_ENTRY KiTimerTableListHead[TIMER_TABLE_SIZE]
Definition: timerobj.c:17
volatile PVOID DpcData
Definition: ketypes.h:708
LIST_ENTRY Entry
Definition: ketypes.h:778
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
uint32_t * PULONG
Definition: typedefs.h:59
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
#define TIMER_TABLE_SIZE
Definition: ketypes.h:848

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}
Type
Definition: Type.h:7
@ MediumImportance
Definition: ketypes.h:694

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
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 interrupts 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}
VOID NTAPI KiTimerExpiration(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
Definition: dpc.c:79
void __cdecl _disable(void)
Definition: intrin_arm.h:365
VOID FASTCALL KiProcessDeferredReadyList(IN PKPRCB Prcb)
Definition: thrdschd.c:41
#define KeAcquireSpinLockAtDpcLevel(SpinLock)
Definition: ke.h:125
#define KeReleaseSpinLockFromDpcLevel(SpinLock)
Definition: ke.h:135
Definition: ketypes.h:699
uint32_t ULONG_PTR
Definition: typedefs.h:65
KDEFERRED_ROUTINE * PKDEFERRED_ROUTINE
Definition: ketypes.h:690

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;
91 PKDPC TimerDpc;
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 */
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);
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 PtrToLong(p)
Definition: basetsd.h:84
BOOLEAN NTAPI KeInsertQueueDpc(IN PKDPC Dpc, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
Definition: dpc.c:725
VOID NTAPI KiCheckTimerTable(IN ULARGE_INTEGER CurrentTime)
Definition: dpc.c:33
#define UlongToPtr(u)
Definition: config.h:106
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
FORCEINLINE VOID KiReleaseDispatcherLock(IN KIRQL OldIrql)
Definition: ke_x.h:157
FORCEINLINE VOID KiRemoveEntryTimer(IN PKTIMER Timer)
Definition: ke_x.h:892
FORCEINLINE VOID KiReleaseTimerLock(IN PKSPIN_LOCK_QUEUE LockQueue)
Definition: ke_x.h:297
FORCEINLINE VOID KxUnwaitThread(IN DISPATCHER_HEADER *Object, IN KPRIORITY Increment)
Definition: ke_x.h:1259
FORCEINLINE PKSPIN_LOCK_QUEUE KiAcquireTimerLock(IN ULONG Hand)
Definition: ke_x.h:286
FORCEINLINE KIRQL KiAcquireDispatcherLock(VOID)
Definition: ke_x.h:149
FORCEINLINE VOID KxUnwaitThreadForEvent(IN PKEVENT Event, IN KPRIORITY Increment)
Definition: ke_x.h:1304
static PLARGE_INTEGER Time
Definition: time.c:105
@ TimerNotificationObject
Definition: ketypes.h:414
DWORD Interval
Definition: netstat.c:30
#define Int32x32To64(a, b)
NTKERNELAPI volatile KSYSTEM_TIME KeTickCount
Definition: clock.c:19
BOOLEAN FASTCALL KiInsertTreeTimer(IN PKTIMER Timer, IN LARGE_INTEGER Interval)
Definition: timerobj.c:26
#define MAX_TIMER_DPCS
Definition: ke.h:69
long LONG
Definition: pedump.c:60
#define KeQueryInterruptTime()
Definition: ke.h:37
Definition: ke.h:72
PVOID Context
Definition: ke.h:75
PKDEFERRED_ROUTINE Routine
Definition: ke.h:74
PKDPC Dpc
Definition: ke.h:73
UCHAR Type
Definition: ketypes.h:700
PKDEFERRED_ROUTINE DeferredRoutine
Definition: ketypes.h:704
volatile USHORT Number
Definition: ketypes.h:702
PVOID DeferredContext
Definition: ketypes.h:705
ULONG DebugDpcTime
Definition: ketypes.h:572
ULONG LowPart
Definition: ketypes.h:929
ULARGE_INTEGER Time
Definition: ketypes.h:779
$ULONG LowPart
Definition: ntbasedef.h:577
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
$ULONG HighPart
Definition: ntbasedef.h:578
static LIST_ENTRY Timers
Definition: clock.c:40
LONGLONG QuadPart
Definition: typedefs.h:114
_In_ WDFCOLLECTION _In_ ULONG Index
#define IO_NO_INCREMENT
Definition: iotypes.h:598
_In_ LARGE_INTEGER _In_ ULONG Period
Definition: kefuncs.h:1313
_In_ LONG _In_ LONG Limit
Definition: kefuncs.h:304

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;
346 PKDPC TimerDpc;
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);
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}

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().