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.

229 lines
5.7 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. calldown.c
  5. Abstract:
  6. This module implements the calldown routines for coordinating between multiple
  7. calldowns/callouts.
  8. Calldowns refer to invocation of a mini rdr routine by the wrapper while callouts
  9. refer to invocations made by the wrapper to other components, e.g., TDI.
  10. Revision History:
  11. Balan Sethu Raman [SethuR] 15-Feb-1995
  12. Notes:
  13. There are a number of instances in which the same function needs to be invoked
  14. on all the mini redirectors that have been registered. The RDBSS needs to be
  15. synchronized with the completion of the invocation of all these calls. It
  16. will be beneficial to invoke these calls in parallel when more than one
  17. mini redirectors are registered. This module provides the framework for such
  18. calldowns. This is provided by the routine RxCalldownMiniRedirectors.
  19. An instance of coordination between multiple callouts occurs when a connect
  20. request is initiated across multiple instances in parallel. The data structures
  21. corresponding to this are defined in rxcep.h for now since the usage is restricted
  22. to the connection engine. It would be a suitable candidate for migration if more uses
  23. are found later.
  24. --*/
  25. #include "precomp.h"
  26. #pragma hdrstop
  27. #include "mrx.h"
  28. #ifdef ALLOC_PRAGMA
  29. #pragma alloc_text(PAGE, RxInitializeMRxCalldownContext)
  30. #pragma alloc_text(PAGE, RxCompleteMRxCalldownRoutine)
  31. #pragma alloc_text(PAGE, RxCalldownMRxWorkerRoutine)
  32. #pragma alloc_text(PAGE, RxCalldownMiniRedirectors)
  33. #endif
  34. VOID
  35. RxInitializeMRxCalldownContext(
  36. PMRX_CALLDOWN_CONTEXT pContext,
  37. PRDBSS_DEVICE_OBJECT pMRxDeviceObject,
  38. PMRX_CALLDOWN_ROUTINE pRoutine,
  39. PVOID pParameter)
  40. /*++
  41. Routine Description:
  42. This routine initializes a mini redirector calldown context.
  43. Arguments:
  44. pContext - the MRx calldown context
  45. Notes:
  46. --*/
  47. {
  48. PAGED_CODE();
  49. pContext->pMRxDeviceObject = pMRxDeviceObject;
  50. pContext->pRoutine = pRoutine;
  51. pContext->pParameter = pParameter;
  52. pContext->pCompletionContext = NULL;
  53. }
  54. VOID
  55. RxCompleteMRxCalldownRoutine(
  56. PMRX_CALLDOWN_COMPLETION_CONTEXT pCompletionContext)
  57. /*++
  58. Routine Description:
  59. This routine constitutes the tail of a mini redirector calldown completion.
  60. It encapsulates the synchronization mechanism for the resumption of RDBSS
  61. Arguments:
  62. pCompletionContext - the MRx calldown completion context
  63. Notes:
  64. --*/
  65. {
  66. PAGED_CODE();
  67. if (pCompletionContext != NULL) {
  68. LONG WaitCount;
  69. WaitCount = InterlockedDecrement(&pCompletionContext->WaitCount);
  70. if (WaitCount == 0) {
  71. KeSetEvent(
  72. &pCompletionContext->Event,
  73. IO_NO_INCREMENT,
  74. FALSE);
  75. }
  76. }
  77. }
  78. VOID
  79. RxCalldownMRxWorkerRoutine(
  80. PMRX_CALLDOWN_CONTEXT pContext)
  81. /*++
  82. Routine Description:
  83. This is the calldown worker routine that invokes the appropriate mini
  84. redirector routine and follows it up with a call to the completion routine.
  85. Arguments:
  86. pContext - the MRx calldown context
  87. Notes:
  88. --*/
  89. {
  90. PRDBSS_DEVICE_OBJECT pMRxDeviceObject = pContext->pMRxDeviceObject;
  91. PAGED_CODE();
  92. if ( pContext->pRoutine != NULL) {
  93. pContext->CompletionStatus = (pContext->pRoutine)(pContext->pParameter);
  94. }
  95. RxCompleteMRxCalldownRoutine(pContext->pCompletionContext);
  96. }
  97. NTSTATUS
  98. RxCalldownMiniRedirectors(
  99. LONG NumberOfMiniRdrs,
  100. PMRX_CALLDOWN_CONTEXT pCalldownContext,
  101. BOOLEAN PostCalldowns)
  102. /*++
  103. Routine Description:
  104. This routine encapsulates the multiple mini redirector calldown.
  105. Arguments:
  106. NumberOfMiniRdrs - the number of mini redirectors
  107. pCalldownContext - the MRx calldown context array for the mini redirectors
  108. PostCalldowns - if TRUE the calldown employs multiple threads
  109. Notes:
  110. The three parameters for this routine constitute an effort to provide
  111. maximum flexibility. The values should be carefully specified for
  112. utmost efficiency.
  113. Since the different calldowns can choose to employ a subset of the
  114. mini redirectors registered at any time the calldown mechanism accepts an
  115. array of calldown contexts and the appropriate number.
  116. In most cases when there is only one mini redirector registered it is
  117. necessary that the context switches be minimized. The routine provides
  118. for this by having an explicit specification (PostCalldowns ) parameter.
  119. --*/
  120. {
  121. LONG Index;
  122. PMRX_CALLDOWN_CONTEXT pContext;
  123. MRX_CALLDOWN_COMPLETION_CONTEXT CompletionContext;
  124. PAGED_CODE();
  125. if (NumberOfMiniRdrs == 0) {
  126. return STATUS_SUCCESS;
  127. }
  128. pContext = pCalldownContext;
  129. CompletionContext.WaitCount = NumberOfMiniRdrs;
  130. KeInitializeEvent(
  131. &CompletionContext.Event,
  132. NotificationEvent,
  133. FALSE);
  134. for (Index = 0,pContext = pCalldownContext;
  135. Index < NumberOfMiniRdrs;
  136. Index++,pContext++) {
  137. pContext->pCompletionContext = &CompletionContext;
  138. }
  139. if (PostCalldowns) {
  140. for (Index = 0, pContext = pCalldownContext;
  141. Index < NumberOfMiniRdrs;
  142. Index++,pContext++) {
  143. RxPostToWorkerThread(
  144. RxFileSystemDeviceObject,
  145. CriticalWorkQueue,
  146. &pContext->WorkQueueItem,
  147. RxCalldownMRxWorkerRoutine,
  148. pContext);
  149. }
  150. } else {
  151. for (Index = 0, pContext = pCalldownContext;
  152. Index < NumberOfMiniRdrs;
  153. Index++,pContext++) {
  154. RxCalldownMRxWorkerRoutine(&pCalldownContext[Index]);
  155. }
  156. }
  157. KeWaitForSingleObject(
  158. &CompletionContext.Event,
  159. Executive,
  160. KernelMode,
  161. FALSE,
  162. NULL);
  163. return STATUS_SUCCESS;
  164. }
  165.