Made header file usage more consistent
[reactos.git] / reactos / ntoskrnl / ke / dpc.c
1 /*
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)
7 * UPDATE HISTORY:
8 * 28/05/98: Created
9 * 12/3/99: Phillip Susi: Fixed IRQL problem
10 */
11
12 /*
13 * NOTE: See also the higher level support routines in ntoskrnl/io/dpc.c
14 */
15
16 /* INCLUDES ***************************************************************/
17
18 #include <ddk/ntddk.h>
19
20 #define NDEBUG
21 #include <internal/debug.h>
22
23 /* TYPES *******************************************************************/
24
25 /* GLOBALS ******************************************************************/
26
27 static LIST_ENTRY DpcQueueHead;
28 static KSPIN_LOCK DpcQueueLock;
29 ULONG DpcQueueSize = 0;
30
31 /* FUNCTIONS ****************************************************************/
32
33 VOID STDCALL KeInitializeDpc (PKDPC Dpc,
34 PKDEFERRED_ROUTINE DeferredRoutine,
35 PVOID DeferredContext)
36 /*
37 * FUNCTION: Initalizes a DPC
38 * ARGUMENTS:
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
43 */
44 {
45 Dpc->Type=0;
46 Dpc->DeferredRoutine=DeferredRoutine;
47 Dpc->DeferredContext=DeferredContext;
48 Dpc->Lock=0;
49 }
50
51 VOID KeDrainDpcQueue(VOID)
52 /*
53 * FUNCTION: Called to execute queued dpcs
54 */
55 {
56 PLIST_ENTRY current_entry;
57 PKDPC current;
58 KIRQL oldlvl;
59
60 assert_irql(DISPATCH_LEVEL);
61
62 if (DpcQueueSize == 0)
63 {
64 return;
65 }
66 DPRINT("KeDrainDpcQueue()\n");
67
68 KeRaiseIrql(HIGH_LEVEL, &oldlvl);
69 KeAcquireSpinLockAtDpcLevel(&DpcQueueLock);
70 current_entry = RemoveHeadList(&DpcQueueHead);
71 KeReleaseSpinLockFromDpcLevel(&DpcQueueLock);
72 KeLowerIrql(oldlvl);
73 current = CONTAINING_RECORD(current_entry,KDPC,DpcListEntry);
74 while (current_entry!=(&DpcQueueHead))
75 {
76 CHECKPOINT;
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);
83 CHECKPOINT;
84 current->Lock=FALSE;
85 KeRaiseIrql(HIGH_LEVEL, &oldlvl);
86 KeAcquireSpinLockAtDpcLevel(&DpcQueueLock);
87 current_entry = RemoveHeadList(&DpcQueueHead);
88 DPRINT("current_entry %x\n", current_entry);
89 DpcQueueSize--;
90 KeReleaseSpinLockFromDpcLevel(&DpcQueueLock);
91 KeLowerIrql(oldlvl);
92 current = CONTAINING_RECORD(current_entry,KDPC,DpcListEntry);
93 DPRINT("current %x\n", current);
94 }
95 }
96
97 BOOLEAN STDCALL KeRemoveQueueDpc (PKDPC Dpc)
98 /*
99 * FUNCTION: Removes DPC object from the system dpc queue
100 * ARGUMENTS:
101 * Dpc = DPC to remove
102 * RETURNS: TRUE if the DPC was in the queue
103 * FALSE otherwise
104 */
105 {
106 KIRQL oldIrql;
107
108 KeAcquireSpinLockAtDpcLevel( &DpcQueueLock );
109 KeRaiseIrql( HIGH_LEVEL, &oldIrql );
110 if (!Dpc->Lock)
111 {
112 KeReleaseSpinLock(&DpcQueueLock, oldIrql);
113 return(FALSE);
114 }
115 RemoveEntryList(&Dpc->DpcListEntry);
116 DpcQueueSize--;
117 Dpc->Lock=0;
118 KeReleaseSpinLock(&DpcQueueLock, oldIrql);
119 return(TRUE);
120 }
121
122 BOOLEAN STDCALL KeInsertQueueDpc (PKDPC Dpc,
123 PVOID SystemArgument1,
124 PVOID SystemArgument2)
125 /*
126 * FUNCTION: Queues a DPC for execution when the IRQL of a processor
127 * drops below DISPATCH_LEVEL
128 * ARGUMENTS:
129 * Dpc = Initalizes DPC
130 * SystemArguments[1-2] = Undocumented
131 * RETURNS: TRUE if the DPC object wasn't already in the queue
132 * FALSE otherwise
133 */
134 {
135 KIRQL oldlvl;
136 DPRINT("KeInsertQueueDpc(dpc %x, SystemArgument1 %x, SystemArgument2 %x)\n",
137 Dpc, SystemArgument1, SystemArgument2);
138
139 assert(KeGetCurrentIrql()>=DISPATCH_LEVEL);
140
141 Dpc->Number=0;
142 Dpc->Importance=Medium;
143 Dpc->SystemArgument1=SystemArgument1;
144 Dpc->SystemArgument2=SystemArgument2;
145 if (Dpc->Lock)
146 {
147 return(FALSE);
148 }
149 KeRaiseIrql( HIGH_LEVEL, &oldlvl );
150 KeAcquireSpinLockAtDpcLevel(&DpcQueueLock);
151 InsertHeadList(&DpcQueueHead,&Dpc->DpcListEntry);
152 DPRINT("Dpc->DpcListEntry.Flink %x\n", Dpc->DpcListEntry.Flink);
153 DpcQueueSize++;
154 Dpc->Lock=(PULONG)1;
155 KeReleaseSpinLock( &DpcQueueLock, oldlvl );
156 DPRINT("DpcQueueHead.Flink %x\n",DpcQueueHead.Flink);
157 DPRINT("Leaving KeInsertQueueDpc()\n",0);
158 return(TRUE);
159 }
160
161 VOID KeInitDpc(VOID)
162 /*
163 * FUNCTION: Initialize DPC handling
164 */
165 {
166 InitializeListHead(&DpcQueueHead);
167 KeInitializeSpinLock(&DpcQueueLock);
168 }
169