mirror of
https://github.com/reactos/reactos.git
synced 2024-09-30 14:37:45 +00:00
- Acquire always the dpc lock on smp systems.
- Set/reset DpcRoutineActive at HIGH_LEVEL (or if the dpc queue is locked). svn path=/trunk/; revision=11753
This commit is contained in:
parent
7af1a71e33
commit
0f6f4de9e1
|
@ -19,7 +19,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/* $Id: dpc.c,v 1.47 2004/11/21 10:48:33 hbirr Exp $
|
||||
/* $Id: dpc.c,v 1.48 2004/11/21 18:13:47 hbirr Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -203,6 +203,7 @@ KeInsertQueueDpc (PKDPC Dpc,
|
|||
Pcr = KeGetCurrentKPCR();
|
||||
Dpc->Number = KeGetCurrentProcessorNumber();
|
||||
}
|
||||
KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
|
||||
#else
|
||||
Pcr = (PKPCR)KPCR_BASE;
|
||||
#endif
|
||||
|
@ -210,6 +211,9 @@ KeInsertQueueDpc (PKDPC Dpc,
|
|||
/* Get the DPC Data */
|
||||
if (InterlockedCompareExchange((LONG*)&Dpc->DpcData, (LONG)&Pcr->PrcbData.DpcData[0].DpcLock, 0)) {
|
||||
DPRINT("DPC Already Inserted");
|
||||
#ifdef MP
|
||||
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
|
||||
#endif
|
||||
KeLowerIrql(OldIrql);
|
||||
return(FALSE);
|
||||
}
|
||||
|
@ -245,9 +249,13 @@ KeInsertQueueDpc (PKDPC Dpc,
|
|||
if ((Dpc->Importance == HighImportance) ||
|
||||
(Pcr->PrcbData.DpcData[0].DpcQueueDepth >= Pcr->PrcbData.MaximumDpcQueueDepth)) {
|
||||
|
||||
#if 0
|
||||
KiIpiSendRequest(1 << Dpc->Number, IPI_REQUEST_DPC);
|
||||
#else
|
||||
/* FIXME: USE IPI */
|
||||
Pcr->PrcbData.DpcInterruptRequested = TRUE;
|
||||
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
/* Request an Interrupt only if the DPC isn't low priority */
|
||||
|
@ -274,6 +282,9 @@ KeInsertQueueDpc (PKDPC Dpc,
|
|||
}
|
||||
#endif
|
||||
}
|
||||
#ifdef MP
|
||||
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
|
||||
#endif
|
||||
/* Lower IRQL */
|
||||
KeLowerIrql(OldIrql);
|
||||
return(TRUE);
|
||||
|
@ -299,7 +310,10 @@ KeRemoveQueueDpc (PKDPC Dpc)
|
|||
|
||||
/* Raise IRQL */
|
||||
DPRINT("Removing DPC: %x\n", Dpc);
|
||||
KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
|
||||
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
||||
#ifdef MP
|
||||
KiAcquireSpinLock(&((PKDPC_DATA)Dpc->DpcData)->DpcLock);
|
||||
#endif
|
||||
|
||||
/* First make sure the DPC lock isn't being held */
|
||||
WasInQueue = Dpc->DpcData ? TRUE : FALSE;
|
||||
|
@ -310,6 +324,9 @@ KeRemoveQueueDpc (PKDPC Dpc)
|
|||
RemoveEntryList(&Dpc->DpcListEntry);
|
||||
|
||||
}
|
||||
#ifdef MP
|
||||
KiReleaseSpinLock(&((PKDPC_DATA)Dpc->DpcData)->DpcLock);
|
||||
#endif
|
||||
|
||||
/* Return if the DPC was in the queue or not */
|
||||
KeLowerIrql(OldIrql);
|
||||
|
@ -475,7 +492,6 @@ KiDispatchInterrupt(VOID)
|
|||
|
||||
/* Set DPC Deliver to Active */
|
||||
Pcr = KeGetCurrentKPCR();
|
||||
Pcr->PrcbData.DpcRoutineActive = TRUE;
|
||||
|
||||
if (Pcr->PrcbData.DpcData[0].DpcQueueDepth > 0) {
|
||||
/* Raise IRQL */
|
||||
|
@ -483,6 +499,7 @@ KiDispatchInterrupt(VOID)
|
|||
#ifdef MP
|
||||
KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
|
||||
#endif
|
||||
Pcr->PrcbData.DpcRoutineActive = TRUE;
|
||||
|
||||
DPRINT("&Pcr->PrcbData.DpcData[0].DpcListHead: %x\n", &Pcr->PrcbData.DpcData[0].DpcListHead);
|
||||
/* Loop while we have entries */
|
||||
|
@ -507,29 +524,29 @@ KiDispatchInterrupt(VOID)
|
|||
Dpc->SystemArgument1,
|
||||
Dpc->SystemArgument2);
|
||||
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
||||
#ifdef MP
|
||||
KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
|
||||
#endif
|
||||
|
||||
#ifdef MP
|
||||
KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
|
||||
/*
|
||||
* If the dpc routine drops the irql below DISPATCH_LEVEL,
|
||||
* a thread switch can occur and after the next thread switch
|
||||
* the execution may start on an other processor.
|
||||
*/
|
||||
* If the dpc routine drops the irql below DISPATCH_LEVEL,
|
||||
* a thread switch can occur and after the next thread switch
|
||||
* the execution may start on an other processor.
|
||||
*/
|
||||
if (Pcr != KeGetCurrentKPCR()) {
|
||||
Pcr->PrcbData.DpcRoutineActive = FALSE;
|
||||
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
|
||||
Pcr = KeGetCurrentKPCR();
|
||||
KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
|
||||
Pcr->PrcbData.DpcRoutineActive = TRUE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#ifdef MP
|
||||
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
|
||||
#endif
|
||||
/* Clear DPC Flags */
|
||||
Pcr->PrcbData.DpcRoutineActive = FALSE;
|
||||
Pcr->PrcbData.DpcInterruptRequested = FALSE;
|
||||
#ifdef MP
|
||||
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
|
||||
#endif
|
||||
|
||||
/* DPC Dispatching Ended, re-enable interrupts */
|
||||
KeLowerIrql(OldIrql);
|
||||
|
|
Loading…
Reference in a new issue