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
))
173 (void)InterlockedDecrementUL(&Prcb
->SignalDone
->CurrentPacket
[1]);
174 if (InterlockedCompareExchangeUL(&Prcb
->SignalDone
->CurrentPacket
[2], 0, 0))
176 while (0 != InterlockedCompareExchangeUL(&Prcb
->SignalDone
->CurrentPacket
[1], 0, 0));
178 ((VOID (NTAPI
*)(PVOID
))(Prcb
->SignalDone
->WorkerRoutine
))(Prcb
->SignalDone
->CurrentPacket
[0]);
179 InterlockedBitTestAndReset((PLONG
)&Prcb
->SignalDone
->TargetSet
, KeGetCurrentProcessorNumber());
180 if (InterlockedCompareExchangeUL(&Prcb
->SignalDone
->CurrentPacket
[2], 0, 0))
182 while (0 != InterlockedCompareExchangeUL(&Prcb
->SignalDone
->TargetSet
, 0, 0));
184 (void)InterlockedExchangePointer((PVOID
*)&Prcb
->SignalDone
, NULL
);
196 KeIpiGenericCall(IN PKIPI_BROADCAST_WORKER Function
,
197 IN ULONG_PTR Argument
)
200 KIRQL OldIrql
, OldIrql2
;
204 PKPRCB Prcb
= KeGetCurrentPrcb();
207 /* Raise to DPC level if required */
208 OldIrql
= KeGetCurrentIrql();
209 if (OldIrql
< DISPATCH_LEVEL
) KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
212 /* Get current processor count and affinity */
213 Count
= KeNumberProcessors
;
214 Affinity
= KeActiveProcessors
;
216 /* Exclude ourselves */
217 Affinity
&= ~Prcb
->SetMember
;
220 /* Acquire the IPI lock */
221 KeAcquireSpinLockAtDpcLevel(&KiReverseStallIpiLock
);
224 /* Make sure this is MP */
228 KiIpiSendPacket(Affinity
,
229 KiIpiGenericCallTarget
,
234 /* Spin until the other processors are ready */
238 KeMemoryBarrierWithoutFence();
243 /* Raise to IPI level */
244 KeRaiseIrql(IPI_LEVEL
, &OldIrql2
);
247 /* Let the other processors know it is time */
251 /* Call the function */
252 Status
= Function(Argument
);
255 /* If this is MP, wait for the other processors to finish */
259 ASSERT(Prcb
== KeGetCurrentPrcb());
262 ASSERTMSG("Not yet implemented\n", FALSE
);
266 /* Release the lock */
267 KeReleaseSpinLockFromDpcLevel(&KiReverseStallIpiLock
);
269 /* Lower IRQL back */
270 KeLowerIrql(OldIrql
);