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>
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.
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.
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.
21 /* $Id: dpc.c,v 1.27 2003/07/11 01:23:15 royce Exp $
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)
30 * 12/3/99: Phillip Susi: Fixed IRQL problem
34 * NOTE: See also the higher level support routines in ntoskrnl/io/dpc.c
37 /* INCLUDES ***************************************************************/
39 #include <ddk/ntddk.h>
40 #include <internal/ps.h>
43 #include <internal/debug.h>
45 /* TYPES *******************************************************************/
47 /* GLOBALS ******************************************************************/
49 static LIST_ENTRY DpcQueueHead
; /* Head of the list of pending DPCs */
50 static KSPIN_LOCK DpcQueueLock
; /* Lock for the above list */
52 * Number of pending DPCs. This is inspected by
53 * the idle thread to determine if the queue needs to
56 ULONG DpcQueueSize
= 0;
58 /* FUNCTIONS ****************************************************************/
64 KeInitializeDpc (PKDPC Dpc
,
65 PKDEFERRED_ROUTINE DeferredRoutine
,
66 PVOID DeferredContext
)
68 * FUNCTION: Initalizes a DPC
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
77 Dpc
->DeferredRoutine
= DeferredRoutine
;
78 Dpc
->DeferredContext
= DeferredContext
;
86 KiDispatchInterrupt(VOID
)
88 * FUNCTION: Called to execute queued dpcs
91 PLIST_ENTRY current_entry
;
95 assert_irql(DISPATCH_LEVEL
);
97 if (DpcQueueSize
== 0)
102 KeRaiseIrql(HIGH_LEVEL
, &oldlvl
);
103 KeAcquireSpinLockAtDpcLevel(&DpcQueueLock
);
105 while (!IsListEmpty(&DpcQueueHead
))
107 current_entry
= RemoveHeadList(&DpcQueueHead
);
109 current
= CONTAINING_RECORD(current_entry
,KDPC
,DpcListEntry
);
111 KeReleaseSpinLock(&DpcQueueLock
, oldlvl
);
112 current
->DeferredRoutine(current
,current
->DeferredContext
,
113 current
->SystemArgument1
,
114 current
->SystemArgument2
);
116 KeRaiseIrql(HIGH_LEVEL
, &oldlvl
);
117 KeAcquireSpinLockAtDpcLevel(&DpcQueueLock
);
119 KeReleaseSpinLock(&DpcQueueLock
, oldlvl
);
126 KeRemoveQueueDpc (PKDPC Dpc
)
128 * FUNCTION: Removes DPC object from the system dpc queue
130 * Dpc = DPC to remove
131 * RETURNS: TRUE if the DPC was in the queue
137 KeRaiseIrql(HIGH_LEVEL
, &oldIrql
);
138 KeAcquireSpinLockAtDpcLevel(&DpcQueueLock
);
141 KeReleaseSpinLock(&DpcQueueLock
, oldIrql
);
144 RemoveEntryList(&Dpc
->DpcListEntry
);
147 KeReleaseSpinLock(&DpcQueueLock
, oldIrql
);
155 KeInsertQueueDpc (PKDPC Dpc
,
156 PVOID SystemArgument1
,
157 PVOID SystemArgument2
)
159 * FUNCTION: Queues a DPC for execution when the IRQL of a processor
160 * drops below DISPATCH_LEVEL
162 * Dpc = Initalizes DPC
163 * SystemArguments[1-2] = Undocumented
164 * RETURNS: TRUE if the DPC object wasn't already in the queue
169 DPRINT("KeInsertQueueDpc(dpc %x, SystemArgument1 %x, SystemArgument2 %x)\n",
170 Dpc
, SystemArgument1
, SystemArgument2
);
172 assert(KeGetCurrentIrql()>=DISPATCH_LEVEL
);
175 Dpc
->Importance
=MediumImportance
;
176 Dpc
->SystemArgument1
=SystemArgument1
;
177 Dpc
->SystemArgument2
=SystemArgument2
;
182 KeRaiseIrql(HIGH_LEVEL
, &oldlvl
);
183 KeAcquireSpinLockAtDpcLevel(&DpcQueueLock
);
184 InsertHeadList(&DpcQueueHead
,&Dpc
->DpcListEntry
);
185 DPRINT("Dpc->DpcListEntry.Flink %x\n", Dpc
->DpcListEntry
.Flink
);
188 KeReleaseSpinLock( &DpcQueueLock
, oldlvl
);
189 DPRINT("DpcQueueHead.Flink %x\n",DpcQueueHead
.Flink
);
190 DPRINT("Leaving KeInsertQueueDpc()\n",0);
195 * FUNCTION: Specifies the DPCs importance
197 * Dpc = Initalizes DPC
198 * Importance = DPC importance
204 KeSetImportanceDpc (IN PKDPC Dpc
,
205 IN KDPC_IMPORTANCE Importance
)
207 Dpc
->Importance
= Importance
;
211 * FUNCTION: Specifies on which processor the DPC will run
213 * Dpc = Initalizes DPC
214 * Number = Processor number
220 KeSetTargetProcessorDpc (IN PKDPC Dpc
,
229 * FUNCTION: Initialize DPC handling
232 InitializeListHead(&DpcQueueHead
);
233 KeInitializeSpinLock(&DpcQueueLock
);