2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ke/dpc.c
5 * PURPOSE: Handle DPCs (Delayed Procedure Calls)
6 * PROGRAMMER: David Welch (welch@mcmail.com)
9 * 12/3/99: Phillip Susi: Fixed IRQL problem
13 * NOTE: See also the higher level support routines in ntoskrnl/io/dpc.c
16 /* INCLUDES ***************************************************************/
18 #include <ddk/ntddk.h>
21 #include <internal/debug.h>
23 /* TYPES *******************************************************************/
25 /* GLOBALS ******************************************************************/
27 static LIST_ENTRY DpcQueueHead
;
28 static KSPIN_LOCK DpcQueueLock
;
29 ULONG DpcQueueSize
= 0;
31 /* FUNCTIONS ****************************************************************/
33 VOID STDCALL
KeInitializeDpc (PKDPC Dpc
,
34 PKDEFERRED_ROUTINE DeferredRoutine
,
35 PVOID DeferredContext
)
37 * FUNCTION: Initalizes a DPC
39 * Dpc = Caller supplied DPC to be initialized
40 * DeferredRoutine = Associated DPC callback
41 * DeferredContext = Parameter to be passed to the callback
42 * NOTE: Callers must be running at IRQL PASSIVE_LEVEL
46 Dpc
->DeferredRoutine
=DeferredRoutine
;
47 Dpc
->DeferredContext
=DeferredContext
;
51 VOID
KeDrainDpcQueue(VOID
)
53 * FUNCTION: Called to execute queued dpcs
56 PLIST_ENTRY current_entry
;
60 assert_irql(DISPATCH_LEVEL
);
62 if (DpcQueueSize
== 0)
66 DPRINT("KeDrainDpcQueue()\n");
68 KeRaiseIrql(HIGH_LEVEL
, &oldlvl
);
69 KeAcquireSpinLockAtDpcLevel(&DpcQueueLock
);
70 current_entry
= RemoveHeadList(&DpcQueueHead
);
71 KeReleaseSpinLockFromDpcLevel(&DpcQueueLock
);
73 current
= CONTAINING_RECORD(current_entry
,KDPC
,DpcListEntry
);
74 while (current_entry
!=(&DpcQueueHead
))
77 DPRINT("DpcQueueSize %d current %x current->DeferredContext %x\n",
78 DpcQueueSize
, current
, current
->DeferredContext
);
79 DPRINT("current->Flink %x\n", current
->DpcListEntry
.Flink
);
80 current
->DeferredRoutine(current
,current
->DeferredContext
,
81 current
->SystemArgument1
,
82 current
->SystemArgument2
);
85 KeRaiseIrql(HIGH_LEVEL
, &oldlvl
);
86 KeAcquireSpinLockAtDpcLevel(&DpcQueueLock
);
87 current_entry
= RemoveHeadList(&DpcQueueHead
);
88 DPRINT("current_entry %x\n", current_entry
);
90 KeReleaseSpinLockFromDpcLevel(&DpcQueueLock
);
92 current
= CONTAINING_RECORD(current_entry
,KDPC
,DpcListEntry
);
93 DPRINT("current %x\n", current
);
97 BOOLEAN STDCALL
KeRemoveQueueDpc (PKDPC Dpc
)
99 * FUNCTION: Removes DPC object from the system dpc queue
101 * Dpc = DPC to remove
102 * RETURNS: TRUE if the DPC was in the queue
108 KeAcquireSpinLockAtDpcLevel( &DpcQueueLock
);
109 KeRaiseIrql( HIGH_LEVEL
, &oldIrql
);
112 KeReleaseSpinLock(&DpcQueueLock
, oldIrql
);
115 RemoveEntryList(&Dpc
->DpcListEntry
);
118 KeReleaseSpinLock(&DpcQueueLock
, oldIrql
);
122 BOOLEAN STDCALL
KeInsertQueueDpc (PKDPC Dpc
,
123 PVOID SystemArgument1
,
124 PVOID SystemArgument2
)
126 * FUNCTION: Queues a DPC for execution when the IRQL of a processor
127 * drops below DISPATCH_LEVEL
129 * Dpc = Initalizes DPC
130 * SystemArguments[1-2] = Undocumented
131 * RETURNS: TRUE if the DPC object wasn't already in the queue
136 DPRINT("KeInsertQueueDpc(dpc %x, SystemArgument1 %x, SystemArgument2 %x)\n",
137 Dpc
, SystemArgument1
, SystemArgument2
);
139 assert(KeGetCurrentIrql()>=DISPATCH_LEVEL
);
142 Dpc
->Importance
=Medium
;
143 Dpc
->SystemArgument1
=SystemArgument1
;
144 Dpc
->SystemArgument2
=SystemArgument2
;
149 KeRaiseIrql( HIGH_LEVEL
, &oldlvl
);
150 KeAcquireSpinLockAtDpcLevel(&DpcQueueLock
);
151 InsertHeadList(&DpcQueueHead
,&Dpc
->DpcListEntry
);
152 DPRINT("Dpc->DpcListEntry.Flink %x\n", Dpc
->DpcListEntry
.Flink
);
155 KeReleaseSpinLock( &DpcQueueLock
, oldlvl
);
156 DPRINT("DpcQueueHead.Flink %x\n",DpcQueueHead
.Flink
);
157 DPRINT("Leaving KeInsertQueueDpc()\n",0);
163 * FUNCTION: Initialize DPC handling
166 InitializeListHead(&DpcQueueHead
);
167 KeInitializeSpinLock(&DpcQueueLock
);