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.

261 lines
6.9 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. wait.c
  5. Abstract:
  6. This module contains the primitives to implement the Wait functions
  7. on the Server side of the Client-Server Runtime Subsystem to the
  8. Session Manager SubSystem.
  9. Author:
  10. Steve Wood (stevewo) 8-Oct-1990
  11. Revision History:
  12. --*/
  13. #include "csrsrv.h"
  14. BOOLEAN
  15. CsrInitializeWait(
  16. IN CSR_WAIT_ROUTINE WaitRoutine,
  17. IN PCSR_THREAD WaitingThread,
  18. IN OUT PCSR_API_MSG WaitReplyMessage,
  19. IN PVOID WaitParameter,
  20. OUT PCSR_WAIT_BLOCK *WaitBlockPtr
  21. )
  22. {
  23. ULONG Length;
  24. PCSR_WAIT_BLOCK WaitBlock;
  25. Length = sizeof( *WaitBlock ) - sizeof( WaitBlock->WaitReplyMessage ) +
  26. WaitReplyMessage->h.u1.s1.TotalLength;
  27. WaitBlock = RtlAllocateHeap( CsrHeap, MAKE_TAG( WAIT_TAG ), Length );
  28. if (WaitBlock == NULL) {
  29. WaitReplyMessage->ReturnValue = (ULONG)STATUS_NO_MEMORY;
  30. return( FALSE );
  31. }
  32. WaitBlock->Length = Length;
  33. WaitBlock->WaitingThread = WaitingThread;
  34. WaitBlock->WaitParameter = WaitParameter;
  35. WaitBlock->WaitRoutine = WaitRoutine;
  36. WaitBlock->UserLink.Flink = WaitBlock->UserLink.Blink = NULL;
  37. WaitBlock->Link.Flink = WaitBlock->Link.Blink = NULL;
  38. RtlMoveMemory( &WaitBlock->WaitReplyMessage,
  39. WaitReplyMessage,
  40. WaitReplyMessage->h.u1.s1.TotalLength
  41. );
  42. *WaitBlockPtr = WaitBlock;
  43. return TRUE;
  44. }
  45. BOOLEAN
  46. CsrCreateWait(
  47. IN PLIST_ENTRY WaitQueue,
  48. IN CSR_WAIT_ROUTINE WaitRoutine,
  49. IN PCSR_THREAD WaitingThread,
  50. IN OUT PCSR_API_MSG WaitReplyMessage,
  51. IN PVOID WaitParameter,
  52. IN PLIST_ENTRY UserLinkListHead OPTIONAL
  53. )
  54. {
  55. PCSR_WAIT_BLOCK WaitBlock;
  56. if (!CsrInitializeWait( WaitRoutine,
  57. WaitingThread,
  58. WaitReplyMessage,
  59. WaitParameter,
  60. &WaitBlock
  61. )
  62. ) {
  63. return FALSE;
  64. }
  65. AcquireWaitListsLock();
  66. if ( WaitingThread->Flags & CSR_THREAD_DESTROYED ) {
  67. RtlFreeHeap( CsrHeap, 0, WaitBlock );
  68. ReleaseWaitListsLock();
  69. return FALSE;
  70. }
  71. WaitingThread->WaitBlock = WaitBlock;
  72. InsertTailList( WaitQueue, &WaitBlock->Link );
  73. if ( ARGUMENT_PRESENT(UserLinkListHead) ) {
  74. InsertTailList( UserLinkListHead, &WaitBlock->UserLink );
  75. }
  76. ReleaseWaitListsLock();
  77. return( TRUE );
  78. }
  79. BOOLEAN
  80. CsrNotifyWaitBlock(
  81. IN PCSR_WAIT_BLOCK WaitBlock,
  82. IN PLIST_ENTRY WaitQueue,
  83. IN PVOID SatisfyParameter1,
  84. IN PVOID SatisfyParameter2,
  85. IN ULONG WaitFlags,
  86. IN BOOLEAN DereferenceThread
  87. )
  88. {
  89. if ((*WaitBlock->WaitRoutine)( WaitQueue,
  90. WaitBlock->WaitingThread,
  91. &WaitBlock->WaitReplyMessage,
  92. WaitBlock->WaitParameter,
  93. SatisfyParameter1,
  94. SatisfyParameter2,
  95. WaitFlags
  96. )
  97. ) {
  98. //
  99. // we don't take any locks other than the waitlist lock
  100. // because the only thing we have to worry about is the thread
  101. // going away beneath us and that's prevented by having
  102. // DestroyThread and DestroyProcess take the waitlist lock.
  103. //
  104. WaitBlock->WaitingThread->WaitBlock = NULL;
  105. if (WaitBlock->WaitReplyMessage.CaptureBuffer != NULL) {
  106. CsrReleaseCapturedArguments(&WaitBlock->WaitReplyMessage);
  107. }
  108. NtReplyPort( WaitBlock->WaitingThread->Process->ClientPort,
  109. (PPORT_MESSAGE)&WaitBlock->WaitReplyMessage
  110. );
  111. if (DereferenceThread) {
  112. if ( WaitBlock->Link.Flink ) {
  113. RemoveEntryList( &WaitBlock->Link );
  114. }
  115. if ( WaitBlock->UserLink.Flink ) {
  116. RemoveEntryList( &WaitBlock->UserLink );
  117. }
  118. CsrDereferenceThread(WaitBlock->WaitingThread);
  119. RtlFreeHeap( CsrHeap, 0, WaitBlock );
  120. }
  121. else {
  122. //
  123. // indicate that this wait has been satisfied. when the
  124. // console unwinds to the point where it can release the
  125. // console lock, it will dereference the thread.
  126. //
  127. WaitBlock->WaitRoutine = NULL;
  128. }
  129. return( TRUE );
  130. }
  131. else {
  132. return( FALSE );
  133. }
  134. }
  135. BOOLEAN
  136. CsrNotifyWait(
  137. IN PLIST_ENTRY WaitQueue,
  138. IN BOOLEAN SatisfyAll,
  139. IN PVOID SatisfyParameter1,
  140. IN PVOID SatisfyParameter2
  141. )
  142. {
  143. PLIST_ENTRY ListHead, ListNext;
  144. PCSR_WAIT_BLOCK WaitBlock;
  145. BOOLEAN Result;
  146. Result = FALSE;
  147. AcquireWaitListsLock();
  148. ListHead = WaitQueue;
  149. ListNext = ListHead->Flink;
  150. while (ListNext != ListHead) {
  151. WaitBlock = CONTAINING_RECORD( ListNext, CSR_WAIT_BLOCK, Link );
  152. ListNext = ListNext->Flink;
  153. if (WaitBlock->WaitRoutine) {
  154. Result |= CsrNotifyWaitBlock( WaitBlock,
  155. WaitQueue,
  156. SatisfyParameter1,
  157. SatisfyParameter2,
  158. 0,
  159. FALSE
  160. );
  161. if (!SatisfyAll) {
  162. break;
  163. }
  164. }
  165. }
  166. ReleaseWaitListsLock();
  167. return( Result );
  168. }
  169. VOID
  170. CsrDereferenceWait(
  171. IN PLIST_ENTRY WaitQueue
  172. )
  173. {
  174. PLIST_ENTRY ListHead, ListNext;
  175. PCSR_WAIT_BLOCK WaitBlock;
  176. AcquireProcessStructureLock();
  177. AcquireWaitListsLock();
  178. ListHead = WaitQueue;
  179. ListNext = ListHead->Flink;
  180. while (ListNext != ListHead) {
  181. WaitBlock = CONTAINING_RECORD( ListNext, CSR_WAIT_BLOCK, Link );
  182. ListNext = ListNext->Flink;
  183. if (!WaitBlock->WaitRoutine) {
  184. if ( WaitBlock->Link.Flink ) {
  185. RemoveEntryList( &WaitBlock->Link );
  186. }
  187. if ( WaitBlock->UserLink.Flink ) {
  188. RemoveEntryList( &WaitBlock->UserLink );
  189. }
  190. CsrDereferenceThread(WaitBlock->WaitingThread);
  191. RtlFreeHeap( CsrHeap, 0, WaitBlock );
  192. }
  193. }
  194. ReleaseWaitListsLock();
  195. ReleaseProcessStructureLock();
  196. }
  197. VOID
  198. CsrMoveSatisfiedWait(
  199. IN PLIST_ENTRY DstWaitQueue,
  200. IN PLIST_ENTRY SrcWaitQueue
  201. )
  202. {
  203. PLIST_ENTRY ListHead, ListNext;
  204. PCSR_WAIT_BLOCK WaitBlock;
  205. AcquireWaitListsLock();
  206. ListHead = SrcWaitQueue;
  207. ListNext = ListHead->Flink;
  208. while (ListNext != ListHead) {
  209. WaitBlock = CONTAINING_RECORD( ListNext, CSR_WAIT_BLOCK, Link );
  210. ListNext = ListNext->Flink;
  211. if (!WaitBlock->WaitRoutine) {
  212. RemoveEntryList( &WaitBlock->Link );
  213. InsertTailList( DstWaitQueue, &WaitBlock->Link );
  214. }
  215. }
  216. ReleaseWaitListsLock();
  217. }