2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ke/ipi.c
5 * PURPOSE: Inter-Processor Packet Interface
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES ******************************************************************/
15 /* GLOBALS *******************************************************************/
17 extern KSPIN_LOCK KiReverseStallIpiLock
;
19 /* PRIVATE FUNCTIONS *********************************************************/
23 KiIpiGenericCallTarget(IN PKIPI_CONTEXT PacketContext
,
24 IN PVOID BroadcastFunction
,
29 ASSERTMSG("Not yet implemented\n", FALSE
);
34 KiIpiSend(IN KAFFINITY TargetProcessors
,
38 ASSERTMSG("Not yet implemented\n", FALSE
);
43 KiIpiSendPacket(IN KAFFINITY TargetProcessors
,
44 IN PKIPI_WORKER WorkerFunction
,
45 IN PKIPI_BROADCAST_WORKER BroadcastFunction
,
50 ASSERTMSG("Not yet implemented\n", FALSE
);
55 KiIpiSignalPacketDone(IN PKIPI_CONTEXT PacketContext
)
58 ASSERTMSG("Not yet implemented\n", FALSE
);
63 KiIpiSignalPacketDoneAndStall(IN PKIPI_CONTEXT PacketContext
,
64 IN
volatile PULONG ReverseStall
)
67 ASSERTMSG("Not yet implemented\n", FALSE
);
73 KiIpiSendRequest(IN KAFFINITY TargetSet
,
81 for (i
= 0, Current
= 1; i
< KeNumberProcessors
; i
++, Current
<<= 1)
83 if (TargetSet
& Current
)
85 /* Get the PRCB for this CPU */
86 Prcb
= KiProcessorBlock
[i
];
88 InterlockedBitTestAndSet((PLONG
)&Prcb
->IpiFrozen
, IpiRequest
);
97 KiIpiSendPacket(IN KAFFINITY TargetSet
,
98 IN PKIPI_BROADCAST_WORKER WorkerRoutine
,
99 IN ULONG_PTR Argument
,
101 IN BOOLEAN Synchronize
)
106 PKPRCB Prcb
, CurrentPrcb
;
109 ASSERT(KeGetCurrentIrql() == SYNCH_LEVEL
);
111 CurrentPrcb
= KeGetCurrentPrcb();
112 (void)InterlockedExchangeUL(&CurrentPrcb
->TargetSet
, TargetSet
);
113 (void)InterlockedExchangeUL(&CurrentPrcb
->WorkerRoutine
, (ULONG_PTR
)WorkerRoutine
);
114 (void)InterlockedExchangePointer(&CurrentPrcb
->CurrentPacket
[0], Argument
);
115 (void)InterlockedExchangeUL(&CurrentPrcb
->CurrentPacket
[1], Count
);
116 (void)InterlockedExchangeUL(&CurrentPrcb
->CurrentPacket
[2], Synchronize
? 1 : 0);
118 for (i
= 0, Processor
= 1; i
< KeNumberProcessors
; i
++, Processor
<<= 1)
120 if (TargetSet
& Processor
)
122 Prcb
= KiProcessorBlock
[i
];
123 while (0 != InterlockedCompareExchangeUL(&Prcb
->SignalDone
, (LONG
)CurrentPrcb
, 0));
124 InterlockedBitTestAndSet((PLONG
)&Prcb
->IpiFrozen
, IPI_SYNCH_REQUEST
);
125 if (Processor
!= CurrentPrcb
->SetMember
)
131 if (TargetSet
& CurrentPrcb
->SetMember
)
133 KeRaiseIrql(IPI_LEVEL
, &oldIrql
);
134 KiIpiServiceRoutine(NULL
, NULL
);
135 KeLowerIrql(oldIrql
);
141 /* PUBLIC FUNCTIONS **********************************************************/
148 KiIpiServiceRoutine(IN PKTRAP_FRAME TrapFrame
,
149 IN PKEXCEPTION_FRAME ExceptionFrame
)
153 ASSERT(KeGetCurrentIrql() == IPI_LEVEL
);
155 Prcb
= KeGetCurrentPrcb();
157 if (InterlockedBitTestAndReset((PLONG
)&Prcb
->IpiFrozen
, IPI_APC
))
159 HalRequestSoftwareInterrupt(APC_LEVEL
);
162 if (InterlockedBitTestAndReset((PLONG
)&Prcb
->IpiFrozen
, IPI_DPC
))
164 Prcb
->DpcInterruptRequested
= TRUE
;
165 HalRequestSoftwareInterrupt(DISPATCH_LEVEL
);
168 if (InterlockedBitTestAndReset((PLONG
)&Prcb
->IpiFrozen
, IPI_SYNCH_REQUEST
))
170 (void)InterlockedDecrementUL(&Prcb
->SignalDone
->CurrentPacket
[1]);
171 if (InterlockedCompareExchangeUL(&Prcb
->SignalDone
->CurrentPacket
[2], 0, 0))
173 while (0 != InterlockedCompareExchangeUL(&Prcb
->SignalDone
->CurrentPacket
[1], 0, 0));
175 ((VOID (NTAPI
*)(PVOID
))(Prcb
->SignalDone
->WorkerRoutine
))(Prcb
->SignalDone
->CurrentPacket
[0]);
176 InterlockedBitTestAndReset((PLONG
)&Prcb
->SignalDone
->TargetSet
, KeGetCurrentProcessorNumber());
177 if (InterlockedCompareExchangeUL(&Prcb
->SignalDone
->CurrentPacket
[2], 0, 0))
179 while (0 != InterlockedCompareExchangeUL(&Prcb
->SignalDone
->TargetSet
, 0, 0));
181 (void)InterlockedExchangePointer(&Prcb
->SignalDone
, NULL
);
192 KeIpiGenericCall(IN PKIPI_BROADCAST_WORKER Function
,
193 IN ULONG_PTR Argument
)
196 KIRQL OldIrql
, OldIrql2
;
200 PKPRCB Prcb
= KeGetCurrentPrcb();
203 /* Raise to DPC level if required */
204 OldIrql
= KeGetCurrentIrql();
205 if (OldIrql
< DISPATCH_LEVEL
) KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
208 /* Get current processor count and affinity */
209 Count
= KeNumberProcessors
;
210 Affinity
= KeActiveProcessors
;
212 /* Exclude ourselves */
213 Affinity
&= ~Prcb
->SetMember
;
216 /* Acquire the IPI lock */
217 KeAcquireSpinLockAtDpcLevel(&KiReverseStallIpiLock
);
220 /* Make sure this is MP */
224 KiIpiSendPacket(Affinity
,
225 KiIpiGenericCallTarget
,
230 /* Spin until the other processors are ready */
234 KeMemoryBarrierWithoutFence();
239 /* Raise to IPI level */
240 KeRaiseIrql(IPI_LEVEL
, &OldIrql2
);
243 /* Let the other processors know it is time */
247 /* Call the function */
248 Status
= Function(Argument
);
251 /* If this is MP, wait for the other processors to finish */
255 ASSERT(Prcb
== KeGetCurrentPrcb());
258 ASSERTMSG("Not yet implemented\n", FALSE
);
262 /* Release the lock */
263 KeReleaseSpinLockFromDpcLevel(&KiReverseStallIpiLock
);
265 /* Lower IRQL back */
266 KeLowerIrql(OldIrql
);