You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
213 lines
4.7 KiB
213 lines
4.7 KiB
/*++
|
|
|
|
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
|
|
KeIpiGenericCall (
|
|
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.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
volatile LONG Count;
|
|
KIRQL OldIrql;
|
|
ULONG_PTR Status;
|
|
|
|
#if !defined(NT_UP)
|
|
|
|
KAFFINITY TargetProcessors;
|
|
|
|
#endif
|
|
|
|
//
|
|
// Raise IRQL to synchronization level and acquire the reverse stall spin
|
|
// lock to synchronize with other reverse stall functions.
|
|
//
|
|
|
|
OldIrql = KeGetCurrentIrql();
|
|
if (OldIrql < SYNCH_LEVEL) {
|
|
KfRaiseIrql(SYNCH_LEVEL);
|
|
}
|
|
|
|
KeAcquireSpinLockAtDpcLevel(&KiReverseStallIpiLock);
|
|
|
|
//
|
|
// Initialize the broadcast packet, compute the set of target processors,
|
|
// and sent the packet to the target processors for execution.
|
|
//
|
|
|
|
#if !defined(NT_UP)
|
|
|
|
Count = KeNumberProcessors;
|
|
TargetProcessors = KeActiveProcessors & ~KeGetCurrentPrcb()->SetMember;
|
|
if (TargetProcessors != 0) {
|
|
KiIpiSendPacket(TargetProcessors,
|
|
KiIpiGenericCallTarget,
|
|
(PVOID)(ULONG_PTR)BroadcastFunction,
|
|
(PVOID)Context,
|
|
(PVOID)&Count);
|
|
}
|
|
|
|
//
|
|
// Wait until all processors have entered the target routine and are
|
|
// waiting.
|
|
//
|
|
|
|
while (Count != 1) {
|
|
KeYieldProcessor();
|
|
}
|
|
|
|
#endif
|
|
|
|
//
|
|
// Raise IRQL to IPI_LEVEL, signal all other processors to proceed, and
|
|
// call the specified function on the source processor.
|
|
//
|
|
|
|
KfRaiseIrql(IPI_LEVEL);
|
|
Count = 0;
|
|
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
|
|
|
|
//
|
|
// Release reverse stall spin lock, lower IRQL to its previous level,
|
|
// and return the function execution status.
|
|
//
|
|
|
|
KeReleaseSpinLockFromDpcLevel(&KiReverseStallIpiLock);
|
|
KeLowerIrql(OldIrql);
|
|
return Status;
|
|
}
|
|
|
|
#if !defined(NT_UP)
|
|
|
|
VOID
|
|
KiIpiGenericCallTarget (
|
|
IN PKIPI_CONTEXT SignalDone,
|
|
IN PVOID BroadcastFunction,
|
|
IN PVOID Context,
|
|
IN PVOID Count
|
|
)
|
|
|
|
/*++
|
|
|
|
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.
|
|
|
|
Count - Supplies the address of a down count synchronization variable.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
//
|
|
// Decrement the synchronization count variable and wait for the value
|
|
// to go to zero.
|
|
//
|
|
|
|
InterlockedDecrement((volatile LONG *)Count);
|
|
while ((*(volatile LONG *)Count) != 0) {
|
|
KeYieldProcessor();
|
|
}
|
|
|
|
//
|
|
// Execute the specified function.
|
|
//
|
|
|
|
((PKIPI_BROADCAST_WORKER)(ULONG_PTR)(BroadcastFunction))((ULONG_PTR)Context);
|
|
KiIpiSignalPacketDone(SignalDone);
|
|
return;
|
|
}
|
|
|
|
#endif
|