mirror of
https://github.com/reactos/reactos.git
synced 2024-11-20 06:15:26 +00:00
Alex Ionescu <ionucu@videotron.ca>
- Fixed formatting mess in ke/dpc.c (which I had made when I wrote it due to MSVC). - Add more comments where needed. - Properly Initialize a Threaded DPC. Thomas Weidenmueller <w3seek@reactos.com> - Use Prcb directly in KeInitDpc. svn path=/trunk/; revision=13975
This commit is contained in:
parent
b2a42182ef
commit
fd962e2f04
3 changed files with 347 additions and 307 deletions
|
@ -41,6 +41,7 @@ VOID KeSetGdtSelector(ULONG Entry, ULONG Value1, ULONG Value2);
|
||||||
struct _KTHREAD;
|
struct _KTHREAD;
|
||||||
struct _KIRQ_TRAPFRAME;
|
struct _KIRQ_TRAPFRAME;
|
||||||
struct _KPCR;
|
struct _KPCR;
|
||||||
|
struct _KPRCB;
|
||||||
struct _KEXCEPTION_FRAME;
|
struct _KEXCEPTION_FRAME;
|
||||||
|
|
||||||
#define IPI_REQUEST_FUNCTIONCALL 0
|
#define IPI_REQUEST_FUNCTIONCALL 0
|
||||||
|
@ -192,7 +193,7 @@ extern LARGE_INTEGER SystemBootTime;
|
||||||
VOID KeInitExceptions(VOID);
|
VOID KeInitExceptions(VOID);
|
||||||
VOID KeInitInterrupts(VOID);
|
VOID KeInitInterrupts(VOID);
|
||||||
VOID KeInitTimer(VOID);
|
VOID KeInitTimer(VOID);
|
||||||
VOID KeInitDpc(struct _KPCR* Pcr);
|
VOID KeInitDpc(struct _KPRCB* Prcb);
|
||||||
VOID KeInitDispatcher(VOID);
|
VOID KeInitDispatcher(VOID);
|
||||||
VOID KeInitializeDispatcher(VOID);
|
VOID KeInitializeDispatcher(VOID);
|
||||||
VOID KiInitializeSystemClock(VOID);
|
VOID KiInitializeSystemClock(VOID);
|
||||||
|
|
|
@ -24,22 +24,22 @@
|
||||||
/* TYPES *******************************************************************/
|
/* TYPES *******************************************************************/
|
||||||
|
|
||||||
#define MAX_QUANTUM 0x7F
|
#define MAX_QUANTUM 0x7F
|
||||||
/* GLOBALS ******************************************************************/
|
|
||||||
|
|
||||||
/* FUNCTIONS ****************************************************************/
|
/* FUNCTIONS ****************************************************************/
|
||||||
|
|
||||||
VOID INIT_FUNCTION
|
|
||||||
KeInitDpc(PKPCR Pcr)
|
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Initialize DPC handling
|
* FUNCTION: Initialize DPC handling
|
||||||
*/
|
*/
|
||||||
|
VOID
|
||||||
|
INIT_FUNCTION
|
||||||
|
KeInitDpc(PKPRCB Prcb)
|
||||||
{
|
{
|
||||||
InitializeListHead(&Pcr->PrcbData.DpcData[0].DpcListHead);
|
InitializeListHead(&Prcb->DpcData[0].DpcListHead);
|
||||||
KeInitializeEvent(Pcr->PrcbData.DpcEvent, 0, 0);
|
KeInitializeEvent(Prcb->DpcEvent, 0, 0);
|
||||||
KeInitializeSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
|
KeInitializeSpinLock(&Prcb->DpcData[0].DpcLock);
|
||||||
Pcr->PrcbData.MaximumDpcQueueDepth = 4;
|
Prcb->MaximumDpcQueueDepth = 4;
|
||||||
Pcr->PrcbData.MinimumDpcRate = 3;
|
Prcb->MinimumDpcRate = 3;
|
||||||
Pcr->PrcbData.DpcData[0].DpcQueueDepth = 0;
|
Prcb->DpcData[0].DpcQueueDepth = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -47,9 +47,9 @@ KeInitDpc(PKPCR Pcr)
|
||||||
*/
|
*/
|
||||||
VOID
|
VOID
|
||||||
STDCALL
|
STDCALL
|
||||||
KeInitializeThreadedDpc(PKDPC Dpc,
|
KeInitializeThreadedDpc(PKDPC Dpc,
|
||||||
PKDEFERRED_ROUTINE DeferredRoutine,
|
PKDEFERRED_ROUTINE DeferredRoutine,
|
||||||
PVOID DeferredContext)
|
PVOID DeferredContext)
|
||||||
/*
|
/*
|
||||||
* FUNCTION:
|
* FUNCTION:
|
||||||
* Initalizes a Threaded DPC and registers the DeferredRoutine for it.
|
* Initalizes a Threaded DPC and registers the DeferredRoutine for it.
|
||||||
|
@ -60,24 +60,18 @@ KeInitializeThreadedDpc(PKDPC Dpc,
|
||||||
* NOTE: Callers can be running at any IRQL.
|
* NOTE: Callers can be running at any IRQL.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
DPRINT("Threaded DPC Initializing: %x with Routine: %x\n", Dpc, DeferredRoutine);
|
DPRINT("Threaded DPC Initializing: %x with Routine: %x\n", Dpc, DeferredRoutine);
|
||||||
//Dpc->Type = KThreadedDpc;
|
Dpc->Type = ThreadedDpcObject;
|
||||||
Dpc->Number= 0;
|
Dpc->Number= 0;
|
||||||
Dpc->Importance= MediumImportance;
|
Dpc->Importance= MediumImportance;
|
||||||
Dpc->DeferredRoutine = DeferredRoutine;
|
Dpc->DeferredRoutine = DeferredRoutine;
|
||||||
Dpc->DeferredContext = DeferredContext;
|
Dpc->DeferredContext = DeferredContext;
|
||||||
Dpc->DpcData = NULL;
|
Dpc->DpcData = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*
|
||||||
VOID
|
|
||||||
STDCALL
|
|
||||||
KeInitializeDpc (PKDPC Dpc,
|
|
||||||
PKDEFERRED_ROUTINE DeferredRoutine,
|
|
||||||
PVOID DeferredContext)
|
|
||||||
/*
|
|
||||||
* FUNCTION:
|
* FUNCTION:
|
||||||
* Initalizes a DPC and registers the DeferredRoutine for it.
|
* Initalizes a DPC and registers the DeferredRoutine for it.
|
||||||
* ARGUMENTS:
|
* ARGUMENTS:
|
||||||
|
@ -86,24 +80,24 @@ KeInitializeDpc (PKDPC Dpc,
|
||||||
* DeferredContext = Parameter to be passed to the callback routine.
|
* DeferredContext = Parameter to be passed to the callback routine.
|
||||||
* NOTE: Callers can be running at any IRQL.
|
* NOTE: Callers can be running at any IRQL.
|
||||||
*/
|
*/
|
||||||
|
VOID
|
||||||
|
STDCALL
|
||||||
|
KeInitializeDpc(PKDPC Dpc,
|
||||||
|
PKDEFERRED_ROUTINE DeferredRoutine,
|
||||||
|
PVOID DeferredContext)
|
||||||
{
|
{
|
||||||
DPRINT("DPC Initializing: %x with Routine: %x\n", Dpc, DeferredRoutine);
|
DPRINT("DPC Initializing: %x with Routine: %x\n", Dpc, DeferredRoutine);
|
||||||
Dpc->Type = DpcObject;
|
Dpc->Type = DpcObject;
|
||||||
Dpc->Number= 0;
|
Dpc->Number= 0;
|
||||||
Dpc->Importance= MediumImportance;
|
Dpc->Importance= MediumImportance;
|
||||||
Dpc->DeferredRoutine = DeferredRoutine;
|
Dpc->DeferredRoutine = DeferredRoutine;
|
||||||
Dpc->DeferredContext = DeferredContext;
|
Dpc->DeferredContext = DeferredContext;
|
||||||
Dpc->DpcData = NULL;
|
Dpc->DpcData = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*
|
||||||
BOOLEAN STDCALL
|
|
||||||
KeInsertQueueDpc (PKDPC Dpc,
|
|
||||||
PVOID SystemArgument1,
|
|
||||||
PVOID SystemArgument2)
|
|
||||||
/*
|
|
||||||
* FUNCTION:
|
* FUNCTION:
|
||||||
* Queues a DPC for execution when the IRQL of a processor
|
* Queues a DPC for execution when the IRQL of a processor
|
||||||
* drops below DISPATCH_LEVEL
|
* drops below DISPATCH_LEVEL
|
||||||
|
@ -155,124 +149,141 @@ KeInsertQueueDpc (PKDPC Dpc,
|
||||||
* is greater that the target depth or the minimum DPC rate is less than the
|
* is greater that the target depth or the minimum DPC rate is less than the
|
||||||
* target rate.
|
* target rate.
|
||||||
*/
|
*/
|
||||||
|
BOOLEAN
|
||||||
|
STDCALL
|
||||||
|
KeInsertQueueDpc(PKDPC Dpc,
|
||||||
|
PVOID SystemArgument1,
|
||||||
|
PVOID SystemArgument2)
|
||||||
{
|
{
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
PKPCR Pcr;
|
PKPRCB Prcb;
|
||||||
|
|
||||||
DPRINT("KeInsertQueueDpc(DPC %x, SystemArgument1 %x, SystemArgument2 %x)\n",
|
DPRINT("KeInsertQueueDpc(DPC %x, SystemArgument1 %x, SystemArgument2 %x)\n",
|
||||||
Dpc, SystemArgument1, SystemArgument2);
|
Dpc, SystemArgument1, SystemArgument2);
|
||||||
|
|
||||||
/* Check IRQL and Raise it to HIGH_LEVEL */
|
/* Check IRQL and Raise it to HIGH_LEVEL */
|
||||||
ASSERT(KeGetCurrentIrql()>=DISPATCH_LEVEL);
|
ASSERT(KeGetCurrentIrql()>=DISPATCH_LEVEL);
|
||||||
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
||||||
|
|
||||||
/* Check if this is a Thread DPC, which we don't support (yet) */
|
/* Check if this is a Thread DPC, which we don't support (yet) */
|
||||||
//if (Dpc->Type == KThreadedDpc) {
|
if (Dpc->Type == ThreadedDpcObject) {
|
||||||
// return FALSE;
|
return FALSE;
|
||||||
// KeLowerIrql(OldIrql);
|
KeLowerIrql(OldIrql);
|
||||||
//}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
/* Get the right PCR for this CPU */
|
/* Get the right PCR for this CPU */
|
||||||
if (Dpc->Number >= MAXIMUM_PROCESSORS) {
|
if (Dpc->Number >= MAXIMUM_PROCESSORS) {
|
||||||
ASSERT (Dpc->Number - MAXIMUM_PROCESSORS < KeNumberProcessors);
|
|
||||||
Pcr = (PKPCR)(KPCR_BASE + (Dpc->Number - MAXIMUM_PROCESSORS) * PAGE_SIZE);
|
ASSERT (Dpc->Number - MAXIMUM_PROCESSORS < KeNumberProcessors);
|
||||||
} else {
|
Prcb = ((PKPCR)((ULONG_PTR)KPCR_BASE + ((Dpc->Number - MAXIMUM_PROCESSORS) * PAGE_SIZE)))->Prcb;
|
||||||
ASSERT (Dpc->Number < KeNumberProcessors);
|
|
||||||
Pcr = KeGetCurrentKPCR();
|
} else {
|
||||||
Dpc->Number = KeGetCurrentProcessorNumber();
|
|
||||||
}
|
ASSERT (Dpc->Number < KeNumberProcessors);
|
||||||
KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
|
Prcb = KeGetCurrentPrcb();
|
||||||
|
Dpc->Number = KeGetCurrentProcessorNumber();
|
||||||
|
}
|
||||||
|
|
||||||
|
KiAcquireSpinLock(&Prcb->DpcData[0].DpcLock);
|
||||||
#else
|
#else
|
||||||
Pcr = (PKPCR)KPCR_BASE;
|
Prcb = ((PKPCR)KPCR_BASE)->Prcb;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Get the DPC Data */
|
/* Get the DPC Data */
|
||||||
if (InterlockedCompareExchangeUL(&Dpc->DpcData, &Pcr->PrcbData.DpcData[0].DpcLock, 0)) {
|
if (InterlockedCompareExchangeUL(&Dpc->DpcData, &Prcb->DpcData[0].DpcLock, 0)) {
|
||||||
DPRINT("DPC Already Inserted");
|
|
||||||
|
DPRINT("DPC Already Inserted");
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
|
KiReleaseSpinLock(&Prcb->DpcData[0].DpcLock);
|
||||||
#endif
|
#endif
|
||||||
KeLowerIrql(OldIrql);
|
KeLowerIrql(OldIrql);
|
||||||
return(FALSE);
|
return(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure the lists are free if the Queue is 0 */
|
/* Make sure the lists are free if the Queue is 0 */
|
||||||
if (Pcr->PrcbData.DpcData[0].DpcQueueDepth == 0) {
|
if (Prcb->DpcData[0].DpcQueueDepth == 0) {
|
||||||
ASSERT(IsListEmpty(&Pcr->PrcbData.DpcData[0].DpcListHead));
|
|
||||||
} else {
|
ASSERT(IsListEmpty(&Prcb->DpcData[0].DpcListHead));
|
||||||
ASSERT(!IsListEmpty(&Pcr->PrcbData.DpcData[0].DpcListHead));
|
} else {
|
||||||
}
|
|
||||||
|
ASSERT(!IsListEmpty(&Prcb->DpcData[0].DpcListHead));
|
||||||
|
}
|
||||||
|
|
||||||
/* Now we can play with the DPC safely */
|
/* Now we can play with the DPC safely */
|
||||||
Dpc->SystemArgument1=SystemArgument1;
|
Dpc->SystemArgument1=SystemArgument1;
|
||||||
Dpc->SystemArgument2=SystemArgument2;
|
Dpc->SystemArgument2=SystemArgument2;
|
||||||
Pcr->PrcbData.DpcData[0].DpcQueueDepth++;
|
Prcb->DpcData[0].DpcQueueDepth++;
|
||||||
Pcr->PrcbData.DpcData[0].DpcCount++;
|
Prcb->DpcData[0].DpcCount++;
|
||||||
|
|
||||||
/* Insert the DPC into the list. HighImportance DPCs go at the beginning */
|
/* Insert the DPC into the list. HighImportance DPCs go at the beginning */
|
||||||
if (Dpc->Importance == HighImportance) {
|
if (Dpc->Importance == HighImportance) {
|
||||||
InsertHeadList(&Pcr->PrcbData.DpcData[0].DpcListHead, &Dpc->DpcListEntry);
|
|
||||||
} else {
|
InsertHeadList(&Prcb->DpcData[0].DpcListHead, &Dpc->DpcListEntry);
|
||||||
InsertTailList(&Pcr->PrcbData.DpcData[0].DpcListHead, &Dpc->DpcListEntry);
|
} else {
|
||||||
}
|
|
||||||
DPRINT("New DPC Added. Dpc->DpcListEntry.Flink %x\n", Dpc->DpcListEntry.Flink);
|
InsertTailList(&Prcb->DpcData[0].DpcListHead, &Dpc->DpcListEntry);
|
||||||
|
}
|
||||||
|
DPRINT("New DPC Added. Dpc->DpcListEntry.Flink %x\n", Dpc->DpcListEntry.Flink);
|
||||||
|
|
||||||
/* Make sure a DPC isn't executing already and respect rules outlined above. */
|
/* Make sure a DPC isn't executing already and respect rules outlined above. */
|
||||||
if ((!Pcr->PrcbData.DpcRoutineActive) && (!Pcr->PrcbData.DpcInterruptRequested)) {
|
if ((!Prcb->DpcRoutineActive) && (!Prcb->DpcInterruptRequested)) {
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
/* Check if this is the same CPU */
|
/* Check if this is the same CPU */
|
||||||
if (Pcr != KeGetCurrentKPCR()) {
|
if (Prcb != KeGetCurrentPrcb()) {
|
||||||
/* Send IPI if High Importance */
|
|
||||||
if ((Dpc->Importance == HighImportance) ||
|
/* Send IPI if High Importance */
|
||||||
(Pcr->PrcbData.DpcData[0].DpcQueueDepth >= Pcr->PrcbData.MaximumDpcQueueDepth)) {
|
if ((Dpc->Importance == HighImportance) ||
|
||||||
if (Dpc->Number >= MAXIMUM_PROCESSORS) {
|
(Prcb->DpcData[0].DpcQueueDepth >= Prcb->MaximumDpcQueueDepth)) {
|
||||||
KiIpiSendRequest(1 << (Dpc->Number - MAXIMUM_PROCESSORS), IPI_REQUEST_DPC);
|
|
||||||
} else {
|
if (Dpc->Number >= MAXIMUM_PROCESSORS) {
|
||||||
KiIpiSendRequest(1 << Dpc->Number, IPI_REQUEST_DPC);
|
|
||||||
}
|
KiIpiSendRequest(1 << (Dpc->Number - MAXIMUM_PROCESSORS), IPI_REQUEST_DPC);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
KiIpiSendRequest(1 << Dpc->Number, IPI_REQUEST_DPC);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Request an Interrupt only if the DPC isn't low priority */
|
|
||||||
if ((Dpc->Importance != LowImportance) ||
|
/* Request an Interrupt only if the DPC isn't low priority */
|
||||||
(Pcr->PrcbData.DpcData[0].DpcQueueDepth >= Pcr->PrcbData.MaximumDpcQueueDepth) ||
|
if ((Dpc->Importance != LowImportance) ||
|
||||||
(Pcr->PrcbData.DpcRequestRate < Pcr->PrcbData.MinimumDpcRate)) {
|
(Prcb->DpcData[0].DpcQueueDepth >= Prcb->MaximumDpcQueueDepth) ||
|
||||||
|
(Prcb->DpcRequestRate < Prcb->MinimumDpcRate)) {
|
||||||
/* Request Interrupt */
|
|
||||||
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
|
/* Request Interrupt */
|
||||||
Pcr->PrcbData.DpcInterruptRequested = TRUE;
|
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
|
||||||
}
|
Prcb->DpcInterruptRequested = TRUE;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
DPRINT("Requesting Interrupt. Importance: %x. QueueDepth: %x. MaxQueue: %x . RequestRate: %x. MinRate:%x \n", Dpc->Importance, Pcr->PrcbData.DpcData[0].DpcQueueDepth, Pcr->PrcbData.MaximumDpcQueueDepth, Pcr->PrcbData.DpcRequestRate, Pcr->PrcbData.MinimumDpcRate);
|
DPRINT("Requesting Interrupt. Importance: %x. QueueDepth: %x. MaxQueue: %x . RequestRate: %x. MinRate:%x \n", Dpc->Importance, Prcb->DpcData[0].DpcQueueDepth, Prcb->MaximumDpcQueueDepth, Prcb->DpcRequestRate, Prcb->MinimumDpcRate);
|
||||||
/* Request an Interrupt only if the DPC isn't low priority */
|
|
||||||
if ((Dpc->Importance != LowImportance) ||
|
/* Request an Interrupt only if the DPC isn't low priority */
|
||||||
(Pcr->PrcbData.DpcData[0].DpcQueueDepth >= Pcr->PrcbData.MaximumDpcQueueDepth) ||
|
if ((Dpc->Importance != LowImportance) ||
|
||||||
(Pcr->PrcbData.DpcRequestRate < Pcr->PrcbData.MinimumDpcRate)) {
|
(Prcb->DpcData[0].DpcQueueDepth >= Prcb->MaximumDpcQueueDepth) ||
|
||||||
|
(Prcb->DpcRequestRate < Prcb->MinimumDpcRate)) {
|
||||||
/* Request Interrupt */
|
|
||||||
DPRINT("Requesting Interrupt\n");
|
/* Request Interrupt */
|
||||||
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
|
DPRINT("Requesting Interrupt\n");
|
||||||
Pcr->PrcbData.DpcInterruptRequested = TRUE;
|
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
|
||||||
}
|
Prcb->DpcInterruptRequested = TRUE;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
|
KiReleaseSpinLock(&Prcb->DpcData[0].DpcLock);
|
||||||
#endif
|
#endif
|
||||||
/* Lower IRQL */
|
/* Lower IRQL */
|
||||||
KeLowerIrql(OldIrql);
|
KeLowerIrql(OldIrql);
|
||||||
return(TRUE);
|
return(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*
|
||||||
BOOLEAN STDCALL
|
|
||||||
KeRemoveQueueDpc (PKDPC Dpc)
|
|
||||||
/*
|
|
||||||
* FUNCTION:
|
* FUNCTION:
|
||||||
* Removes DPC object from the system dpc queue
|
* Removes DPC object from the system dpc queue
|
||||||
* ARGUMENTS:
|
* ARGUMENTS:
|
||||||
|
@ -281,33 +292,36 @@ KeRemoveQueueDpc (PKDPC Dpc)
|
||||||
* TRUE if the DPC was in the queue
|
* TRUE if the DPC was in the queue
|
||||||
* FALSE otherwise
|
* FALSE otherwise
|
||||||
*/
|
*/
|
||||||
|
BOOLEAN
|
||||||
|
STDCALL
|
||||||
|
KeRemoveQueueDpc(PKDPC Dpc)
|
||||||
{
|
{
|
||||||
BOOLEAN WasInQueue;
|
BOOLEAN WasInQueue;
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
|
|
||||||
/* Raise IRQL */
|
/* Raise IRQL */
|
||||||
DPRINT("Removing DPC: %x\n", Dpc);
|
DPRINT("Removing DPC: %x\n", Dpc);
|
||||||
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
KiAcquireSpinLock(&((PKDPC_DATA)Dpc->DpcData)->DpcLock);
|
KiAcquireSpinLock(&((PKDPC_DATA)Dpc->DpcData)->DpcLock);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* First make sure the DPC lock isn't being held */
|
/* First make sure the DPC lock isn't being held */
|
||||||
WasInQueue = Dpc->DpcData ? TRUE : FALSE;
|
WasInQueue = Dpc->DpcData ? TRUE : FALSE;
|
||||||
if (Dpc->DpcData) {
|
if (Dpc->DpcData) {
|
||||||
|
|
||||||
/* Remove the DPC */
|
/* Remove the DPC */
|
||||||
((PKDPC_DATA)Dpc->DpcData)->DpcQueueDepth--;
|
((PKDPC_DATA)Dpc->DpcData)->DpcQueueDepth--;
|
||||||
RemoveEntryList(&Dpc->DpcListEntry);
|
RemoveEntryList(&Dpc->DpcListEntry);
|
||||||
|
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
KiReleaseSpinLock(&((PKDPC_DATA)Dpc->DpcData)->DpcLock);
|
KiReleaseSpinLock(&((PKDPC_DATA)Dpc->DpcData)->DpcLock);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Return if the DPC was in the queue or not */
|
/* Return if the DPC was in the queue or not */
|
||||||
KeLowerIrql(OldIrql);
|
KeLowerIrql(OldIrql);
|
||||||
return WasInQueue;
|
return WasInQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -323,7 +337,8 @@ KeFlushQueuedDpcs(VOID)
|
||||||
* Called when deleting a Driver.
|
* Called when deleting a Driver.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
if (KeGetCurrentKPCR()->PrcbData.DpcData[0].DpcQueueDepth) HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
|
/* Request an interrupt if needed */
|
||||||
|
if (KeGetCurrentPrcb()->DpcData[0].DpcQueueDepth) HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -332,10 +347,11 @@ KeFlushQueuedDpcs(VOID)
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
STDCALL
|
STDCALL
|
||||||
KeIsExecutingDpc(
|
KeIsExecutingDpc(
|
||||||
VOID
|
VOID
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return KeGetCurrentKPCR()->PrcbData.DpcRoutineActive;
|
/* Return if the Dpc Routine is active */
|
||||||
|
return KeGetCurrentPrcb()->DpcRoutineActive;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -349,39 +365,41 @@ KeIsExecutingDpc(
|
||||||
*/
|
*/
|
||||||
VOID
|
VOID
|
||||||
STDCALL
|
STDCALL
|
||||||
KeSetImportanceDpc (IN PKDPC Dpc,
|
KeSetImportanceDpc (IN PKDPC Dpc,
|
||||||
IN KDPC_IMPORTANCE Importance)
|
IN KDPC_IMPORTANCE Importance)
|
||||||
{
|
{
|
||||||
Dpc->Importance = Importance;
|
/* Set the DPC Importance */
|
||||||
|
Dpc->Importance = Importance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
* @implemented
|
||||||
|
*
|
||||||
* FUNCTION: Specifies on which processor the DPC will run
|
* FUNCTION: Specifies on which processor the DPC will run
|
||||||
* ARGUMENTS:
|
* ARGUMENTS:
|
||||||
* Dpc = Initalizes DPC
|
* Dpc = Initalizes DPC
|
||||||
* Number = Processor number
|
* Number = Processor number
|
||||||
* RETURNS: None
|
* RETURNS: None
|
||||||
*
|
|
||||||
* @implemented
|
|
||||||
*/
|
*/
|
||||||
VOID STDCALL
|
VOID
|
||||||
KeSetTargetProcessorDpc (IN PKDPC Dpc,
|
STDCALL
|
||||||
IN CCHAR Number)
|
KeSetTargetProcessorDpc(IN PKDPC Dpc,
|
||||||
|
IN CCHAR Number)
|
||||||
{
|
{
|
||||||
if (Number >= MAXIMUM_PROCESSORS)
|
/* Check how many CPUs are on the system */
|
||||||
{
|
if (Number >= MAXIMUM_PROCESSORS) {
|
||||||
Dpc->Number = 0;
|
|
||||||
}
|
/* No CPU Number */
|
||||||
else
|
Dpc->Number = 0;
|
||||||
{
|
|
||||||
ASSERT(Number < KeNumberProcessors);
|
} else {
|
||||||
Dpc->Number = Number + MAXIMUM_PROCESSORS;
|
|
||||||
}
|
/* Set the Number Specified */
|
||||||
|
ASSERT(Number < KeNumberProcessors);
|
||||||
|
Dpc->Number = Number + MAXIMUM_PROCESSORS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
|
||||||
STDCALL
|
|
||||||
KiQuantumEnd(VOID)
|
|
||||||
/*
|
/*
|
||||||
* FUNCTION:
|
* FUNCTION:
|
||||||
* Called when a quantum end occurs to check if priority should be changed
|
* Called when a quantum end occurs to check if priority should be changed
|
||||||
|
@ -389,152 +407,173 @@ KiQuantumEnd(VOID)
|
||||||
* NOTES:
|
* NOTES:
|
||||||
* Called when deleting a Driver.
|
* Called when deleting a Driver.
|
||||||
*/
|
*/
|
||||||
|
VOID
|
||||||
|
STDCALL
|
||||||
|
KiQuantumEnd(VOID)
|
||||||
{
|
{
|
||||||
PKPRCB Prcb;
|
PKPRCB Prcb;
|
||||||
PKTHREAD CurrentThread;
|
PKTHREAD CurrentThread;
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
PKPROCESS Process;
|
PKPROCESS Process;
|
||||||
KPRIORITY OldPriority;
|
KPRIORITY OldPriority;
|
||||||
KPRIORITY NewPriority;
|
KPRIORITY NewPriority;
|
||||||
|
|
||||||
/* Lock dispatcher, get current thread */
|
/* Lock dispatcher, get current thread */
|
||||||
Prcb = &KeGetCurrentKPCR()->PrcbData;
|
Prcb = KeGetCurrentPrcb();
|
||||||
CurrentThread = KeGetCurrentThread();
|
CurrentThread = KeGetCurrentThread();
|
||||||
OldIrql = KeRaiseIrqlToSynchLevel();
|
OldIrql = KeRaiseIrqlToSynchLevel();
|
||||||
|
|
||||||
/* Get the Thread's Process */
|
/* Get the Thread's Process */
|
||||||
Process = CurrentThread->ApcState.Process;
|
Process = CurrentThread->ApcState.Process;
|
||||||
|
|
||||||
/* Set DPC Event if requested */
|
/* Set DPC Event if requested */
|
||||||
if (Prcb->DpcSetEventRequest) {
|
if (Prcb->DpcSetEventRequest) {
|
||||||
KeSetEvent(Prcb->DpcEvent, 0, 0);
|
KeSetEvent(Prcb->DpcEvent, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if Quantum expired */
|
/* Check if Quantum expired */
|
||||||
if (CurrentThread->Quantum <= 0) {
|
if (CurrentThread->Quantum <= 0) {
|
||||||
/* Set the new Quantum */
|
/* Set the new Quantum */
|
||||||
CurrentThread->Quantum = Process->ThreadQuantum;
|
CurrentThread->Quantum = Process->ThreadQuantum;
|
||||||
|
|
||||||
/* Calculate new priority */
|
/* Calculate new priority */
|
||||||
OldPriority = CurrentThread->Priority;
|
OldPriority = CurrentThread->Priority;
|
||||||
if (OldPriority < LOW_REALTIME_PRIORITY) {
|
if (OldPriority < LOW_REALTIME_PRIORITY) {
|
||||||
NewPriority = OldPriority - CurrentThread->PriorityDecrement - 1;
|
|
||||||
if (NewPriority < CurrentThread->BasePriority) {
|
/* Set the New Priority and add the Priority Decrement */
|
||||||
NewPriority = CurrentThread->BasePriority;
|
NewPriority = OldPriority - CurrentThread->PriorityDecrement - 1;
|
||||||
}
|
|
||||||
CurrentThread->PriorityDecrement = 0;
|
/* Don't go out of bounds */
|
||||||
if (OldPriority != NewPriority) {
|
if (NewPriority < CurrentThread->BasePriority) NewPriority = CurrentThread->BasePriority;
|
||||||
/* Set new Priority */
|
|
||||||
CurrentThread->Priority = NewPriority;
|
/* Reset the priority decrement */
|
||||||
} else {
|
CurrentThread->PriorityDecrement = 0;
|
||||||
/* Queue new thread if none is already */
|
|
||||||
if (Prcb->NextThread == NULL) {
|
/* Set a new priority if needed */
|
||||||
/* FIXME: Schedule a New Thread, when ROS will have NT Scheduler */
|
if (OldPriority != NewPriority) {
|
||||||
} else {
|
|
||||||
/* Make the current thread non-premeptive if a new thread is queued */
|
/* Set new Priority */
|
||||||
CurrentThread->Preempted = FALSE;
|
CurrentThread->Priority = NewPriority;
|
||||||
}
|
|
||||||
}
|
} else {
|
||||||
} else {
|
|
||||||
/* Set the Quantum back to Maximum */
|
/* Queue new thread if none is already */
|
||||||
//if (CurrentThread->DisableQuantum) {
|
if (Prcb->NextThread == NULL) {
|
||||||
// CurrentThread->Quantum = MAX_QUANTUM;
|
|
||||||
//}
|
/* FIXME: Schedule a New Thread, when ROS will have NT Scheduler */
|
||||||
}
|
|
||||||
}
|
} else {
|
||||||
/* Dispatch the Thread */
|
|
||||||
KeLowerIrql(DISPATCH_LEVEL);
|
/* Make the current thread non-premeptive if a new thread is queued */
|
||||||
PsDispatchThread(THREAD_STATE_READY);
|
CurrentThread->Preempted = FALSE;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/* Set the Quantum back to Maximum */
|
||||||
|
//if (CurrentThread->DisableQuantum) {
|
||||||
|
// CurrentThread->Quantum = MAX_QUANTUM;
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dispatch the Thread */
|
||||||
|
KeLowerIrql(DISPATCH_LEVEL);
|
||||||
|
PsDispatchThread(THREAD_STATE_READY);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*
|
||||||
VOID
|
|
||||||
STDCALL
|
|
||||||
KiDispatchInterrupt(VOID)
|
|
||||||
/*
|
|
||||||
* FUNCTION:
|
* FUNCTION:
|
||||||
* Called whenever a system interrupt is generated at DISPATCH_LEVEL.
|
* Called whenever a system interrupt is generated at DISPATCH_LEVEL.
|
||||||
* It delivers queued DPCs and dispatches a new thread if need be.
|
* It delivers queued DPCs and dispatches a new thread if need be.
|
||||||
*/
|
*/
|
||||||
|
VOID
|
||||||
|
STDCALL
|
||||||
|
KiDispatchInterrupt(VOID)
|
||||||
{
|
{
|
||||||
PLIST_ENTRY DpcEntry;
|
PLIST_ENTRY DpcEntry;
|
||||||
PKDPC Dpc;
|
PKDPC Dpc;
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
PKPCR Pcr;
|
PKPRCB Prcb;
|
||||||
|
|
||||||
DPRINT("Dispatching Interrupts\n");
|
DPRINT("Dispatching Interrupts\n");
|
||||||
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
||||||
|
|
||||||
/* Set DPC Deliver to Active */
|
/* Set DPC Deliver to Active */
|
||||||
Pcr = KeGetCurrentKPCR();
|
Prcb = KeGetCurrentPrcb();
|
||||||
|
|
||||||
if (Pcr->PrcbData.DpcData[0].DpcQueueDepth > 0) {
|
if (Prcb->DpcData[0].DpcQueueDepth > 0) {
|
||||||
/* Raise IRQL */
|
/* Raise IRQL */
|
||||||
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
|
KiAcquireSpinLock(&Prcb->DpcData[0].DpcLock);
|
||||||
#endif
|
#endif
|
||||||
Pcr->PrcbData.DpcRoutineActive = TRUE;
|
Prcb->DpcRoutineActive = TRUE;
|
||||||
|
|
||||||
DPRINT("&Pcr->PrcbData.DpcData[0].DpcListHead: %x\n", &Pcr->PrcbData.DpcData[0].DpcListHead);
|
DPRINT("&Prcb->DpcData[0].DpcListHead: %x\n", &Prcb->DpcData[0].DpcListHead);
|
||||||
/* Loop while we have entries */
|
/* Loop while we have entries */
|
||||||
while (!IsListEmpty(&Pcr->PrcbData.DpcData[0].DpcListHead)) {
|
while (!IsListEmpty(&Prcb->DpcData[0].DpcListHead)) {
|
||||||
ASSERT(Pcr->PrcbData.DpcData[0].DpcQueueDepth > 0);
|
|
||||||
DPRINT("Queue Depth: %x\n", Pcr->PrcbData.DpcData[0].DpcQueueDepth);
|
ASSERT(Prcb->DpcData[0].DpcQueueDepth > 0);
|
||||||
|
DPRINT("Queue Depth: %x\n", Prcb->DpcData[0].DpcQueueDepth);
|
||||||
/* Get the DPC call it */
|
|
||||||
DpcEntry = RemoveHeadList(&Pcr->PrcbData.DpcData[0].DpcListHead);
|
/* Get the DPC call it */
|
||||||
Dpc = CONTAINING_RECORD(DpcEntry, KDPC, DpcListEntry);
|
DpcEntry = RemoveHeadList(&Prcb->DpcData[0].DpcListHead);
|
||||||
DPRINT("Dpc->DpcListEntry.Flink %x\n", Dpc->DpcListEntry.Flink);
|
Dpc = CONTAINING_RECORD(DpcEntry, KDPC, DpcListEntry);
|
||||||
Dpc->DpcData = NULL;
|
DPRINT("Dpc->DpcListEntry.Flink %x\n", Dpc->DpcListEntry.Flink);
|
||||||
Pcr->PrcbData.DpcData[0].DpcQueueDepth--;
|
Dpc->DpcData = NULL;
|
||||||
|
Prcb->DpcData[0].DpcQueueDepth--;
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
|
KiReleaseSpinLock(&Prcb->DpcData[0].DpcLock);
|
||||||
#endif
|
#endif
|
||||||
/* Disable/Enabled Interrupts and Call the DPC */
|
/* Disable/Enabled Interrupts and Call the DPC */
|
||||||
KeLowerIrql(OldIrql);
|
KeLowerIrql(OldIrql);
|
||||||
DPRINT("Calling DPC: %x\n", Dpc);
|
DPRINT("Calling DPC: %x\n", Dpc);
|
||||||
Dpc->DeferredRoutine(Dpc,
|
Dpc->DeferredRoutine(Dpc,
|
||||||
Dpc->DeferredContext,
|
Dpc->DeferredContext,
|
||||||
Dpc->SystemArgument1,
|
Dpc->SystemArgument1,
|
||||||
Dpc->SystemArgument2);
|
Dpc->SystemArgument2);
|
||||||
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
|
KiAcquireSpinLock(&Prcb->DpcData[0].DpcLock);
|
||||||
/*
|
/*
|
||||||
* If the dpc routine drops the irql below DISPATCH_LEVEL,
|
* If the dpc routine drops the irql below DISPATCH_LEVEL,
|
||||||
* a thread switch can occur and after the next thread switch
|
* a thread switch can occur and after the next thread switch
|
||||||
* the execution may start on an other processor.
|
* the execution may start on an other processor.
|
||||||
*/
|
*/
|
||||||
if (Pcr != KeGetCurrentKPCR()) {
|
if (Prcb != KeGetCurrentPrcb()) {
|
||||||
Pcr->PrcbData.DpcRoutineActive = FALSE;
|
|
||||||
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
|
Prcb->DpcRoutineActive = FALSE;
|
||||||
Pcr = KeGetCurrentKPCR();
|
KiReleaseSpinLock(&Prcb->DpcData[0].DpcLock);
|
||||||
KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
|
Prcb = KeGetCurrentPrcb();
|
||||||
Pcr->PrcbData.DpcRoutineActive = TRUE;
|
KiAcquireSpinLock(&Prcb->DpcData[0].DpcLock);
|
||||||
}
|
Prcb->DpcRoutineActive = TRUE;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
/* Clear DPC Flags */
|
/* Clear DPC Flags */
|
||||||
Pcr->PrcbData.DpcRoutineActive = FALSE;
|
Prcb->DpcRoutineActive = FALSE;
|
||||||
Pcr->PrcbData.DpcInterruptRequested = FALSE;
|
Prcb->DpcInterruptRequested = FALSE;
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
|
KiReleaseSpinLock(&Prcb->DpcData[0].DpcLock);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* DPC Dispatching Ended, re-enable interrupts */
|
/* DPC Dispatching Ended, re-enable interrupts */
|
||||||
KeLowerIrql(OldIrql);
|
KeLowerIrql(OldIrql);
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINT("Checking for Quantum End\n");
|
DPRINT("Checking for Quantum End\n");
|
||||||
/* If we have Quantum End, call the function */
|
|
||||||
if (Pcr->PrcbData.QuantumEnd) {
|
/* If we have Quantum End, call the function */
|
||||||
Pcr->PrcbData.QuantumEnd = FALSE;
|
if (Prcb->QuantumEnd) {
|
||||||
KiQuantumEnd();
|
|
||||||
}
|
Prcb->QuantumEnd = FALSE;
|
||||||
|
KiQuantumEnd();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -187,7 +187,7 @@ KeApplicationProcessorInit(VOID)
|
||||||
/* Check FPU/MMX/SSE support. */
|
/* Check FPU/MMX/SSE support. */
|
||||||
KiCheckFPU();
|
KiCheckFPU();
|
||||||
|
|
||||||
KeInitDpc(Pcr);
|
KeInitDpc(Pcr->Prcb);
|
||||||
|
|
||||||
if (Pcr->PrcbData.FeatureBits & X86_FEATURE_SYSCALL)
|
if (Pcr->PrcbData.FeatureBits & X86_FEATURE_SYSCALL)
|
||||||
{
|
{
|
||||||
|
@ -262,7 +262,7 @@ KeInit1(PCHAR CommandLine, PULONG LastKernelAddress)
|
||||||
/* Mark the end of the exception handler list */
|
/* Mark the end of the exception handler list */
|
||||||
KPCR->Tib.ExceptionList = (PVOID)-1;
|
KPCR->Tib.ExceptionList = (PVOID)-1;
|
||||||
|
|
||||||
KeInitDpc(KPCR);
|
KeInitDpc(KPCR->Prcb);
|
||||||
|
|
||||||
KeInitExceptions ();
|
KeInitExceptions ();
|
||||||
KeInitInterrupts ();
|
KeInitInterrupts ();
|
||||||
|
|
Loading…
Reference in a new issue