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
KeInitializeDpc(PKDPC Dpc
, PKDEFERRED_ROUTINE DeferredRoutine
,
34 PVOID DeferredContext
)
36 * FUNCTION: Initalizes a DPC
38 * Dpc = Caller supplied DPC to be initialized
39 * DeferredRoutine = Associated DPC callback
40 * DeferredContext = Parameter to be passed to the callback
41 * NOTE: Callers must be running at IRQL PASSIVE_LEVEL
45 Dpc
->DeferredRoutine
=DeferredRoutine
;
46 Dpc
->DeferredContext
=DeferredContext
;
50 void KeDrainDpcQueue(void)
52 * FUNCTION: Called to execute queued dpcs
55 PLIST_ENTRY current_entry
;
59 assert_irql(DISPATCH_LEVEL
);
61 if (DpcQueueSize
== 0)
65 DPRINT("KeDrainDpcQueue()\n");
67 KeAcquireSpinLockAtDpcLevel(&DpcQueueLock
);
68 KeRaiseIrql(HIGH_LEVEL
,&oldlvl
);
69 current_entry
= RemoveHeadList(&DpcQueueHead
);
71 current
= CONTAINING_RECORD(current_entry
,KDPC
,DpcListEntry
);
72 while (current_entry
!=(&DpcQueueHead
))
75 DPRINT("DpcQueueSize %d current %x current->DeferredContext %x\n",
76 DpcQueueSize
, current
, current
->DeferredContext
);
77 DPRINT("current->Flink %x\n", current
->DpcListEntry
.Flink
);
78 current
->DeferredRoutine(current
,current
->DeferredContext
,
79 current
->SystemArgument1
,
80 current
->SystemArgument2
);
83 KeRaiseIrql(HIGH_LEVEL
,&oldlvl
);
84 current_entry
= RemoveHeadList(&DpcQueueHead
);
85 DPRINT("current_entry %x\n", current_entry
);
88 current
= CONTAINING_RECORD(current_entry
,KDPC
,DpcListEntry
);
89 DPRINT("current %x\n", current
);
91 KeReleaseSpinLockFromDpcLevel(&DpcQueueLock
);
94 BOOLEAN
KeRemoveQueueDpc(PKDPC Dpc
)
96 * FUNCTION: Removes DPC object from the system dpc queue
99 * RETURNS: TRUE if the DPC was in the queue
105 KeAcquireSpinLockAtDpcLevel( &DpcQueueLock
);
106 KeRaiseIrql( HIGH_LEVEL
, &oldIrql
);
109 KeReleaseSpinLock(&DpcQueueLock
, oldIrql
);
112 RemoveEntryList(&Dpc
->DpcListEntry
);
115 KeReleaseSpinLock(&DpcQueueLock
, oldIrql
);
119 BOOLEAN
KeInsertQueueDpc(PKDPC dpc
, PVOID SystemArgument1
,
120 PVOID SystemArgument2
)
122 * FUNCTION: Queues a DPC for execution when the IRQL of a processor
123 * drops below DISPATCH_LEVEL
125 * Dpc = Initalizes DPC
126 * SystemArguments[1-2] = Undocumented
127 * RETURNS: TRUE if the DPC object wasn't already in the queue
132 DPRINT("KeInsertQueueDpc(dpc %x, SystemArgument1 %x, SystemArgument2 %x)\n",
133 dpc
, SystemArgument1
, SystemArgument2
);
135 assert(KeGetCurrentIrql()>=DISPATCH_LEVEL
);
138 dpc
->Importance
=Medium
;
139 dpc
->SystemArgument1
=SystemArgument1
;
140 dpc
->SystemArgument2
=SystemArgument2
;
145 KeRaiseIrql( HIGH_LEVEL
, &oldlvl
);
146 KeAcquireSpinLockAtDpcLevel(&DpcQueueLock
);
147 InsertHeadList(&DpcQueueHead
,&dpc
->DpcListEntry
);
148 DPRINT("dpc->DpcListEntry.Flink %x\n", dpc
->DpcListEntry
.Flink
);
150 KeReleaseSpinLock( &DpcQueueLock
, oldlvl
);
152 DPRINT("DpcQueueHead.Flink %x\n",DpcQueueHead
.Flink
);
153 DPRINT("Leaving KeInsertQueueDpc()\n",0);
159 * FUNCTION: Initialize DPC handling
162 InitializeListHead(&DpcQueueHead
);
163 KeInitializeSpinLock(&DpcQueueLock
);