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.
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 ****************************************************************/
61 KeInitializeDpc (PKDPC Dpc,
62 PKDEFERRED_ROUTINE DeferredRoutine,
63 PVOID DeferredContext)
65 * FUNCTION: Initalizes a DPC
67 * Dpc = Caller supplied DPC to be initialized
68 * DeferredRoutine = Associated DPC callback
69 * DeferredContext = Parameter to be passed to the callback
70 * NOTE: Callers must be running at IRQL PASSIVE_LEVEL
74 Dpc->DeferredRoutine = DeferredRoutine;
75 Dpc->DeferredContext = DeferredContext;
80 KiDispatchInterrupt(VOID)
82 * FUNCTION: Called to execute queued dpcs
85 PLIST_ENTRY current_entry;
89 assert_irql(DISPATCH_LEVEL);
91 if (DpcQueueSize == 0)
96 KeRaiseIrql(HIGH_LEVEL, &oldlvl);
97 KeAcquireSpinLockAtDpcLevel(&DpcQueueLock);
98 current_entry = RemoveHeadList(&DpcQueueHead);
99 if (current_entry != &DpcQueueHead)
103 KeReleaseSpinLockFromDpcLevel(&DpcQueueLock);
104 current = CONTAINING_RECORD(current_entry,KDPC,DpcListEntry);
107 while (current_entry!=(&DpcQueueHead))
109 current->DeferredRoutine(current,current->DeferredContext,
110 current->SystemArgument1,
111 current->SystemArgument2);
113 KeRaiseIrql(HIGH_LEVEL, &oldlvl);
114 KeAcquireSpinLockAtDpcLevel(&DpcQueueLock);
115 current_entry = RemoveHeadList(&DpcQueueHead);
116 if (current_entry != &DpcQueueHead)
120 KeReleaseSpinLockFromDpcLevel(&DpcQueueLock);
121 current = CONTAINING_RECORD(current_entry,KDPC,DpcListEntry);
128 KeRemoveQueueDpc (PKDPC Dpc)
130 * FUNCTION: Removes DPC object from the system dpc queue
132 * Dpc = DPC to remove
133 * RETURNS: TRUE if the DPC was in the queue
139 KeAcquireSpinLockAtDpcLevel(&DpcQueueLock);
140 KeRaiseIrql(HIGH_LEVEL, &oldIrql);
143 KeReleaseSpinLock(&DpcQueueLock, oldIrql);
146 RemoveEntryList(&Dpc->DpcListEntry);
149 KeReleaseSpinLock(&DpcQueueLock, oldIrql);
154 KeInsertQueueDpc (PKDPC Dpc,
155 PVOID SystemArgument1,
156 PVOID SystemArgument2)
158 * FUNCTION: Queues a DPC for execution when the IRQL of a processor
159 * drops below DISPATCH_LEVEL
161 * Dpc = Initalizes DPC
162 * SystemArguments[1-2] = Undocumented
163 * RETURNS: TRUE if the DPC object wasn't already in the queue
168 DPRINT("KeInsertQueueDpc(dpc %x, SystemArgument1 %x, SystemArgument2 %x)\n",
169 Dpc, SystemArgument1, SystemArgument2);
171 assert(KeGetCurrentIrql()>=DISPATCH_LEVEL);
174 Dpc->Importance=MediumImportance;
175 Dpc->SystemArgument1=SystemArgument1;
176 Dpc->SystemArgument2=SystemArgument2;
181 KeRaiseIrql(HIGH_LEVEL, &oldlvl);
182 KeAcquireSpinLockAtDpcLevel(&DpcQueueLock);
183 InsertHeadList(&DpcQueueHead,&Dpc->DpcListEntry);
184 DPRINT("Dpc->DpcListEntry.Flink %x\n", Dpc->DpcListEntry.Flink);
187 KeReleaseSpinLock( &DpcQueueLock, oldlvl );
188 DPRINT("DpcQueueHead.Flink %x\n",DpcQueueHead.Flink);
189 DPRINT("Leaving KeInsertQueueDpc()\n",0);
194 * FUNCTION: Specifies the DPCs importance
196 * Dpc = Initalizes DPC
197 * Importance = DPC importance
201 KeSetImportanceDpc (IN PKDPC Dpc,
202 IN KDPC_IMPORTANCE Importance)
204 Dpc->Importance = Importance;
208 * FUNCTION: Specifies on which processor the DPC will run
210 * Dpc = Initalizes DPC
211 * Number = Processor number
215 KeSetTargetProcessorDpc (IN PKDPC Dpc,
224 * FUNCTION: Initialize DPC handling
227 InitializeListHead(&DpcQueueHead);
228 KeInitializeSpinLock(&DpcQueueLock);