mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 07:02:56 +00:00
- Implemented KiIpiSendRequest for simple requests.
- Removed KeIpiCallForBootProcessor. - Used the KPCR of the processors for storing the ipi data. svn path=/trunk/; revision=11833
This commit is contained in:
parent
b51c0305db
commit
79a75d3246
2 changed files with 144 additions and 123 deletions
|
@ -43,6 +43,28 @@ struct _KIRQ_TRAPFRAME;
|
||||||
struct _KPCR;
|
struct _KPCR;
|
||||||
struct _KEXCEPTION_FRAME;
|
struct _KEXCEPTION_FRAME;
|
||||||
|
|
||||||
|
#define IPI_REQUEST_FUNCTIONCALL 1
|
||||||
|
#define IPI_REQUEST_APC 2
|
||||||
|
#define IPI_REQUEST_DPC 4
|
||||||
|
|
||||||
|
/* ipi.c ********************************************************************/
|
||||||
|
|
||||||
|
BOOLEAN STDCALL
|
||||||
|
KiIpiServiceRoutine(IN PKTRAP_FRAME TrapFrame,
|
||||||
|
IN struct _KEXCEPTION_FRAME* ExceptionFrame);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
KiIpiSendRequest(ULONG TargetSet,
|
||||||
|
ULONG IpiRequest);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
KeIpiGenericCall(VOID STDCALL (*WorkerRoutine)(PVOID),
|
||||||
|
PVOID Argument);
|
||||||
|
|
||||||
|
/* next file ***************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
VOID STDCALL
|
VOID STDCALL
|
||||||
DbgBreakPointNoBugCheck(VOID);
|
DbgBreakPointNoBugCheck(VOID);
|
||||||
|
|
||||||
|
@ -59,11 +81,6 @@ KeProfileInterruptWithSource(
|
||||||
IN KPROFILE_SOURCE Source
|
IN KPROFILE_SOURCE Source
|
||||||
);
|
);
|
||||||
|
|
||||||
BOOLEAN
|
|
||||||
STDCALL
|
|
||||||
KiIpiServiceRoutine(IN PKTRAP_FRAME TrapFrame,
|
|
||||||
IN struct _KEXCEPTION_FRAME* ExceptionFrame);
|
|
||||||
|
|
||||||
VOID STDCALL KeUpdateSystemTime(PKTRAP_FRAME TrapFrame, KIRQL Irql);
|
VOID STDCALL KeUpdateSystemTime(PKTRAP_FRAME TrapFrame, KIRQL Irql);
|
||||||
VOID STDCALL KeUpdateRunTime(PKTRAP_FRAME TrapFrame, KIRQL Irql);
|
VOID STDCALL KeUpdateRunTime(PKTRAP_FRAME TrapFrame, KIRQL Irql);
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: ipi.c,v 1.3 2004/11/14 20:00:06 hbirr Exp $
|
/* $Id: ipi.c,v 1.4 2004/11/27 16:32:10 hbirr Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -20,127 +20,167 @@
|
||||||
|
|
||||||
KSPIN_LOCK KiIpiLock;
|
KSPIN_LOCK KiIpiLock;
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
VOID STDCALL (*Function)(PVOID);
|
|
||||||
PVOID Argument;
|
|
||||||
BOOLEAN Synchronize;
|
|
||||||
ULONG StartCount;
|
|
||||||
ULONG EndCount;
|
|
||||||
} KiIpiInfo;
|
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
|
VOID
|
||||||
|
KiIpiSendRequest(ULONG TargetSet, ULONG IpiRequest)
|
||||||
|
{
|
||||||
|
ULONG i;
|
||||||
|
PKPCR Pcr;
|
||||||
|
|
||||||
|
for (i = 0; i < KeNumberProcessors; i++)
|
||||||
|
{
|
||||||
|
if (TargetSet & (1 << i))
|
||||||
|
{
|
||||||
|
Pcr = (PKPCR)(KPCR_BASE + i * PAGE_SIZE);
|
||||||
|
Pcr->PrcbData.IpiFrozen |= IpiRequest;
|
||||||
|
HalRequestIpi(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @unimplemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
STDCALL
|
STDCALL
|
||||||
KiIpiServiceRoutine(IN PKTRAP_FRAME TrapFrame,
|
KiIpiServiceRoutine(IN PKTRAP_FRAME TrapFrame,
|
||||||
IN PKEXCEPTION_FRAME ExceptionFrame)
|
IN PKEXCEPTION_FRAME ExceptionFrame)
|
||||||
{
|
{
|
||||||
LARGE_INTEGER StartTime, CurrentTime, Frequency;
|
#ifdef DBG
|
||||||
|
LARGE_INTEGER StartTime, CurrentTime, Frequency;
|
||||||
|
ULONG Count = 5;
|
||||||
|
#endif
|
||||||
|
ULONG TargetSet, Processor;
|
||||||
|
|
||||||
ASSERT(KeGetCurrentIrql() == IPI_LEVEL);
|
PKPCR Pcr;
|
||||||
|
|
||||||
DPRINT("KiIpiServiceRoutine\n");
|
ASSERT(KeGetCurrentIrql() == IPI_LEVEL);
|
||||||
|
|
||||||
|
DPRINT("KiIpiServiceRoutine\n");
|
||||||
|
|
||||||
if (KiIpiInfo.Synchronize)
|
Pcr = KeGetCurrentKPCR();
|
||||||
{
|
|
||||||
InterlockedDecrement(&KiIpiInfo.StartCount);
|
if (Pcr->PrcbData.IpiFrozen & IPI_REQUEST_APC)
|
||||||
StartTime = KeQueryPerformanceCounter(&Frequency);
|
{
|
||||||
while (0 != InterlockedCompareExchange(&KiIpiInfo.StartCount, 0, 0))
|
Pcr->PrcbData.IpiFrozen &= ~IPI_REQUEST_APC;
|
||||||
{
|
HalRequestSoftwareInterrupt(APC_LEVEL);
|
||||||
CurrentTime = KeQueryPerformanceCounter(NULL);
|
}
|
||||||
if (CurrentTime.QuadPart > StartTime.QuadPart + Frequency.QuadPart)
|
|
||||||
{
|
if (Pcr->PrcbData.IpiFrozen & IPI_REQUEST_DPC)
|
||||||
DPRINT1("Waiting longer than 1 seconds to start the ipi routine\n");
|
{
|
||||||
KEBUGCHECK(0);
|
Pcr->PrcbData.IpiFrozen &= ~IPI_REQUEST_DPC;
|
||||||
}
|
Pcr->PrcbData.DpcInterruptRequested = TRUE;
|
||||||
}
|
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
|
||||||
}
|
}
|
||||||
KiIpiInfo.Function(KiIpiInfo.Argument);
|
|
||||||
if (KiIpiInfo.Synchronize)
|
if (Pcr->PrcbData.IpiFrozen & IPI_REQUEST_FUNCTIONCALL)
|
||||||
{
|
{
|
||||||
InterlockedDecrement(&KiIpiInfo.EndCount);
|
InterlockedDecrement((PLONG)&Pcr->PrcbData.SignalDone->CurrentPacket[1]);
|
||||||
StartTime = KeQueryPerformanceCounter(&Frequency);
|
if (Pcr->PrcbData.SignalDone->CurrentPacket[2])
|
||||||
while (0 != InterlockedCompareExchange(&KiIpiInfo.EndCount, 0, 0))
|
{
|
||||||
{
|
#ifdef DBG
|
||||||
CurrentTime = KeQueryPerformanceCounter(NULL);
|
StartTime = KeQueryPerformanceCounter(&Frequency);
|
||||||
if (CurrentTime.QuadPart > StartTime.QuadPart + Frequency.QuadPart)
|
#endif
|
||||||
{
|
while (0 != InterlockedCompareExchange((PLONG)&Pcr->PrcbData.SignalDone->CurrentPacket[1], 0, 0))
|
||||||
DPRINT1("Waiting longer than 1 seconds after executing the ipi routine\n");
|
{
|
||||||
KEBUGCHECK(0);
|
#ifdef DBG
|
||||||
}
|
CurrentTime = KeQueryPerformanceCounter(NULL);
|
||||||
}
|
if (CurrentTime.QuadPart > StartTime.QuadPart + Count * Frequency.QuadPart)
|
||||||
}
|
{
|
||||||
return TRUE;
|
DPRINT1("Waiting longer than %d seconds to start the ipi routine\n", Count);
|
||||||
|
KEBUGCHECK(0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
((VOID STDCALL(*)(PVOID))(Pcr->PrcbData.SignalDone->WorkerRoutine))(Pcr->PrcbData.SignalDone->CurrentPacket[0]);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
Processor = 1 << KeGetCurrentProcessorNumber();
|
||||||
|
TargetSet = Pcr->PrcbData.SignalDone->TargetSet;
|
||||||
|
} while (Processor & InterlockedCompareExchange(&Pcr->PrcbData.SignalDone->TargetSet, TargetSet & ~Processor, TargetSet));
|
||||||
|
if (Pcr->PrcbData.SignalDone->CurrentPacket[2])
|
||||||
|
{
|
||||||
|
#ifdef DBG
|
||||||
|
StartTime = KeQueryPerformanceCounter(&Frequency);
|
||||||
|
#endif
|
||||||
|
while (0 != InterlockedCompareExchange(&Pcr->PrcbData.SignalDone->TargetSet, 0, 0))
|
||||||
|
{
|
||||||
|
#ifdef DBG
|
||||||
|
CurrentTime = KeQueryPerformanceCounter(NULL);
|
||||||
|
if (CurrentTime.QuadPart > StartTime.QuadPart + Count * Frequency.QuadPart)
|
||||||
|
{
|
||||||
|
DPRINT1("Waiting longer than %d seconds after executing the ipi routine\n", Count);
|
||||||
|
KEBUGCHECK(0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InterlockedExchangePointer(&Pcr->PrcbData.SignalDone, NULL);
|
||||||
|
Pcr->PrcbData.IpiFrozen &= ~IPI_REQUEST_FUNCTIONCALL;
|
||||||
|
}
|
||||||
|
DPRINT("KiIpiServiceRoutine done\n");
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
STDCALL
|
STDCALL
|
||||||
KiIpiSendPacket(ULONG Processors, VOID STDCALL (*Function)(PVOID), PVOID Argument, ULONG Count, BOOLEAN Synchronize)
|
KiIpiSendPacket(ULONG TargetSet, VOID STDCALL (*WorkerRoutine)(PVOID), PVOID Argument, ULONG Count, BOOLEAN Synchronize)
|
||||||
{
|
{
|
||||||
ULONG i;
|
ULONG i, Processor, CurrentProcessor;
|
||||||
|
PKPCR Pcr, CurrentPcr;
|
||||||
|
KIRQL oldIrql;
|
||||||
|
|
||||||
|
|
||||||
ASSERT(KeGetCurrentIrql() == SYNCH_LEVEL);
|
ASSERT(KeGetCurrentIrql() == SYNCH_LEVEL);
|
||||||
|
|
||||||
/*
|
CurrentPcr = KeGetCurrentKPCR();
|
||||||
* FIXME
|
CurrentPcr->PrcbData.TargetSet = TargetSet;
|
||||||
* M$ puts the ipi information anywhere into the KPCR of the requestor.
|
CurrentPcr->PrcbData.WorkerRoutine = (ULONG_PTR)WorkerRoutine;
|
||||||
* The KPCR of the target contains a pointer of the KPCR of the requestor.
|
CurrentPcr->PrcbData.CurrentPacket[0] = Argument;
|
||||||
*/
|
CurrentPcr->PrcbData.CurrentPacket[1] = (PVOID)Count;
|
||||||
|
CurrentPcr->PrcbData.CurrentPacket[2] = (PVOID)(ULONG)Synchronize;
|
||||||
|
|
||||||
KiIpiInfo.Function = Function;
|
CurrentProcessor = 1 << KeGetCurrentProcessorNumber();
|
||||||
KiIpiInfo.Argument = Argument;
|
|
||||||
if (Synchronize)
|
|
||||||
{
|
|
||||||
KiIpiInfo.StartCount = Count;
|
|
||||||
KiIpiInfo.EndCount = Count;
|
|
||||||
}
|
|
||||||
KiIpiInfo.Synchronize = Synchronize;
|
|
||||||
|
|
||||||
for (i = 0; i < KeNumberProcessors; i++)
|
for (i = 0, Processor = 1; i < KeNumberProcessors; i++, Processor <<= 1)
|
||||||
{
|
{
|
||||||
if (Processors & (1 << i))
|
if (TargetSet & Processor)
|
||||||
{
|
{
|
||||||
HalRequestIpi(i);
|
Pcr = (PKPCR)(KPCR_BASE + i * PAGE_SIZE);
|
||||||
|
while(0 != InterlockedCompareExchange((PLONG)&Pcr->PrcbData.SignalDone, (LONG)&CurrentPcr->PrcbData, 0));
|
||||||
|
Pcr->PrcbData.IpiFrozen |= IPI_REQUEST_FUNCTIONCALL;
|
||||||
|
if (Processor != CurrentProcessor)
|
||||||
|
{
|
||||||
|
HalRequestIpi(i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (TargetSet & CurrentProcessor)
|
||||||
|
{
|
||||||
|
KeRaiseIrql(IPI_LEVEL, &oldIrql);
|
||||||
|
KiIpiServiceRoutine(NULL, NULL);
|
||||||
|
KeLowerIrql(oldIrql);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
STDCALL
|
|
||||||
KeIpiGenericCall(VOID STDCALL (*Function)(PVOID), PVOID Argument)
|
KeIpiGenericCall(VOID STDCALL (*Function)(PVOID), PVOID Argument)
|
||||||
{
|
{
|
||||||
KIRQL oldIrql, oldIrql2;
|
KIRQL oldIrql;
|
||||||
ULONG Count, i;
|
ULONG TargetSet;
|
||||||
ULONG Processors = 0;
|
|
||||||
|
|
||||||
DPRINT("KeIpiGenericCall on CPU%d\n", KeGetCurrentProcessorNumber());
|
DPRINT("KeIpiGenericCall on CPU%d\n", KeGetCurrentProcessorNumber());
|
||||||
|
|
||||||
KeRaiseIrql(SYNCH_LEVEL, &oldIrql);
|
KeRaiseIrql(SYNCH_LEVEL, &oldIrql);
|
||||||
|
|
||||||
Count = KeNumberProcessors;
|
|
||||||
for (i = 0; i < KeNumberProcessors; i++)
|
|
||||||
{
|
|
||||||
if (KeGetCurrentProcessorNumber() != i)
|
|
||||||
{
|
|
||||||
Processors |= (1 << i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
KiAcquireSpinLock(&KiIpiLock);
|
KiAcquireSpinLock(&KiIpiLock);
|
||||||
|
|
||||||
KiIpiSendPacket(Processors, Function, Argument, Count, TRUE);
|
TargetSet = (1 << KeNumberProcessors) - 1;
|
||||||
|
|
||||||
KeRaiseIrql(IPI_LEVEL, &oldIrql2);
|
|
||||||
|
|
||||||
KiIpiServiceRoutine(NULL, NULL);
|
|
||||||
|
|
||||||
KeLowerIrql(oldIrql2);
|
|
||||||
|
|
||||||
|
KiIpiSendPacket(TargetSet, Function, Argument, KeNumberProcessors, TRUE);
|
||||||
|
|
||||||
KiReleaseSpinLock(&KiIpiLock);
|
KiReleaseSpinLock(&KiIpiLock);
|
||||||
|
|
||||||
KeLowerIrql(oldIrql);
|
KeLowerIrql(oldIrql);
|
||||||
|
@ -148,41 +188,5 @@ KeIpiGenericCall(VOID STDCALL (*Function)(PVOID), PVOID Argument)
|
||||||
DPRINT("KeIpiGenericCall on CPU%d done\n", KeGetCurrentProcessorNumber());
|
DPRINT("KeIpiGenericCall on CPU%d done\n", KeGetCurrentProcessorNumber());
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
|
||||||
STDCALL
|
|
||||||
KeIpiCallForBootProcessor(VOID STDCALL (*Function)(PVOID), PVOID Argument)
|
|
||||||
{
|
|
||||||
KIRQL oldIrql, oldIrql2;
|
|
||||||
LARGE_INTEGER StartCount, CurrentCount;
|
|
||||||
LARGE_INTEGER Frequency;
|
|
||||||
|
|
||||||
KeRaiseIrql(SYNCH_LEVEL, &oldIrql);
|
|
||||||
|
|
||||||
ASSERT (KeGetCurrentProcessorNumber() != 0);
|
|
||||||
|
|
||||||
KiAcquireSpinLock(&KiIpiLock);
|
|
||||||
|
|
||||||
KiIpiSendPacket(1, Function, Argument, 1, TRUE);
|
|
||||||
|
|
||||||
KeRaiseIrql(IPI_LEVEL, &oldIrql2);
|
|
||||||
|
|
||||||
StartCount = KeQueryPerformanceCounter(&Frequency);
|
|
||||||
while (0 != InterlockedCompareExchange(&KiIpiInfo.EndCount, 0, 0))
|
|
||||||
{
|
|
||||||
CurrentCount = KeQueryPerformanceCounter(NULL);
|
|
||||||
if (CurrentCount.QuadPart > StartCount.QuadPart + Frequency.QuadPart)
|
|
||||||
{
|
|
||||||
DPRINT1("Waiting longer than 1 second after sending the ipi to the boot processor\n");
|
|
||||||
KEBUGCHECK(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
KeLowerIrql(oldIrql2);
|
|
||||||
|
|
||||||
KiReleaseSpinLock(&KiIpiLock);
|
|
||||||
|
|
||||||
KeLowerIrql(oldIrql);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue