2006-09-13 02:25:32 +00:00
|
|
|
/*
|
|
|
|
* PROJECT: ReactOS Kernel
|
|
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
2004-08-12 06:04:21 +00:00
|
|
|
* FILE: ntoskrnl/ke/ipi.c
|
2006-09-13 02:25:32 +00:00
|
|
|
* PURPOSE: Inter-Processor Packet Interface
|
|
|
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
2004-08-12 06:04:21 +00:00
|
|
|
*/
|
|
|
|
|
2006-09-13 02:25:32 +00:00
|
|
|
/* INCLUDES ******************************************************************/
|
2004-08-12 06:04:21 +00:00
|
|
|
|
2004-08-15 16:39:12 +00:00
|
|
|
#include <ntoskrnl.h>
|
2004-08-12 06:04:21 +00:00
|
|
|
#define NDEBUG
|
|
|
|
#include <internal/debug.h>
|
|
|
|
|
2004-11-14 20:00:06 +00:00
|
|
|
/* GLOBALS *******************************************************************/
|
|
|
|
|
|
|
|
KSPIN_LOCK KiIpiLock;
|
|
|
|
|
2006-09-13 02:25:32 +00:00
|
|
|
/* PRIVATE FUNCTIONS *********************************************************/
|
2004-11-27 16:32:10 +00:00
|
|
|
|
2005-05-09 01:38:29 +00:00
|
|
|
VOID
|
2005-09-14 01:44:19 +00:00
|
|
|
NTAPI
|
2006-09-13 02:25:32 +00:00
|
|
|
KiIpiSendRequest(IN KAFFINITY TargetSet,
|
|
|
|
IN ULONG IpiRequest)
|
2004-11-14 20:00:06 +00:00
|
|
|
{
|
2006-09-13 02:25:32 +00:00
|
|
|
#ifdef CONFIG_SMP
|
|
|
|
LONG i;
|
2007-11-06 14:34:32 +00:00
|
|
|
PKPRCB Prcb;
|
2006-09-13 02:25:32 +00:00
|
|
|
KAFFINITY Current;
|
2004-11-27 16:32:10 +00:00
|
|
|
|
2006-09-13 02:25:32 +00:00
|
|
|
for (i = 0, Current = 1; i < KeNumberProcessors; i++, Current <<= 1)
|
|
|
|
{
|
|
|
|
if (TargetSet & Current)
|
|
|
|
{
|
2007-11-06 14:34:32 +00:00
|
|
|
/* Get the PRCB for this CPU */
|
2007-11-06 21:36:47 +00:00
|
|
|
Prcb = KiProcessorBlock[i];
|
2007-11-06 14:34:32 +00:00
|
|
|
|
|
|
|
InterlockedBitTestAndSet((PLONG)&Prcb->IpiFrozen, IpiRequest);
|
2006-09-13 02:25:32 +00:00
|
|
|
HalRequestIpi(i);
|
|
|
|
}
|
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
#endif
|
2004-11-14 20:00:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
2006-09-13 02:25:32 +00:00
|
|
|
NTAPI
|
|
|
|
KiIpiSendPacket(IN KAFFINITY TargetSet,
|
|
|
|
IN PKIPI_BROADCAST_WORKER WorkerRoutine,
|
|
|
|
IN ULONG_PTR Argument,
|
|
|
|
IN ULONG Count,
|
|
|
|
IN BOOLEAN Synchronize)
|
2004-11-14 20:00:06 +00:00
|
|
|
{
|
2006-09-13 02:25:32 +00:00
|
|
|
#ifdef CONFIG_SMP
|
2005-07-17 18:27:46 +00:00
|
|
|
KAFFINITY Processor;
|
2005-07-05 22:35:29 +00:00
|
|
|
LONG i;
|
2005-03-12 09:40:07 +00:00
|
|
|
PKPRCB Prcb, CurrentPrcb;
|
2004-11-27 16:32:10 +00:00
|
|
|
KIRQL oldIrql;
|
|
|
|
|
2004-11-14 20:00:06 +00:00
|
|
|
ASSERT(KeGetCurrentIrql() == SYNCH_LEVEL);
|
|
|
|
|
2005-03-12 09:40:07 +00:00
|
|
|
CurrentPrcb = KeGetCurrentPrcb();
|
2006-03-04 17:27:40 +00:00
|
|
|
(void)InterlockedExchangeUL(&CurrentPrcb->TargetSet, TargetSet);
|
|
|
|
(void)InterlockedExchangeUL(&CurrentPrcb->WorkerRoutine, (ULONG_PTR)WorkerRoutine);
|
|
|
|
(void)InterlockedExchangePointer(&CurrentPrcb->CurrentPacket[0], Argument);
|
|
|
|
(void)InterlockedExchangeUL(&CurrentPrcb->CurrentPacket[1], Count);
|
|
|
|
(void)InterlockedExchangeUL(&CurrentPrcb->CurrentPacket[2], Synchronize ? 1 : 0);
|
2004-11-14 20:00:06 +00:00
|
|
|
|
2004-11-27 16:32:10 +00:00
|
|
|
for (i = 0, Processor = 1; i < KeNumberProcessors; i++, Processor <<= 1)
|
2004-11-14 20:00:06 +00:00
|
|
|
{
|
2006-09-13 02:25:32 +00:00
|
|
|
if (TargetSet & Processor)
|
|
|
|
{
|
2007-11-06 21:36:47 +00:00
|
|
|
Prcb = KiProcessorBlock[i];
|
2007-11-06 14:34:32 +00:00
|
|
|
while (0 != InterlockedCompareExchangeUL(&Prcb->SignalDone, (LONG)CurrentPrcb, 0));
|
|
|
|
InterlockedBitTestAndSet((PLONG)&Prcb->IpiFrozen, IPI_SYNCH_REQUEST);
|
2006-09-13 02:25:32 +00:00
|
|
|
if (Processor != CurrentPrcb->SetMember)
|
|
|
|
{
|
|
|
|
HalRequestIpi(i);
|
|
|
|
}
|
|
|
|
}
|
2004-11-14 20:00:06 +00:00
|
|
|
}
|
2005-07-17 18:27:46 +00:00
|
|
|
if (TargetSet & CurrentPrcb->SetMember)
|
2004-11-27 16:32:10 +00:00
|
|
|
{
|
2006-09-13 02:25:32 +00:00
|
|
|
KeRaiseIrql(IPI_LEVEL, &oldIrql);
|
|
|
|
KiIpiServiceRoutine(NULL, NULL);
|
|
|
|
KeLowerIrql(oldIrql);
|
2004-11-27 16:32:10 +00:00
|
|
|
}
|
2006-09-13 02:25:32 +00:00
|
|
|
#endif
|
2004-11-14 20:00:06 +00:00
|
|
|
}
|
|
|
|
|
2006-09-13 02:25:32 +00:00
|
|
|
/* PUBLIC FUNCTIONS **********************************************************/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
BOOLEAN
|
2005-09-14 01:44:19 +00:00
|
|
|
NTAPI
|
2006-09-13 02:25:32 +00:00
|
|
|
KiIpiServiceRoutine(IN PKTRAP_FRAME TrapFrame,
|
|
|
|
IN PVOID ExceptionFrame)
|
2004-11-14 20:00:06 +00:00
|
|
|
{
|
2006-09-13 02:25:32 +00:00
|
|
|
#ifdef CONFIG_SMP
|
|
|
|
PKPRCB Prcb;
|
|
|
|
ASSERT(KeGetCurrentIrql() == IPI_LEVEL);
|
2004-11-14 20:00:06 +00:00
|
|
|
|
2006-09-13 02:25:32 +00:00
|
|
|
Prcb = KeGetCurrentPrcb();
|
2004-11-14 20:00:06 +00:00
|
|
|
|
2007-11-06 14:34:32 +00:00
|
|
|
if (InterlockedBitTestAndReset((PLONG)&Prcb->IpiFrozen, IPI_APC))
|
2006-09-13 02:25:32 +00:00
|
|
|
{
|
|
|
|
HalRequestSoftwareInterrupt(APC_LEVEL);
|
|
|
|
}
|
2004-11-14 20:00:06 +00:00
|
|
|
|
2007-11-06 14:34:32 +00:00
|
|
|
if (InterlockedBitTestAndReset((PLONG)&Prcb->IpiFrozen, IPI_DPC))
|
2006-09-13 02:25:32 +00:00
|
|
|
{
|
|
|
|
Prcb->DpcInterruptRequested = TRUE;
|
|
|
|
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
|
|
|
|
}
|
2004-11-14 20:00:06 +00:00
|
|
|
|
2007-11-06 14:34:32 +00:00
|
|
|
if (InterlockedBitTestAndReset((PLONG)&Prcb->IpiFrozen, IPI_SYNCH_REQUEST))
|
2006-09-13 02:25:32 +00:00
|
|
|
{
|
|
|
|
(void)InterlockedDecrementUL(&Prcb->SignalDone->CurrentPacket[1]);
|
|
|
|
if (InterlockedCompareExchangeUL(&Prcb->SignalDone->CurrentPacket[2], 0, 0))
|
|
|
|
{
|
|
|
|
while (0 != InterlockedCompareExchangeUL(&Prcb->SignalDone->CurrentPacket[1], 0, 0));
|
|
|
|
}
|
2007-11-06 14:34:32 +00:00
|
|
|
((VOID (NTAPI*)(PVOID))(Prcb->SignalDone->WorkerRoutine))(Prcb->SignalDone->CurrentPacket[0]);
|
|
|
|
InterlockedBitTestAndReset((PLONG)&Prcb->SignalDone->TargetSet, KeGetCurrentProcessorNumber());
|
2006-09-13 02:25:32 +00:00
|
|
|
if (InterlockedCompareExchangeUL(&Prcb->SignalDone->CurrentPacket[2], 0, 0))
|
|
|
|
{
|
|
|
|
while (0 != InterlockedCompareExchangeUL(&Prcb->SignalDone->TargetSet, 0, 0));
|
|
|
|
}
|
|
|
|
(void)InterlockedExchangePointer(&Prcb->SignalDone, NULL);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return TRUE;
|
|
|
|
}
|
2004-11-14 20:00:06 +00:00
|
|
|
|
2006-09-13 02:25:32 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
ULONG_PTR
|
|
|
|
NTAPI
|
|
|
|
KeIpiGenericCall(IN PKIPI_BROADCAST_WORKER Function,
|
|
|
|
IN ULONG_PTR Argument)
|
|
|
|
{
|
|
|
|
#ifdef CONFIG_SMP
|
|
|
|
#error Not yet implemented!
|
|
|
|
#else
|
|
|
|
ULONG_PTR Status;
|
2008-02-07 07:10:13 +00:00
|
|
|
KIRQL OldIrql, OldIrql2;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2006-09-13 02:25:32 +00:00
|
|
|
/* Raise to DPC level if required */
|
|
|
|
OldIrql = KeGetCurrentIrql();
|
2008-02-07 07:10:13 +00:00
|
|
|
if (OldIrql < DISPATCH_LEVEL) KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2006-09-13 02:25:32 +00:00
|
|
|
/* Acquire the IPI lock */
|
|
|
|
KefAcquireSpinLockAtDpcLevel(&KiIpiLock);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2006-09-13 02:25:32 +00:00
|
|
|
/* Raise to IPI level */
|
2008-02-07 07:10:13 +00:00
|
|
|
KeRaiseIrql(IPI_LEVEL, &OldIrql2);
|
2006-09-13 02:25:32 +00:00
|
|
|
|
|
|
|
/* Call the function */
|
|
|
|
Status = Function(Argument);
|
2004-11-14 20:00:06 +00:00
|
|
|
|
2006-09-13 02:25:32 +00:00
|
|
|
/* Release the lock */
|
|
|
|
KefReleaseSpinLockFromDpcLevel(&KiIpiLock);
|
|
|
|
|
|
|
|
/* Lower IRQL back */
|
2008-02-07 07:10:13 +00:00
|
|
|
KeLowerIrql(OldIrql);
|
2006-09-13 02:25:32 +00:00
|
|
|
return Status;
|
|
|
|
#endif
|
|
|
|
}
|
2004-08-12 06:04:21 +00:00
|
|
|
|
|
|
|
/* EOF */
|