2000-12-10 23:42:01 +00:00
|
|
|
/*
|
|
|
|
* ReactOS kernel
|
2003-12-30 18:52:06 +00:00
|
|
|
* Copyright (C) 2000, 1999, 1998 David Welch <welch@cwcom.net>,
|
2000-12-10 23:42:01 +00:00
|
|
|
* Philip Susi <phreak@iag.net>,
|
|
|
|
* Eric Kohl <ekohl@abo.rhein-zeitung.de>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
*/
|
2004-08-12 06:04:21 +00:00
|
|
|
/* $Id: dpc.c,v 1.33 2004/08/12 06:04:21 ion Exp $
|
2000-07-01 18:27:03 +00:00
|
|
|
*
|
1998-08-25 04:27:26 +00:00
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS kernel
|
1998-09-05 17:34:23 +00:00
|
|
|
* FILE: ntoskrnl/ke/dpc.c
|
1998-08-25 04:27:26 +00:00
|
|
|
* PURPOSE: Handle DPCs (Delayed Procedure Calls)
|
|
|
|
* PROGRAMMER: David Welch (welch@mcmail.com)
|
|
|
|
* UPDATE HISTORY:
|
|
|
|
* 28/05/98: Created
|
1999-12-05 08:30:10 +00:00
|
|
|
* 12/3/99: Phillip Susi: Fixed IRQL problem
|
1998-08-25 04:27:26 +00:00
|
|
|
*/
|
2000-07-01 18:27:03 +00:00
|
|
|
|
1998-08-25 04:27:26 +00:00
|
|
|
/*
|
1998-09-05 17:34:23 +00:00
|
|
|
* NOTE: See also the higher level support routines in ntoskrnl/io/dpc.c
|
1998-08-25 04:27:26 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES ***************************************************************/
|
|
|
|
|
2002-09-08 10:23:54 +00:00
|
|
|
#include <ddk/ntddk.h>
|
|
|
|
#include <internal/ps.h>
|
1998-08-25 04:27:26 +00:00
|
|
|
|
1998-09-05 17:34:23 +00:00
|
|
|
#define NDEBUG
|
|
|
|
#include <internal/debug.h>
|
1998-08-25 04:27:26 +00:00
|
|
|
|
2004-07-29 23:28:48 +00:00
|
|
|
extern volatile ULONGLONG KeTickCount;
|
|
|
|
|
1998-08-25 04:27:26 +00:00
|
|
|
/* TYPES *******************************************************************/
|
|
|
|
|
|
|
|
/* GLOBALS ******************************************************************/
|
|
|
|
|
2000-12-10 23:42:01 +00:00
|
|
|
static LIST_ENTRY DpcQueueHead; /* Head of the list of pending DPCs */
|
|
|
|
static KSPIN_LOCK DpcQueueLock; /* Lock for the above list */
|
2004-07-29 23:28:48 +00:00
|
|
|
static ULONGLONG DpcTimeInside = 0;
|
|
|
|
|
2003-12-30 18:52:06 +00:00
|
|
|
/*
|
2000-12-10 23:42:01 +00:00
|
|
|
* Number of pending DPCs. This is inspected by
|
|
|
|
* the idle thread to determine if the queue needs to
|
|
|
|
* be run down
|
|
|
|
*/
|
2003-12-30 18:52:06 +00:00
|
|
|
ULONG DpcQueueSize = 0;
|
1998-08-25 04:27:26 +00:00
|
|
|
|
2004-07-29 23:28:48 +00:00
|
|
|
/*
|
|
|
|
* Number of DPC's Processed.
|
|
|
|
*/
|
|
|
|
ULONG DpcCount = 0;
|
|
|
|
|
1998-08-25 04:27:26 +00:00
|
|
|
/* FUNCTIONS ****************************************************************/
|
|
|
|
|
2003-07-10 17:44:06 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2003-12-30 18:52:06 +00:00
|
|
|
VOID STDCALL
|
2000-12-10 23:42:01 +00:00
|
|
|
KeInitializeDpc (PKDPC Dpc,
|
|
|
|
PKDEFERRED_ROUTINE DeferredRoutine,
|
|
|
|
PVOID DeferredContext)
|
1998-08-25 04:27:26 +00:00
|
|
|
/*
|
|
|
|
* FUNCTION: Initalizes a DPC
|
|
|
|
* ARGUMENTS:
|
|
|
|
* Dpc = Caller supplied DPC to be initialized
|
|
|
|
* DeferredRoutine = Associated DPC callback
|
|
|
|
* DeferredContext = Parameter to be passed to the callback
|
|
|
|
* NOTE: Callers must be running at IRQL PASSIVE_LEVEL
|
|
|
|
*/
|
|
|
|
{
|
2000-12-10 23:42:01 +00:00
|
|
|
Dpc->Type = 0;
|
|
|
|
Dpc->DeferredRoutine = DeferredRoutine;
|
|
|
|
Dpc->DeferredContext = DeferredContext;
|
|
|
|
Dpc->Lock = 0;
|
1998-08-25 04:27:26 +00:00
|
|
|
}
|
|
|
|
|
2003-07-10 17:44:06 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2003-12-30 18:52:06 +00:00
|
|
|
VOID STDCALL
|
2000-12-10 23:42:01 +00:00
|
|
|
KiDispatchInterrupt(VOID)
|
1998-08-25 04:27:26 +00:00
|
|
|
/*
|
|
|
|
* FUNCTION: Called to execute queued dpcs
|
|
|
|
*/
|
|
|
|
{
|
1998-09-05 17:34:23 +00:00
|
|
|
PLIST_ENTRY current_entry;
|
|
|
|
PKDPC current;
|
1998-12-08 16:51:47 +00:00
|
|
|
KIRQL oldlvl;
|
2003-12-30 18:52:06 +00:00
|
|
|
|
1999-06-27 13:01:23 +00:00
|
|
|
assert_irql(DISPATCH_LEVEL);
|
2003-12-30 18:52:06 +00:00
|
|
|
|
1999-05-29 00:15:17 +00:00
|
|
|
if (DpcQueueSize == 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2003-12-30 18:52:06 +00:00
|
|
|
|
1999-12-10 17:04:37 +00:00
|
|
|
KeRaiseIrql(HIGH_LEVEL, &oldlvl);
|
2004-01-18 22:42:50 +00:00
|
|
|
KiAcquireSpinLock(&DpcQueueLock);
|
2001-04-02 04:07:49 +00:00
|
|
|
|
2004-07-29 23:28:48 +00:00
|
|
|
DpcTimeInside = KeTickCount;
|
|
|
|
DpcCount = DpcCount + DpcQueueSize;
|
|
|
|
|
2003-06-16 19:18:14 +00:00
|
|
|
while (!IsListEmpty(&DpcQueueHead))
|
|
|
|
{
|
|
|
|
current_entry = RemoveHeadList(&DpcQueueHead);
|
|
|
|
DpcQueueSize--;
|
2003-12-30 18:52:06 +00:00
|
|
|
|
|
|
|
assert(DpcQueueSize || IsListEmpty(&DpcQueueHead));
|
|
|
|
|
2003-06-16 19:18:14 +00:00
|
|
|
current = CONTAINING_RECORD(current_entry,KDPC,DpcListEntry);
|
|
|
|
current->Lock=FALSE;
|
2004-01-18 22:42:50 +00:00
|
|
|
KiReleaseSpinLock(&DpcQueueLock);
|
2003-12-30 18:52:06 +00:00
|
|
|
KeLowerIrql(oldlvl);
|
2003-06-16 19:18:14 +00:00
|
|
|
current->DeferredRoutine(current,current->DeferredContext,
|
|
|
|
current->SystemArgument1,
|
|
|
|
current->SystemArgument2);
|
|
|
|
|
|
|
|
KeRaiseIrql(HIGH_LEVEL, &oldlvl);
|
2004-01-18 22:42:50 +00:00
|
|
|
KiAcquireSpinLock(&DpcQueueLock);
|
2003-06-16 19:18:14 +00:00
|
|
|
}
|
2004-07-29 23:28:48 +00:00
|
|
|
KiDpcTime += (KeTickCount - DpcTimeInside);
|
|
|
|
|
2004-01-18 22:42:50 +00:00
|
|
|
KiReleaseSpinLock(&DpcQueueLock);
|
2003-12-30 18:52:06 +00:00
|
|
|
KeLowerIrql(oldlvl);
|
1998-08-25 04:27:26 +00:00
|
|
|
}
|
|
|
|
|
2004-06-23 22:32:24 +00:00
|
|
|
/*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
|
|
|
STDCALL
|
|
|
|
VOID
|
|
|
|
KeFlushQueuedDpcs(
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
|
|
|
STDCALL
|
|
|
|
VOID
|
|
|
|
KeIsExecutingDpc(
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
2003-07-10 17:44:06 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2003-12-30 18:52:06 +00:00
|
|
|
BOOLEAN STDCALL
|
2000-12-10 23:42:01 +00:00
|
|
|
KeRemoveQueueDpc (PKDPC Dpc)
|
1998-08-25 04:27:26 +00:00
|
|
|
/*
|
|
|
|
* FUNCTION: Removes DPC object from the system dpc queue
|
|
|
|
* ARGUMENTS:
|
|
|
|
* Dpc = DPC to remove
|
|
|
|
* RETURNS: TRUE if the DPC was in the queue
|
|
|
|
* FALSE otherwise
|
|
|
|
*/
|
|
|
|
{
|
1999-11-12 12:01:17 +00:00
|
|
|
KIRQL oldIrql;
|
2003-12-30 18:52:06 +00:00
|
|
|
BOOLEAN WasInQueue;
|
|
|
|
|
2002-01-09 03:00:21 +00:00
|
|
|
KeRaiseIrql(HIGH_LEVEL, &oldIrql);
|
2004-01-18 22:42:50 +00:00
|
|
|
KiAcquireSpinLock(&DpcQueueLock);
|
2003-12-30 18:52:06 +00:00
|
|
|
WasInQueue = Dpc->Lock ? TRUE : FALSE;
|
|
|
|
if (WasInQueue)
|
1998-08-25 04:27:26 +00:00
|
|
|
{
|
2003-12-30 18:52:06 +00:00
|
|
|
RemoveEntryList(&Dpc->DpcListEntry);
|
|
|
|
DpcQueueSize--;
|
|
|
|
Dpc->Lock=0;
|
1998-08-25 04:27:26 +00:00
|
|
|
}
|
2003-12-30 18:52:06 +00:00
|
|
|
|
|
|
|
assert(DpcQueueSize || IsListEmpty(&DpcQueueHead));
|
|
|
|
|
2004-01-18 22:42:50 +00:00
|
|
|
KiReleaseSpinLock(&DpcQueueLock);
|
2003-12-30 18:52:06 +00:00
|
|
|
KeLowerIrql(oldIrql);
|
|
|
|
|
|
|
|
return WasInQueue;
|
1998-08-25 04:27:26 +00:00
|
|
|
}
|
|
|
|
|
2003-07-10 17:44:06 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2003-12-30 18:52:06 +00:00
|
|
|
BOOLEAN STDCALL
|
2000-12-10 23:42:01 +00:00
|
|
|
KeInsertQueueDpc (PKDPC Dpc,
|
|
|
|
PVOID SystemArgument1,
|
|
|
|
PVOID SystemArgument2)
|
1998-08-25 04:27:26 +00:00
|
|
|
/*
|
|
|
|
* FUNCTION: Queues a DPC for execution when the IRQL of a processor
|
|
|
|
* drops below DISPATCH_LEVEL
|
|
|
|
* ARGUMENTS:
|
|
|
|
* Dpc = Initalizes DPC
|
|
|
|
* SystemArguments[1-2] = Undocumented
|
|
|
|
* RETURNS: TRUE if the DPC object wasn't already in the queue
|
|
|
|
* FALSE otherwise
|
|
|
|
*/
|
|
|
|
{
|
1999-12-05 08:30:10 +00:00
|
|
|
KIRQL oldlvl;
|
1999-05-29 00:15:17 +00:00
|
|
|
DPRINT("KeInsertQueueDpc(dpc %x, SystemArgument1 %x, SystemArgument2 %x)\n",
|
2000-06-04 19:51:05 +00:00
|
|
|
Dpc, SystemArgument1, SystemArgument2);
|
1999-06-27 13:01:23 +00:00
|
|
|
|
1998-09-15 14:31:18 +00:00
|
|
|
assert(KeGetCurrentIrql()>=DISPATCH_LEVEL);
|
1999-06-27 13:01:23 +00:00
|
|
|
|
2000-06-04 19:51:05 +00:00
|
|
|
Dpc->Number=0;
|
2000-07-01 18:27:03 +00:00
|
|
|
Dpc->Importance=MediumImportance;
|
2000-06-04 19:51:05 +00:00
|
|
|
Dpc->SystemArgument1=SystemArgument1;
|
|
|
|
Dpc->SystemArgument2=SystemArgument2;
|
|
|
|
if (Dpc->Lock)
|
1998-08-25 04:27:26 +00:00
|
|
|
{
|
|
|
|
return(FALSE);
|
|
|
|
}
|
2002-01-09 03:00:21 +00:00
|
|
|
KeRaiseIrql(HIGH_LEVEL, &oldlvl);
|
2004-01-18 22:42:50 +00:00
|
|
|
KiAcquireSpinLock(&DpcQueueLock);
|
2003-12-30 18:52:06 +00:00
|
|
|
assert(DpcQueueSize || IsListEmpty(&DpcQueueHead));
|
2000-06-04 19:51:05 +00:00
|
|
|
InsertHeadList(&DpcQueueHead,&Dpc->DpcListEntry);
|
|
|
|
DPRINT("Dpc->DpcListEntry.Flink %x\n", Dpc->DpcListEntry.Flink);
|
1998-12-08 19:44:04 +00:00
|
|
|
DpcQueueSize++;
|
2000-06-04 19:51:05 +00:00
|
|
|
Dpc->Lock=(PULONG)1;
|
2004-01-18 22:42:50 +00:00
|
|
|
KiReleaseSpinLock(&DpcQueueLock);
|
2003-12-30 18:52:06 +00:00
|
|
|
KeLowerIrql(oldlvl);
|
1998-09-05 17:34:23 +00:00
|
|
|
DPRINT("DpcQueueHead.Flink %x\n",DpcQueueHead.Flink);
|
|
|
|
DPRINT("Leaving KeInsertQueueDpc()\n",0);
|
1998-08-25 04:27:26 +00:00
|
|
|
return(TRUE);
|
|
|
|
}
|
|
|
|
|
2000-07-01 18:27:03 +00:00
|
|
|
/*
|
|
|
|
* FUNCTION: Specifies the DPCs importance
|
|
|
|
* ARGUMENTS:
|
|
|
|
* Dpc = Initalizes DPC
|
|
|
|
* Importance = DPC importance
|
|
|
|
* RETURNS: None
|
2003-07-10 17:44:06 +00:00
|
|
|
*
|
|
|
|
* @implemented
|
2000-07-01 18:27:03 +00:00
|
|
|
*/
|
2000-12-10 23:42:01 +00:00
|
|
|
VOID STDCALL
|
|
|
|
KeSetImportanceDpc (IN PKDPC Dpc,
|
|
|
|
IN KDPC_IMPORTANCE Importance)
|
2000-07-01 18:27:03 +00:00
|
|
|
{
|
|
|
|
Dpc->Importance = Importance;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* FUNCTION: Specifies on which processor the DPC will run
|
|
|
|
* ARGUMENTS:
|
|
|
|
* Dpc = Initalizes DPC
|
|
|
|
* Number = Processor number
|
|
|
|
* RETURNS: None
|
2003-07-10 17:44:06 +00:00
|
|
|
*
|
|
|
|
* @unimplemented
|
2000-07-01 18:27:03 +00:00
|
|
|
*/
|
2000-12-10 23:42:01 +00:00
|
|
|
VOID STDCALL
|
|
|
|
KeSetTargetProcessorDpc (IN PKDPC Dpc,
|
|
|
|
IN CCHAR Number)
|
2000-07-01 18:27:03 +00:00
|
|
|
{
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
2003-10-12 17:05:50 +00:00
|
|
|
VOID INIT_FUNCTION
|
2000-12-10 23:42:01 +00:00
|
|
|
KeInitDpc(VOID)
|
1998-08-25 04:27:26 +00:00
|
|
|
/*
|
|
|
|
* FUNCTION: Initialize DPC handling
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
InitializeListHead(&DpcQueueHead);
|
1999-12-02 20:53:55 +00:00
|
|
|
KeInitializeSpinLock(&DpcQueueLock);
|
1998-08-25 04:27:26 +00:00
|
|
|
}
|
|
|
|
|
2000-07-01 18:27:03 +00:00
|
|
|
/* EOF */
|