2006-09-02 16:19:00 +00:00
|
|
|
/*
|
|
|
|
* PROJECT: ReactOS Kernel
|
|
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
|
|
* FILE: ntoskrnl/ke/i386/cpu.c
|
|
|
|
* PURPOSE: Routines for CPU-level support
|
|
|
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
2005-01-26 13:58:37 +00:00
|
|
|
* Philip Susi (phreak@iag.net)
|
|
|
|
* Eric Kohl (ekohl@abo.rhein-zeitung.de)
|
1998-08-25 04:27:26 +00:00
|
|
|
*/
|
2000-07-01 18:27:03 +00:00
|
|
|
|
2006-09-02 16:19:00 +00:00
|
|
|
/* INCLUDES ******************************************************************/
|
1998-08-25 04:27:26 +00:00
|
|
|
|
2006-09-02 16:19:00 +00:00
|
|
|
#define NTDDI_VERSION NTDDI_WS03
|
1998-08-25 04:27:26 +00:00
|
|
|
|
2004-08-15 16:39:12 +00:00
|
|
|
#include <ntoskrnl.h>
|
1998-09-05 17:34:23 +00:00
|
|
|
#define NDEBUG
|
2006-09-02 16:19:00 +00:00
|
|
|
#include <debug.h>
|
1998-08-25 04:27:26 +00:00
|
|
|
|
2006-09-02 16:19:00 +00:00
|
|
|
/* GLOBALS *******************************************************************/
|
2005-11-28 23:25:31 +00:00
|
|
|
|
2006-07-13 06:23:34 +00:00
|
|
|
ULONG KiMaximumDpcQueueDepth = 4;
|
|
|
|
ULONG KiMinimumDpcRate = 3;
|
|
|
|
ULONG KiAdjustDpcThreshold = 20;
|
|
|
|
ULONG KiIdealDpcRate = 20;
|
2006-09-02 04:40:09 +00:00
|
|
|
KMUTEX KiGenericCallDpcMutex;
|
2005-11-28 23:25:31 +00:00
|
|
|
|
2006-09-02 16:19:00 +00:00
|
|
|
/* PRIVATE FUNCTIONS *********************************************************/
|
1998-08-25 04:27:26 +00:00
|
|
|
|
2004-11-21 06:51:18 +00:00
|
|
|
VOID
|
2006-09-02 16:19:00 +00:00
|
|
|
NTAPI
|
|
|
|
KiInitializeDpc(IN PKDPC Dpc,
|
|
|
|
IN PKDEFERRED_ROUTINE DeferredRoutine,
|
|
|
|
IN PVOID DeferredContext,
|
|
|
|
IN KOBJECTS Type)
|
1998-08-25 04:27:26 +00:00
|
|
|
{
|
2006-09-02 16:19:00 +00:00
|
|
|
/* Setup the DPC Object */
|
|
|
|
Dpc->Type = Type;
|
2005-03-12 19:45:37 +00:00
|
|
|
Dpc->Number= 0;
|
|
|
|
Dpc->Importance= MediumImportance;
|
|
|
|
Dpc->DeferredRoutine = DeferredRoutine;
|
|
|
|
Dpc->DeferredContext = DeferredContext;
|
|
|
|
Dpc->DpcData = NULL;
|
1998-08-25 04:27:26 +00:00
|
|
|
}
|
|
|
|
|
2006-09-02 16:19:00 +00:00
|
|
|
/* PUBLIC FUNCTIONS **********************************************************/
|
|
|
|
|
2004-06-23 22:32:24 +00:00
|
|
|
/*
|
2004-11-21 06:51:18 +00:00
|
|
|
* @implemented
|
2004-06-23 22:32:24 +00:00
|
|
|
*/
|
2005-03-12 19:45:37 +00:00
|
|
|
VOID
|
2006-09-02 16:19:00 +00:00
|
|
|
NTAPI
|
|
|
|
KeInitializeThreadedDpc(IN PKDPC Dpc,
|
|
|
|
IN PKDEFERRED_ROUTINE DeferredRoutine,
|
|
|
|
IN PVOID DeferredContext)
|
2004-06-23 22:32:24 +00:00
|
|
|
{
|
2006-09-02 16:19:00 +00:00
|
|
|
/* Call the internal routine */
|
|
|
|
KiInitializeDpc(Dpc, DeferredRoutine, DeferredContext, ThreadedDpcObject);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
KeInitializeDpc(IN PKDPC Dpc,
|
|
|
|
IN PKDEFERRED_ROUTINE DeferredRoutine,
|
|
|
|
IN PVOID DeferredContext)
|
|
|
|
{
|
|
|
|
/* Call the internal routine */
|
|
|
|
KiInitializeDpc(Dpc, DeferredRoutine, DeferredContext, DpcObject);
|
2004-06-23 22:32:24 +00:00
|
|
|
}
|
|
|
|
|
2003-07-10 17:44:06 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
1998-08-25 04:27:26 +00:00
|
|
|
*/
|
2005-05-09 01:38:29 +00:00
|
|
|
BOOLEAN
|
2006-09-02 16:19:00 +00:00
|
|
|
NTAPI
|
|
|
|
KeInsertQueueDpc(IN PKDPC Dpc,
|
|
|
|
IN PVOID SystemArgument1,
|
|
|
|
IN PVOID SystemArgument2)
|
1998-08-25 04:27:26 +00:00
|
|
|
{
|
2005-03-12 19:45:37 +00:00
|
|
|
KIRQL OldIrql;
|
2006-09-02 16:19:00 +00:00
|
|
|
PKPRCB Prcb, CurrentPrcb = KeGetCurrentPrcb();
|
|
|
|
ULONG Cpu;
|
|
|
|
PKDPC_DATA DpcData;
|
|
|
|
BOOLEAN DpcConfigured = FALSE, DpcInserted = FALSE;
|
|
|
|
ASSERT_DPC(Dpc);
|
2005-03-12 19:45:37 +00:00
|
|
|
|
|
|
|
/* Check IRQL and Raise it to HIGH_LEVEL */
|
|
|
|
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2006-09-02 16:19:00 +00:00
|
|
|
/* Check if the DPC has more then the maximum number of CPUs */
|
|
|
|
if (Dpc->Number >= MAXIMUM_PROCESSORS)
|
|
|
|
{
|
|
|
|
/* Then substract the maximum and get that PRCB. */
|
|
|
|
Cpu = Dpc->Number - MAXIMUM_PROCESSORS;
|
|
|
|
Prcb = KiProcessorBlock[Cpu];
|
2005-03-12 19:45:37 +00:00
|
|
|
}
|
2006-09-02 16:19:00 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Use the current one */
|
|
|
|
Prcb = CurrentPrcb;
|
|
|
|
Cpu = Prcb->Number;
|
2005-03-12 19:45:37 +00:00
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2006-09-02 16:19:00 +00:00
|
|
|
/* Check if this is a threaded DPC and threaded DPCs are enabled */
|
|
|
|
if ((Dpc->Type = ThreadedDpcObject) && (Prcb->ThreadDpcEnable))
|
|
|
|
{
|
|
|
|
/* Then use the threaded data */
|
|
|
|
DpcData = &Prcb->DpcData[DPC_THREADED];
|
2005-03-12 19:45:37 +00:00
|
|
|
}
|
2006-09-02 16:19:00 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Otherwise, use the regular data */
|
|
|
|
DpcData = &Prcb->DpcData[DPC_NORMAL];
|
2005-03-12 19:45:37 +00:00
|
|
|
}
|
|
|
|
|
2006-09-02 16:19:00 +00:00
|
|
|
/* Acquire the DPC lock */
|
|
|
|
KiAcquireSpinLock(&DpcData->DpcLock);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2006-09-02 16:19:00 +00:00
|
|
|
/* Get the DPC Data */
|
|
|
|
if (!InterlockedCompareExchangePointer(&Dpc->DpcData, DpcData, NULL))
|
|
|
|
{
|
|
|
|
/* Now we can play with the DPC safely */
|
|
|
|
Dpc->SystemArgument1 = SystemArgument1;
|
|
|
|
Dpc->SystemArgument2 = SystemArgument2;
|
|
|
|
DpcData->DpcQueueDepth++;
|
|
|
|
DpcData->DpcCount++;
|
|
|
|
DpcConfigured = TRUE;
|
|
|
|
|
|
|
|
/* Check if this is a high importance DPC */
|
|
|
|
if (Dpc->Importance == HighImportance)
|
|
|
|
{
|
|
|
|
/* Pre-empty other DPCs */
|
|
|
|
InsertHeadList(&DpcData->DpcListHead, &Dpc->DpcListEntry);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Add it at the end */
|
|
|
|
InsertTailList(&DpcData->DpcListHead, &Dpc->DpcListEntry);
|
|
|
|
}
|
2005-03-12 19:45:37 +00:00
|
|
|
|
2006-09-02 16:19:00 +00:00
|
|
|
/* Check if this is the DPC on the threaded list */
|
|
|
|
if (&Prcb->DpcData[DPC_THREADED].DpcListHead == &DpcData->DpcListHead)
|
|
|
|
{
|
|
|
|
/* Make sure a threaded DPC isn't already active */
|
|
|
|
if (!(Prcb->DpcThreadActive) && (!Prcb->DpcThreadRequested))
|
|
|
|
{
|
|
|
|
/* FIXME: Setup Threaded DPC */
|
|
|
|
ASSERT(FALSE);
|
2005-03-12 19:45:37 +00:00
|
|
|
}
|
2006-09-02 16:19:00 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Make sure a DPC isn't executing already */
|
|
|
|
if ((!Prcb->DpcRoutineActive) && (!Prcb->DpcInterruptRequested))
|
|
|
|
{
|
|
|
|
/* Check if this is the same CPU */
|
|
|
|
if (Prcb != CurrentPrcb)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Check if the DPC is of high importance or above the
|
|
|
|
* maximum depth. If it is, then make sure that the CPU
|
|
|
|
* isn't idle, or that it's sleeping.
|
|
|
|
*/
|
|
|
|
if (((Dpc->Importance == HighImportance) ||
|
|
|
|
(DpcData->DpcQueueDepth >=
|
|
|
|
Prcb->MaximumDpcQueueDepth)) &&
|
|
|
|
(!(AFFINITY_MASK(Cpu) & IdleProcessorMask) ||
|
|
|
|
(Prcb->Sleeping)))
|
|
|
|
{
|
|
|
|
/* Set interrupt requested */
|
|
|
|
Prcb->DpcInterruptRequested = TRUE;
|
|
|
|
|
|
|
|
/* Set DPC inserted */
|
|
|
|
DpcInserted = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Check if the DPC is of anything but low importance */
|
|
|
|
if ((Dpc->Importance != LowImportance) ||
|
|
|
|
(DpcData->DpcQueueDepth >=
|
|
|
|
Prcb->MaximumDpcQueueDepth) ||
|
|
|
|
(Prcb->DpcRequestRate < Prcb->MinimumDpcRate))
|
|
|
|
{
|
|
|
|
/* Set interrupt requested */
|
|
|
|
Prcb->DpcInterruptRequested = TRUE;
|
|
|
|
|
|
|
|
/* Set DPC inserted */
|
|
|
|
DpcInserted = TRUE;
|
|
|
|
}
|
|
|
|
}
|
2005-03-12 19:45:37 +00:00
|
|
|
}
|
|
|
|
}
|
2006-09-02 16:19:00 +00:00
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2006-09-02 16:19:00 +00:00
|
|
|
/* Release the lock */
|
|
|
|
KiReleaseSpinLock(&DpcData->DpcLock);
|
|
|
|
|
|
|
|
/* Check if the DPC was inserted */
|
|
|
|
if (DpcInserted)
|
|
|
|
{
|
|
|
|
/* Check if this was SMP */
|
|
|
|
if (Prcb != CurrentPrcb)
|
|
|
|
{
|
|
|
|
/* It was, request and IPI */
|
|
|
|
KiIpiSendRequest(AFFINITY_MASK(Cpu), IPI_DPC);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* It wasn't, request an interrupt from HAL */
|
2005-03-12 19:45:37 +00:00
|
|
|
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
|
|
|
|
}
|
|
|
|
}
|
2006-09-02 16:19:00 +00:00
|
|
|
|
2005-05-09 01:38:29 +00:00
|
|
|
/* Lower IRQL */
|
2005-03-12 19:45:37 +00:00
|
|
|
KeLowerIrql(OldIrql);
|
2006-09-02 16:19:00 +00:00
|
|
|
return DpcConfigured;
|
1998-08-25 04:27:26 +00:00
|
|
|
}
|
|
|
|
|
2003-07-10 17:44:06 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
1998-08-25 04:27:26 +00:00
|
|
|
*/
|
2005-05-09 01:38:29 +00:00
|
|
|
BOOLEAN
|
2006-09-02 16:19:00 +00:00
|
|
|
NTAPI
|
|
|
|
KeRemoveQueueDpc(IN PKDPC Dpc)
|
1998-08-25 04:27:26 +00:00
|
|
|
{
|
2006-09-02 16:19:00 +00:00
|
|
|
PKDPC_DATA DpcData;
|
|
|
|
UCHAR DpcType;
|
|
|
|
ASSERT_DPC(Dpc);
|
|
|
|
|
|
|
|
/* Disable interrupts */
|
|
|
|
Ke386DisableInterrupts();
|
|
|
|
|
|
|
|
/* Get DPC data and type */
|
|
|
|
DpcType = Dpc->Type;
|
|
|
|
DpcData = Dpc->DpcData;
|
|
|
|
if (DpcData)
|
|
|
|
{
|
|
|
|
/* Acquire the DPC lock */
|
|
|
|
KiAcquireSpinLock(&DpcData->DpcLock);
|
|
|
|
|
|
|
|
/* Make sure that the data didn't change */
|
|
|
|
if (DpcData == Dpc->DpcData)
|
|
|
|
{
|
|
|
|
/* Remove the DPC */
|
|
|
|
DpcData->DpcQueueDepth--;
|
|
|
|
RemoveEntryList(&Dpc->DpcListEntry);
|
|
|
|
Dpc->DpcData = NULL;
|
|
|
|
}
|
2005-03-12 19:45:37 +00:00
|
|
|
|
2006-09-02 16:19:00 +00:00
|
|
|
/* Release the lock */
|
|
|
|
KiReleaseSpinLock(&DpcData->DpcLock);
|
2005-03-12 19:45:37 +00:00
|
|
|
}
|
2006-09-02 16:19:00 +00:00
|
|
|
|
|
|
|
/* Re-enable interrupts */
|
|
|
|
Ke386EnableInterrupts();
|
2004-11-21 06:51:18 +00:00
|
|
|
|
2005-03-12 19:45:37 +00:00
|
|
|
/* Return if the DPC was in the queue or not */
|
2006-09-02 16:19:00 +00:00
|
|
|
return DpcData ? TRUE : FALSE;
|
2004-11-21 06:51:18 +00:00
|
|
|
}
|
2004-10-17 15:39:30 +00:00
|
|
|
|
2004-11-21 06:51:18 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
VOID
|
2006-09-02 16:19:00 +00:00
|
|
|
NTAPI
|
2004-11-21 06:51:18 +00:00
|
|
|
KeFlushQueuedDpcs(VOID)
|
|
|
|
{
|
2006-09-02 16:19:00 +00:00
|
|
|
PAGED_CODE();
|
|
|
|
|
2005-03-12 19:45:37 +00:00
|
|
|
/* Request an interrupt if needed */
|
2006-09-02 16:19:00 +00:00
|
|
|
DPRINT1("%s - FIXME!!!\n", __FUNCTION__);
|
2005-03-12 19:45:37 +00:00
|
|
|
if (KeGetCurrentPrcb()->DpcData[0].DpcQueueDepth) HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
|
2004-11-21 06:51:18 +00:00
|
|
|
}
|
2004-10-31 17:02:31 +00:00
|
|
|
|
2004-11-21 06:51:18 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2005-05-09 01:38:29 +00:00
|
|
|
BOOLEAN
|
2006-09-02 16:19:00 +00:00
|
|
|
NTAPI
|
|
|
|
KeIsExecutingDpc(VOID)
|
2004-11-21 06:51:18 +00:00
|
|
|
{
|
2005-03-12 19:45:37 +00:00
|
|
|
/* Return if the Dpc Routine is active */
|
|
|
|
return KeGetCurrentPrcb()->DpcRoutineActive;
|
1998-08-25 04:27:26 +00:00
|
|
|
}
|
|
|
|
|
2000-07-01 18:27:03 +00:00
|
|
|
/*
|
2003-07-10 17:44:06 +00:00
|
|
|
* @implemented
|
2000-07-01 18:27:03 +00:00
|
|
|
*/
|
2005-05-09 01:38:29 +00:00
|
|
|
VOID
|
2006-09-02 16:19:00 +00:00
|
|
|
NTAPI
|
2005-03-12 19:45:37 +00:00
|
|
|
KeSetImportanceDpc (IN PKDPC Dpc,
|
2006-09-02 16:19:00 +00:00
|
|
|
IN KDPC_IMPORTANCE Importance)
|
2000-07-01 18:27:03 +00:00
|
|
|
{
|
2005-03-12 19:45:37 +00:00
|
|
|
/* Set the DPC Importance */
|
2006-09-02 16:19:00 +00:00
|
|
|
ASSERT_DPC(Dpc);
|
2005-03-12 19:45:37 +00:00
|
|
|
Dpc->Importance = Importance;
|
2000-07-01 18:27:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2005-03-12 19:45:37 +00:00
|
|
|
* @implemented
|
2000-07-01 18:27:03 +00:00
|
|
|
*/
|
2005-05-09 01:38:29 +00:00
|
|
|
VOID
|
2006-09-02 16:19:00 +00:00
|
|
|
NTAPI
|
2005-03-12 19:45:37 +00:00
|
|
|
KeSetTargetProcessorDpc(IN PKDPC Dpc,
|
|
|
|
IN CCHAR Number)
|
2000-07-01 18:27:03 +00:00
|
|
|
{
|
2006-09-02 16:19:00 +00:00
|
|
|
/* Set a target CPU */
|
|
|
|
ASSERT_DPC(Dpc);
|
|
|
|
Dpc->Number = Number + MAXIMUM_PROCESSORS;
|
2000-07-01 18:27:03 +00:00
|
|
|
}
|
|
|
|
|
1998-08-25 04:27:26 +00:00
|
|
|
/*
|
2005-05-09 01:38:29 +00:00
|
|
|
* FUNCTION:
|
2004-11-21 06:51:18 +00:00
|
|
|
* Called when a quantum end occurs to check if priority should be changed
|
|
|
|
* and wether a new thread should be dispatched.
|
|
|
|
* NOTES:
|
|
|
|
* Called when deleting a Driver.
|
1998-08-25 04:27:26 +00:00
|
|
|
*/
|
2005-03-12 19:45:37 +00:00
|
|
|
VOID
|
|
|
|
STDCALL
|
|
|
|
KiQuantumEnd(VOID)
|
1998-08-25 04:27:26 +00:00
|
|
|
{
|
2005-03-12 19:45:37 +00:00
|
|
|
PKPRCB Prcb;
|
|
|
|
PKTHREAD CurrentThread;
|
|
|
|
KIRQL OldIrql;
|
|
|
|
PKPROCESS Process;
|
|
|
|
KPRIORITY OldPriority;
|
|
|
|
KPRIORITY NewPriority;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-12 19:45:37 +00:00
|
|
|
/* Lock dispatcher, get current thread */
|
|
|
|
Prcb = KeGetCurrentPrcb();
|
|
|
|
CurrentThread = KeGetCurrentThread();
|
|
|
|
OldIrql = KeRaiseIrqlToSynchLevel();
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-12 19:45:37 +00:00
|
|
|
/* Get the Thread's Process */
|
|
|
|
Process = CurrentThread->ApcState.Process;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-12 19:45:37 +00:00
|
|
|
/* Set DPC Event if requested */
|
2006-05-10 17:47:44 +00:00
|
|
|
if (Prcb->DpcSetEventRequest)
|
|
|
|
{
|
|
|
|
KeSetEvent(&Prcb->DpcEvent, 0, 0);
|
2005-03-12 19:45:37 +00:00
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-12 19:45:37 +00:00
|
|
|
/* Check if Quantum expired */
|
|
|
|
if (CurrentThread->Quantum <= 0) {
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-05-05 22:40:05 +00:00
|
|
|
/* Reset the new Quantum */
|
|
|
|
CurrentThread->Quantum = CurrentThread->QuantumReset;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-12 19:45:37 +00:00
|
|
|
/* Calculate new priority */
|
|
|
|
OldPriority = CurrentThread->Priority;
|
|
|
|
if (OldPriority < LOW_REALTIME_PRIORITY) {
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-12 19:45:37 +00:00
|
|
|
/* Set the New Priority and add the Priority Decrement */
|
|
|
|
NewPriority = OldPriority - CurrentThread->PriorityDecrement - 1;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-12 19:45:37 +00:00
|
|
|
/* Don't go out of bounds */
|
|
|
|
if (NewPriority < CurrentThread->BasePriority) NewPriority = CurrentThread->BasePriority;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-12 19:45:37 +00:00
|
|
|
/* Reset the priority decrement */
|
|
|
|
CurrentThread->PriorityDecrement = 0;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-12 19:45:37 +00:00
|
|
|
/* Set a new priority if needed */
|
|
|
|
if (OldPriority != NewPriority) {
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-12 19:45:37 +00:00
|
|
|
/* Set new Priority */
|
2005-08-09 08:02:05 +00:00
|
|
|
BOOLEAN Dummy; /* <- This is a hack anyways... */
|
|
|
|
KiSetPriorityThread(CurrentThread, NewPriority, &Dummy);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-12 19:45:37 +00:00
|
|
|
} else {
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-12 19:45:37 +00:00
|
|
|
/* Queue new thread if none is already */
|
|
|
|
if (Prcb->NextThread == NULL) {
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-12 19:45:37 +00:00
|
|
|
/* FIXME: Schedule a New Thread, when ROS will have NT Scheduler */
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-12 19:45:37 +00:00
|
|
|
} else {
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-12 19:45:37 +00:00
|
|
|
/* Make the current thread non-premeptive if a new thread is queued */
|
|
|
|
CurrentThread->Preempted = FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-12 19:45:37 +00:00
|
|
|
} else {
|
|
|
|
/* Set the Quantum back to Maximum */
|
|
|
|
//if (CurrentThread->DisableQuantum) {
|
|
|
|
// CurrentThread->Quantum = MAX_QUANTUM;
|
|
|
|
//}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Dispatch the Thread */
|
|
|
|
KeLowerIrql(DISPATCH_LEVEL);
|
2005-04-18 15:49:57 +00:00
|
|
|
KiDispatchThread(Ready);
|
2005-05-09 01:38:29 +00:00
|
|
|
}
|
2004-11-21 06:51:18 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
2005-03-12 19:45:37 +00:00
|
|
|
*
|
2005-05-09 01:38:29 +00:00
|
|
|
* FUNCTION:
|
2005-02-28 17:40:15 +00:00
|
|
|
* Called whenever a system interrupt is generated at DISPATCH_LEVEL.
|
|
|
|
* It delivers queued DPCs and dispatches a new thread if need be.
|
|
|
|
*/
|
2005-03-12 19:45:37 +00:00
|
|
|
VOID
|
|
|
|
STDCALL
|
|
|
|
KiDispatchInterrupt(VOID)
|
2004-11-21 06:51:18 +00:00
|
|
|
{
|
2005-03-12 19:45:37 +00:00
|
|
|
PLIST_ENTRY DpcEntry;
|
|
|
|
PKDPC Dpc;
|
|
|
|
KIRQL OldIrql;
|
|
|
|
PKPRCB Prcb;
|
|
|
|
|
|
|
|
DPRINT("Dispatching Interrupts\n");
|
|
|
|
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
|
|
|
|
|
|
|
/* Set DPC Deliver to Active */
|
|
|
|
Prcb = KeGetCurrentPrcb();
|
|
|
|
|
|
|
|
if (Prcb->DpcData[0].DpcQueueDepth > 0) {
|
|
|
|
/* Raise IRQL */
|
|
|
|
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
2005-05-09 01:38:29 +00:00
|
|
|
#ifdef CONFIG_SMP
|
2005-03-12 19:45:37 +00:00
|
|
|
KiAcquireSpinLock(&Prcb->DpcData[0].DpcLock);
|
2004-11-21 06:51:18 +00:00
|
|
|
#endif
|
2005-03-12 19:45:37 +00:00
|
|
|
Prcb->DpcRoutineActive = TRUE;
|
|
|
|
|
|
|
|
DPRINT("&Prcb->DpcData[0].DpcListHead: %x\n", &Prcb->DpcData[0].DpcListHead);
|
|
|
|
/* Loop while we have entries */
|
|
|
|
while (!IsListEmpty(&Prcb->DpcData[0].DpcListHead)) {
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-12 19:45:37 +00:00
|
|
|
ASSERT(Prcb->DpcData[0].DpcQueueDepth > 0);
|
|
|
|
DPRINT("Queue Depth: %x\n", Prcb->DpcData[0].DpcQueueDepth);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-12 19:45:37 +00:00
|
|
|
/* Get the DPC call it */
|
|
|
|
DpcEntry = RemoveHeadList(&Prcb->DpcData[0].DpcListHead);
|
|
|
|
Dpc = CONTAINING_RECORD(DpcEntry, KDPC, DpcListEntry);
|
|
|
|
DPRINT("Dpc->DpcListEntry.Flink %x\n", Dpc->DpcListEntry.Flink);
|
|
|
|
Dpc->DpcData = NULL;
|
|
|
|
Prcb->DpcData[0].DpcQueueDepth--;
|
2005-01-05 19:25:49 +00:00
|
|
|
#ifdef CONFIG_SMP
|
2005-03-12 19:45:37 +00:00
|
|
|
KiReleaseSpinLock(&Prcb->DpcData[0].DpcLock);
|
2004-11-21 06:51:18 +00:00
|
|
|
#endif
|
2005-03-12 19:45:37 +00:00
|
|
|
/* Disable/Enabled Interrupts and Call the DPC */
|
|
|
|
KeLowerIrql(OldIrql);
|
|
|
|
DPRINT("Calling DPC: %x\n", Dpc);
|
|
|
|
Dpc->DeferredRoutine(Dpc,
|
|
|
|
Dpc->DeferredContext,
|
|
|
|
Dpc->SystemArgument1,
|
|
|
|
Dpc->SystemArgument2);
|
|
|
|
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-01-05 19:25:49 +00:00
|
|
|
#ifdef CONFIG_SMP
|
2005-03-12 19:45:37 +00:00
|
|
|
KiAcquireSpinLock(&Prcb->DpcData[0].DpcLock);
|
2005-05-09 01:38:29 +00:00
|
|
|
/*
|
2005-03-12 19:45:37 +00:00
|
|
|
* If the dpc routine drops the irql below DISPATCH_LEVEL,
|
2005-05-09 01:38:29 +00:00
|
|
|
* a thread switch can occur and after the next thread switch
|
2005-03-12 19:45:37 +00:00
|
|
|
* the execution may start on an other processor.
|
|
|
|
*/
|
|
|
|
if (Prcb != KeGetCurrentPrcb()) {
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-12 19:45:37 +00:00
|
|
|
Prcb->DpcRoutineActive = FALSE;
|
|
|
|
KiReleaseSpinLock(&Prcb->DpcData[0].DpcLock);
|
|
|
|
Prcb = KeGetCurrentPrcb();
|
|
|
|
KiAcquireSpinLock(&Prcb->DpcData[0].DpcLock);
|
|
|
|
Prcb->DpcRoutineActive = TRUE;
|
|
|
|
}
|
2004-11-21 06:51:18 +00:00
|
|
|
#endif
|
2005-03-12 19:45:37 +00:00
|
|
|
}
|
|
|
|
/* Clear DPC Flags */
|
|
|
|
Prcb->DpcRoutineActive = FALSE;
|
|
|
|
Prcb->DpcInterruptRequested = FALSE;
|
2005-01-05 19:25:49 +00:00
|
|
|
#ifdef CONFIG_SMP
|
2005-03-12 19:45:37 +00:00
|
|
|
KiReleaseSpinLock(&Prcb->DpcData[0].DpcLock);
|
2004-11-21 18:13:47 +00:00
|
|
|
#endif
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-12 19:45:37 +00:00
|
|
|
/* DPC Dispatching Ended, re-enable interrupts */
|
|
|
|
KeLowerIrql(OldIrql);
|
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-12 19:45:37 +00:00
|
|
|
DPRINT("Checking for Quantum End\n");
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-12 19:45:37 +00:00
|
|
|
/* If we have Quantum End, call the function */
|
|
|
|
if (Prcb->QuantumEnd) {
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-12 19:45:37 +00:00
|
|
|
Prcb->QuantumEnd = FALSE;
|
|
|
|
KiQuantumEnd();
|
|
|
|
}
|
1998-08-25 04:27:26 +00:00
|
|
|
}
|
|
|
|
|
2000-07-01 18:27:03 +00:00
|
|
|
/* EOF */
|