- Fixed the freeing of memory from boot load drivers.
[reactos.git] / reactos / ntoskrnl / ke / dpc.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2000, 1999, 1998 David Welch <welch@cwcom.net>,
4 * Philip Susi <phreak@iag.net>,
5 * Eric Kohl <ekohl@abo.rhein-zeitung.de>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21 /* $Id: dpc.c,v 1.28 2003/10/12 17:05:45 hbirr Exp $
22 *
23 * COPYRIGHT: See COPYING in the top level directory
24 * PROJECT: ReactOS kernel
25 * FILE: ntoskrnl/ke/dpc.c
26 * PURPOSE: Handle DPCs (Delayed Procedure Calls)
27 * PROGRAMMER: David Welch (welch@mcmail.com)
28 * UPDATE HISTORY:
29 * 28/05/98: Created
30 * 12/3/99: Phillip Susi: Fixed IRQL problem
31 */
32
33 /*
34 * NOTE: See also the higher level support routines in ntoskrnl/io/dpc.c
35 */
36
37 /* INCLUDES ***************************************************************/
38
39 #include <ddk/ntddk.h>
40 #include <internal/ps.h>
41
42 #define NDEBUG
43 #include <internal/debug.h>
44
45 /* TYPES *******************************************************************/
46
47 /* GLOBALS ******************************************************************/
48
49 static LIST_ENTRY DpcQueueHead; /* Head of the list of pending DPCs */
50 static KSPIN_LOCK DpcQueueLock; /* Lock for the above list */
51 /*
52 * Number of pending DPCs. This is inspected by
53 * the idle thread to determine if the queue needs to
54 * be run down
55 */
56 ULONG DpcQueueSize = 0;
57
58 /* FUNCTIONS ****************************************************************/
59
60 /*
61 * @implemented
62 */
63 VOID STDCALL
64 KeInitializeDpc (PKDPC Dpc,
65 PKDEFERRED_ROUTINE DeferredRoutine,
66 PVOID DeferredContext)
67 /*
68 * FUNCTION: Initalizes a DPC
69 * ARGUMENTS:
70 * Dpc = Caller supplied DPC to be initialized
71 * DeferredRoutine = Associated DPC callback
72 * DeferredContext = Parameter to be passed to the callback
73 * NOTE: Callers must be running at IRQL PASSIVE_LEVEL
74 */
75 {
76 Dpc->Type = 0;
77 Dpc->DeferredRoutine = DeferredRoutine;
78 Dpc->DeferredContext = DeferredContext;
79 Dpc->Lock = 0;
80 }
81
82 /*
83 * @implemented
84 */
85 VOID STDCALL
86 KiDispatchInterrupt(VOID)
87 /*
88 * FUNCTION: Called to execute queued dpcs
89 */
90 {
91 PLIST_ENTRY current_entry;
92 PKDPC current;
93 KIRQL oldlvl;
94
95 assert_irql(DISPATCH_LEVEL);
96
97 if (DpcQueueSize == 0)
98 {
99 return;
100 }
101
102 KeRaiseIrql(HIGH_LEVEL, &oldlvl);
103 KeAcquireSpinLockAtDpcLevel(&DpcQueueLock);
104
105 while (!IsListEmpty(&DpcQueueHead))
106 {
107 current_entry = RemoveHeadList(&DpcQueueHead);
108 DpcQueueSize--;
109 current = CONTAINING_RECORD(current_entry,KDPC,DpcListEntry);
110 current->Lock=FALSE;
111 KeReleaseSpinLock(&DpcQueueLock, oldlvl);
112 current->DeferredRoutine(current,current->DeferredContext,
113 current->SystemArgument1,
114 current->SystemArgument2);
115
116 KeRaiseIrql(HIGH_LEVEL, &oldlvl);
117 KeAcquireSpinLockAtDpcLevel(&DpcQueueLock);
118 }
119 KeReleaseSpinLock(&DpcQueueLock, oldlvl);
120 }
121
122 /*
123 * @implemented
124 */
125 BOOLEAN STDCALL
126 KeRemoveQueueDpc (PKDPC Dpc)
127 /*
128 * FUNCTION: Removes DPC object from the system dpc queue
129 * ARGUMENTS:
130 * Dpc = DPC to remove
131 * RETURNS: TRUE if the DPC was in the queue
132 * FALSE otherwise
133 */
134 {
135 KIRQL oldIrql;
136
137 KeRaiseIrql(HIGH_LEVEL, &oldIrql);
138 KeAcquireSpinLockAtDpcLevel(&DpcQueueLock);
139 if (!Dpc->Lock)
140 {
141 KeReleaseSpinLock(&DpcQueueLock, oldIrql);
142 return(FALSE);
143 }
144 RemoveEntryList(&Dpc->DpcListEntry);
145 DpcQueueSize--;
146 Dpc->Lock=0;
147 KeReleaseSpinLock(&DpcQueueLock, oldIrql);
148 return(TRUE);
149 }
150
151 /*
152 * @implemented
153 */
154 BOOLEAN STDCALL
155 KeInsertQueueDpc (PKDPC Dpc,
156 PVOID SystemArgument1,
157 PVOID SystemArgument2)
158 /*
159 * FUNCTION: Queues a DPC for execution when the IRQL of a processor
160 * drops below DISPATCH_LEVEL
161 * ARGUMENTS:
162 * Dpc = Initalizes DPC
163 * SystemArguments[1-2] = Undocumented
164 * RETURNS: TRUE if the DPC object wasn't already in the queue
165 * FALSE otherwise
166 */
167 {
168 KIRQL oldlvl;
169 DPRINT("KeInsertQueueDpc(dpc %x, SystemArgument1 %x, SystemArgument2 %x)\n",
170 Dpc, SystemArgument1, SystemArgument2);
171
172 assert(KeGetCurrentIrql()>=DISPATCH_LEVEL);
173
174 Dpc->Number=0;
175 Dpc->Importance=MediumImportance;
176 Dpc->SystemArgument1=SystemArgument1;
177 Dpc->SystemArgument2=SystemArgument2;
178 if (Dpc->Lock)
179 {
180 return(FALSE);
181 }
182 KeRaiseIrql(HIGH_LEVEL, &oldlvl);
183 KeAcquireSpinLockAtDpcLevel(&DpcQueueLock);
184 InsertHeadList(&DpcQueueHead,&Dpc->DpcListEntry);
185 DPRINT("Dpc->DpcListEntry.Flink %x\n", Dpc->DpcListEntry.Flink);
186 DpcQueueSize++;
187 Dpc->Lock=(PULONG)1;
188 KeReleaseSpinLock( &DpcQueueLock, oldlvl );
189 DPRINT("DpcQueueHead.Flink %x\n",DpcQueueHead.Flink);
190 DPRINT("Leaving KeInsertQueueDpc()\n",0);
191 return(TRUE);
192 }
193
194 /*
195 * FUNCTION: Specifies the DPCs importance
196 * ARGUMENTS:
197 * Dpc = Initalizes DPC
198 * Importance = DPC importance
199 * RETURNS: None
200 *
201 * @implemented
202 */
203 VOID STDCALL
204 KeSetImportanceDpc (IN PKDPC Dpc,
205 IN KDPC_IMPORTANCE Importance)
206 {
207 Dpc->Importance = Importance;
208 }
209
210 /*
211 * FUNCTION: Specifies on which processor the DPC will run
212 * ARGUMENTS:
213 * Dpc = Initalizes DPC
214 * Number = Processor number
215 * RETURNS: None
216 *
217 * @unimplemented
218 */
219 VOID STDCALL
220 KeSetTargetProcessorDpc (IN PKDPC Dpc,
221 IN CCHAR Number)
222 {
223 UNIMPLEMENTED;
224 }
225
226 VOID INIT_FUNCTION
227 KeInitDpc(VOID)
228 /*
229 * FUNCTION: Initialize DPC handling
230 */
231 {
232 InitializeListHead(&DpcQueueHead);
233 KeInitializeSpinLock(&DpcQueueLock);
234 }
235
236 /* EOF */