windows-nt/Source/XPSP1/NT/base/ntos/ke/xipi.c

258 lines
5.6 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1993-1995 Microsoft Corporation
Module Name:
xipi.c
Abstract:
This module implements portable interprocessor interrup routines.
Author:
David N. Cutler (davec) 24-Apr-1993
Environment:
Kernel mode only.
Revision History:
--*/
#include "ki.h"
//
// Define forward reference function prototypes.
//
VOID
KiIpiGenericCallTarget (
IN PKIPI_CONTEXT SignalDone,
IN PVOID BroadcastFunction,
IN PVOID Context,
IN PVOID Parameter3
);
ULONG_PTR
KiIpiGenericCall (
IN PKIPI_BROADCAST_WORKER BroadcastFunction,
IN ULONG_PTR Context
)
/*++
Routine Description:
This function executes the specified function on every processor in
the host configuration in a synchronous manner, i.e., the function
is executed on each target in series with the execution of the source
processor.
Arguments:
BroadcastFunction - Supplies the address of function that is executed
on each of the target processors.
Context - Supplies the value of the context parameter that is passed
to each function.
Return Value:
The value returned by the specified function on the source processor
is returned as the function value.
--*/
{
KIRQL OldIrql;
ULONG_PTR Status;
KAFFINITY TargetProcessors;
//
// Raise IRQL to the higher of the current level and synchronization
// level to avoid a possible context switch.
//
KeRaiseIrql((KIRQL)(max(KiSynchIrql, KeGetCurrentIrql())), &OldIrql);
//
// Initialize the broadcast packet, compute the set of target processors,
// and sent the packet to the target processors for execution.
//
#if !defined(NT_UP)
TargetProcessors = KeActiveProcessors & ~KeGetCurrentPrcb()->SetMember;
if (TargetProcessors != 0) {
KiIpiSendPacket(TargetProcessors,
KiIpiGenericCallTarget,
(PVOID)BroadcastFunction,
(PVOID)Context,
NULL);
}
#endif
//
// Execute function of source processor and capture return status.
//
Status = BroadcastFunction(Context);
//
// Wait until all of the target processors have finished capturing the
// function parameters.
//
#if !defined(NT_UP)
if (TargetProcessors != 0) {
KiIpiStallOnPacketTargets(TargetProcessors);
}
#endif
//
// Lower IRQL to its previous level and return the function execution
// status.
//
KeLowerIrql(OldIrql);
return Status;
}
#if !defined(NT_UP)
VOID
KiIpiGenericCallTarget (
IN PKIPI_CONTEXT SignalDone,
IN PVOID BroadcastFunction,
IN PVOID Context,
IN PVOID Parameter3
)
/*++
Routine Description:
This function is the target jacket function to execute a broadcast
function on a set of target processors. The broadcast packet address
is obtained, the specified parameters are captured, the broadcast
packet address is cleared to signal the source processor to continue,
and the specified function is executed.
Arguments:
SignalDone Supplies a pointer to a variable that is cleared when the
requested operation has been performed.
BroadcastFunction - Supplies the address of function that is executed
on each of the target processors.
Context - Supplies the value of the context parameter that is passed
to each function.
Parameter3 - Not used.
Return Value:
None
--*/
{
//
// Execute the specified function.
//
((PKIPI_BROADCAST_WORKER)(BroadcastFunction))((ULONG_PTR)Context);
KiIpiSignalPacketDone(SignalDone);
return;
}
VOID
KiIpiStallOnPacketTargets (
KAFFINITY TargetSet
)
/*++
Routine Description:
This function waits until the specified set of processors have signaled
their completion of a requested function.
N.B. The exact protocol used between the source and the target of an
interprocessor request is not specified. Minimally the source
must construct an appropriate packet and send the packet to a set
of specified targets. Each target receives the address of the packet
address as an argument, and minimally must clear the packet address
when the mutually agreed upon protocol allows. The target has three
options:
1. Capture necessary information, release the source by clearing
the packet address, execute the request in parallel with the
source, and return from the interrupt.
2. Execute the request in series with the source, release the
source by clearing the packet address, and return from the
interrupt.
3. Execute the request in series with the source, release the
source, wait for a reply from the source based on a packet
parameter, and return from the interrupt.
This function is provided to enable the source to synchronize with the
target for cases 2 and 3 above.
N.B. There is no support for method 3 above.
Arguments:
TargetSet - Supplies the the target set of IPI processors.
Return Value:
None.
--*/
{
volatile ULONG *Barrier;
PKPRCB Prcb;
//
// Wait until the target set of processors is zero in the current
// processor's packet.
//
Prcb = KeGetCurrentPrcb();
//
// If there is one and only one bit set in the target set, then wait
// on the target set. Otherwise, wait on the packet barrier.
//
Barrier = (volatile ULONG *)&Prcb->TargetSet;
if ((TargetSet & (TargetSet - 1)) != 0) {
Barrier = &Prcb->PacketBarrier;
}
while (*Barrier != 0) {
KeYieldProcessor();
}
return;
}
#endif