Leaked source code of windows server 2003
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

  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. KeIpiGenericCall (
  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. volatile LONG Count;
  46. KIRQL OldIrql;
  47. ULONG_PTR Status;
  48. #if !defined(NT_UP)
  49. KAFFINITY TargetProcessors;
  50. #endif
  51. //
  52. // Raise IRQL to synchronization level and acquire the reverse stall spin
  53. // lock to synchronize with other reverse stall functions.
  54. //
  55. OldIrql = KeGetCurrentIrql();
  56. if (OldIrql < SYNCH_LEVEL) {
  57. KfRaiseIrql(SYNCH_LEVEL);
  58. }
  59. KeAcquireSpinLockAtDpcLevel(&KiReverseStallIpiLock);
  60. //
  61. // Initialize the broadcast packet, compute the set of target processors,
  62. // and sent the packet to the target processors for execution.
  63. //
  64. #if !defined(NT_UP)
  65. Count = KeNumberProcessors;
  66. TargetProcessors = KeActiveProcessors & ~KeGetCurrentPrcb()->SetMember;
  67. if (TargetProcessors != 0) {
  68. KiIpiSendPacket(TargetProcessors,
  69. KiIpiGenericCallTarget,
  70. (PVOID)(ULONG_PTR)BroadcastFunction,
  71. (PVOID)Context,
  72. (PVOID)&Count);
  73. }
  74. //
  75. // Wait until all processors have entered the target routine and are
  76. // waiting.
  77. //
  78. while (Count != 1) {
  79. KeYieldProcessor();
  80. }
  81. #endif
  82. //
  83. // Raise IRQL to IPI_LEVEL, signal all other processors to proceed, and
  84. // call the specified function on the source processor.
  85. //
  86. KfRaiseIrql(IPI_LEVEL);
  87. Count = 0;
  88. Status = BroadcastFunction(Context);
  89. //
  90. // Wait until all of the target processors have finished capturing the
  91. // function parameters.
  92. //
  93. #if !defined(NT_UP)
  94. if (TargetProcessors != 0) {
  95. KiIpiStallOnPacketTargets(TargetProcessors);
  96. }
  97. #endif
  98. //
  99. // Release reverse stall spin lock, lower IRQL to its previous level,
  100. // and return the function execution status.
  101. //
  102. KeReleaseSpinLockFromDpcLevel(&KiReverseStallIpiLock);
  103. KeLowerIrql(OldIrql);
  104. return Status;
  105. }
  106. #if !defined(NT_UP)
  107. VOID
  108. KiIpiGenericCallTarget (
  109. IN PKIPI_CONTEXT SignalDone,
  110. IN PVOID BroadcastFunction,
  111. IN PVOID Context,
  112. IN PVOID Count
  113. )
  114. /*++
  115. Routine Description:
  116. This function is the target jacket function to execute a broadcast
  117. function on a set of target processors. The broadcast packet address
  118. is obtained, the specified parameters are captured, the broadcast
  119. packet address is cleared to signal the source processor to continue,
  120. and the specified function is executed.
  121. Arguments:
  122. SignalDone Supplies a pointer to a variable that is cleared when the
  123. requested operation has been performed.
  124. BroadcastFunction - Supplies the address of function that is executed
  125. on each of the target processors.
  126. Context - Supplies the value of the context parameter that is passed
  127. to each function.
  128. Count - Supplies the address of a down count synchronization variable.
  129. Return Value:
  130. None
  131. --*/
  132. {
  133. //
  134. // Decrement the synchronization count variable and wait for the value
  135. // to go to zero.
  136. //
  137. InterlockedDecrement((volatile LONG *)Count);
  138. while ((*(volatile LONG *)Count) != 0) {
  139. KeYieldProcessor();
  140. }
  141. //
  142. // Execute the specified function.
  143. //
  144. ((PKIPI_BROADCAST_WORKER)(ULONG_PTR)(BroadcastFunction))((ULONG_PTR)Context);
  145. KiIpiSignalPacketDone(SignalDone);
  146. return;
  147. }
  148. #endif