mirror of
https://github.com/reactos/reactos.git
synced 2024-11-07 07:00:19 +00:00
c501d8112c
svn path=/branches/aicom-network-fixes/; revision=34994
172 lines
4.7 KiB
C
172 lines
4.7 KiB
C
/*
|
|
* PROJECT: ReactOS Kernel
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
* FILE: ntoskrnl/ke/ipi.c
|
|
* PURPOSE: Inter-Processor Packet Interface
|
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
|
*/
|
|
|
|
/* INCLUDES ******************************************************************/
|
|
|
|
#include <ntoskrnl.h>
|
|
#define NDEBUG
|
|
#include <internal/debug.h>
|
|
|
|
/* GLOBALS *******************************************************************/
|
|
|
|
KSPIN_LOCK KiIpiLock;
|
|
|
|
/* PRIVATE FUNCTIONS *********************************************************/
|
|
|
|
VOID
|
|
NTAPI
|
|
KiIpiSendRequest(IN KAFFINITY TargetSet,
|
|
IN ULONG IpiRequest)
|
|
{
|
|
#ifdef CONFIG_SMP
|
|
LONG i;
|
|
PKPRCB Prcb;
|
|
KAFFINITY Current;
|
|
|
|
for (i = 0, Current = 1; i < KeNumberProcessors; i++, Current <<= 1)
|
|
{
|
|
if (TargetSet & Current)
|
|
{
|
|
/* Get the PRCB for this CPU */
|
|
Prcb = KiProcessorBlock[i];
|
|
|
|
InterlockedBitTestAndSet((PLONG)&Prcb->IpiFrozen, IpiRequest);
|
|
HalRequestIpi(i);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
KiIpiSendPacket(IN KAFFINITY TargetSet,
|
|
IN PKIPI_BROADCAST_WORKER WorkerRoutine,
|
|
IN ULONG_PTR Argument,
|
|
IN ULONG Count,
|
|
IN BOOLEAN Synchronize)
|
|
{
|
|
#ifdef CONFIG_SMP
|
|
KAFFINITY Processor;
|
|
LONG i;
|
|
PKPRCB Prcb, CurrentPrcb;
|
|
KIRQL oldIrql;
|
|
|
|
ASSERT(KeGetCurrentIrql() == SYNCH_LEVEL);
|
|
|
|
CurrentPrcb = KeGetCurrentPrcb();
|
|
(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);
|
|
|
|
for (i = 0, Processor = 1; i < KeNumberProcessors; i++, Processor <<= 1)
|
|
{
|
|
if (TargetSet & Processor)
|
|
{
|
|
Prcb = KiProcessorBlock[i];
|
|
while (0 != InterlockedCompareExchangeUL(&Prcb->SignalDone, (LONG)CurrentPrcb, 0));
|
|
InterlockedBitTestAndSet((PLONG)&Prcb->IpiFrozen, IPI_SYNCH_REQUEST);
|
|
if (Processor != CurrentPrcb->SetMember)
|
|
{
|
|
HalRequestIpi(i);
|
|
}
|
|
}
|
|
}
|
|
if (TargetSet & CurrentPrcb->SetMember)
|
|
{
|
|
KeRaiseIrql(IPI_LEVEL, &oldIrql);
|
|
KiIpiServiceRoutine(NULL, NULL);
|
|
KeLowerIrql(oldIrql);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* PUBLIC FUNCTIONS **********************************************************/
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
BOOLEAN
|
|
NTAPI
|
|
KiIpiServiceRoutine(IN PKTRAP_FRAME TrapFrame,
|
|
IN PVOID ExceptionFrame)
|
|
{
|
|
#ifdef CONFIG_SMP
|
|
PKPRCB Prcb;
|
|
ASSERT(KeGetCurrentIrql() == IPI_LEVEL);
|
|
|
|
Prcb = KeGetCurrentPrcb();
|
|
|
|
if (InterlockedBitTestAndReset((PLONG)&Prcb->IpiFrozen, IPI_APC))
|
|
{
|
|
HalRequestSoftwareInterrupt(APC_LEVEL);
|
|
}
|
|
|
|
if (InterlockedBitTestAndReset((PLONG)&Prcb->IpiFrozen, IPI_DPC))
|
|
{
|
|
Prcb->DpcInterruptRequested = TRUE;
|
|
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
|
|
}
|
|
|
|
if (InterlockedBitTestAndReset((PLONG)&Prcb->IpiFrozen, IPI_SYNCH_REQUEST))
|
|
{
|
|
(void)InterlockedDecrementUL(&Prcb->SignalDone->CurrentPacket[1]);
|
|
if (InterlockedCompareExchangeUL(&Prcb->SignalDone->CurrentPacket[2], 0, 0))
|
|
{
|
|
while (0 != InterlockedCompareExchangeUL(&Prcb->SignalDone->CurrentPacket[1], 0, 0));
|
|
}
|
|
((VOID (NTAPI*)(PVOID))(Prcb->SignalDone->WorkerRoutine))(Prcb->SignalDone->CurrentPacket[0]);
|
|
InterlockedBitTestAndReset((PLONG)&Prcb->SignalDone->TargetSet, KeGetCurrentProcessorNumber());
|
|
if (InterlockedCompareExchangeUL(&Prcb->SignalDone->CurrentPacket[2], 0, 0))
|
|
{
|
|
while (0 != InterlockedCompareExchangeUL(&Prcb->SignalDone->TargetSet, 0, 0));
|
|
}
|
|
(void)InterlockedExchangePointer(&Prcb->SignalDone, NULL);
|
|
}
|
|
#endif
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* @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;
|
|
KIRQL OldIrql, OldIrql2;
|
|
|
|
/* Raise to DPC level if required */
|
|
OldIrql = KeGetCurrentIrql();
|
|
if (OldIrql < DISPATCH_LEVEL) KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
|
|
|
|
/* Acquire the IPI lock */
|
|
KefAcquireSpinLockAtDpcLevel(&KiIpiLock);
|
|
|
|
/* Raise to IPI level */
|
|
KeRaiseIrql(IPI_LEVEL, &OldIrql2);
|
|
|
|
/* Call the function */
|
|
Status = Function(Argument);
|
|
|
|
/* Release the lock */
|
|
KefReleaseSpinLockFromDpcLevel(&KiIpiLock);
|
|
|
|
/* Lower IRQL back */
|
|
KeLowerIrql(OldIrql);
|
|
return Status;
|
|
#endif
|
|
}
|
|
|
|
/* EOF */
|