Source code of Windows XP (NT5)
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.

257 lines
5.6 KiB

  1. /*++
  2. Copyright (c) 1993-1995 Microsoft Corporation
  3. Module Name:
  4. xipi.c
  5. Abstract:
  6. This module implements portable interprocessor interrup routines.
  7. Author:
  8. David N. Cutler (davec) 24-Apr-1993
  9. Environment:
  10. Kernel mode only.
  11. Revision History:
  12. --*/
  13. #include "ki.h"
  14. //
  15. // Define forward reference function prototypes.
  16. //
  17. VOID
  18. KiIpiGenericCallTarget (
  19. IN PKIPI_CONTEXT SignalDone,
  20. IN PVOID BroadcastFunction,
  21. IN PVOID Context,
  22. IN PVOID Parameter3
  23. );
  24. ULONG_PTR
  25. KiIpiGenericCall (
  26. IN PKIPI_BROADCAST_WORKER BroadcastFunction,
  27. IN ULONG_PTR Context
  28. )
  29. /*++
  30. Routine Description:
  31. This function executes the specified function on every processor in
  32. the host configuration in a synchronous manner, i.e., the function
  33. is executed on each target in series with the execution of the source
  34. processor.
  35. Arguments:
  36. BroadcastFunction - Supplies the address of function that is executed
  37. on each of the target processors.
  38. Context - Supplies the value of the context parameter that is passed
  39. to each function.
  40. Return Value:
  41. The value returned by the specified function on the source processor
  42. is returned as the function value.
  43. --*/
  44. {
  45. KIRQL OldIrql;
  46. ULONG_PTR Status;
  47. KAFFINITY TargetProcessors;
  48. //
  49. // Raise IRQL to the higher of the current level and synchronization
  50. // level to avoid a possible context switch.
  51. //
  52. KeRaiseIrql((KIRQL)(max(KiSynchIrql, KeGetCurrentIrql())), &OldIrql);
  53. //
  54. // Initialize the broadcast packet, compute the set of target processors,
  55. // and sent the packet to the target processors for execution.
  56. //
  57. #if !defined(NT_UP)
  58. TargetProcessors = KeActiveProcessors & ~KeGetCurrentPrcb()->SetMember;
  59. if (TargetProcessors != 0) {
  60. KiIpiSendPacket(TargetProcessors,
  61. KiIpiGenericCallTarget,
  62. (PVOID)BroadcastFunction,
  63. (PVOID)Context,
  64. NULL);
  65. }
  66. #endif
  67. //
  68. // Execute function of source processor and capture return status.
  69. //
  70. Status = BroadcastFunction(Context);
  71. //
  72. // Wait until all of the target processors have finished capturing the
  73. // function parameters.
  74. //
  75. #if !defined(NT_UP)
  76. if (TargetProcessors != 0) {
  77. KiIpiStallOnPacketTargets(TargetProcessors);
  78. }
  79. #endif
  80. //
  81. // Lower IRQL to its previous level and return the function execution
  82. // status.
  83. //
  84. KeLowerIrql(OldIrql);
  85. return Status;
  86. }
  87. #if !defined(NT_UP)
  88. VOID
  89. KiIpiGenericCallTarget (
  90. IN PKIPI_CONTEXT SignalDone,
  91. IN PVOID BroadcastFunction,
  92. IN PVOID Context,
  93. IN PVOID Parameter3
  94. )
  95. /*++
  96. Routine Description:
  97. This function is the target jacket function to execute a broadcast
  98. function on a set of target processors. The broadcast packet address
  99. is obtained, the specified parameters are captured, the broadcast
  100. packet address is cleared to signal the source processor to continue,
  101. and the specified function is executed.
  102. Arguments:
  103. SignalDone Supplies a pointer to a variable that is cleared when the
  104. requested operation has been performed.
  105. BroadcastFunction - Supplies the address of function that is executed
  106. on each of the target processors.
  107. Context - Supplies the value of the context parameter that is passed
  108. to each function.
  109. Parameter3 - Not used.
  110. Return Value:
  111. None
  112. --*/
  113. {
  114. //
  115. // Execute the specified function.
  116. //
  117. ((PKIPI_BROADCAST_WORKER)(BroadcastFunction))((ULONG_PTR)Context);
  118. KiIpiSignalPacketDone(SignalDone);
  119. return;
  120. }
  121. VOID
  122. KiIpiStallOnPacketTargets (
  123. KAFFINITY TargetSet
  124. )
  125. /*++
  126. Routine Description:
  127. This function waits until the specified set of processors have signaled
  128. their completion of a requested function.
  129. N.B. The exact protocol used between the source and the target of an
  130. interprocessor request is not specified. Minimally the source
  131. must construct an appropriate packet and send the packet to a set
  132. of specified targets. Each target receives the address of the packet
  133. address as an argument, and minimally must clear the packet address
  134. when the mutually agreed upon protocol allows. The target has three
  135. options:
  136. 1. Capture necessary information, release the source by clearing
  137. the packet address, execute the request in parallel with the
  138. source, and return from the interrupt.
  139. 2. Execute the request in series with the source, release the
  140. source by clearing the packet address, and return from the
  141. interrupt.
  142. 3. Execute the request in series with the source, release the
  143. source, wait for a reply from the source based on a packet
  144. parameter, and return from the interrupt.
  145. This function is provided to enable the source to synchronize with the
  146. target for cases 2 and 3 above.
  147. N.B. There is no support for method 3 above.
  148. Arguments:
  149. TargetSet - Supplies the the target set of IPI processors.
  150. Return Value:
  151. None.
  152. --*/
  153. {
  154. volatile ULONG *Barrier;
  155. PKPRCB Prcb;
  156. //
  157. // Wait until the target set of processors is zero in the current
  158. // processor's packet.
  159. //
  160. Prcb = KeGetCurrentPrcb();
  161. //
  162. // If there is one and only one bit set in the target set, then wait
  163. // on the target set. Otherwise, wait on the packet barrier.
  164. //
  165. Barrier = (volatile ULONG *)&Prcb->TargetSet;
  166. if ((TargetSet & (TargetSet - 1)) != 0) {
  167. Barrier = &Prcb->PacketBarrier;
  168. }
  169. while (*Barrier != 0) {
  170. KeYieldProcessor();
  171. }
  172. return;
  173. }
  174. #endif