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.

261 lines
7.1 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->Link.Flink = WaitBlock->Link.Blink = NULL;
  37. RtlCopyMemory( &WaitBlock->WaitReplyMessage,
  38. WaitReplyMessage,
  39. WaitReplyMessage->h.u1.s1.TotalLength
  40. );
  41. *WaitBlockPtr = WaitBlock;
  42. return TRUE;
  43. }
  44. BOOLEAN
  45. CsrCreateWait(
  46. IN PLIST_ENTRY WaitQueue,
  47. IN CSR_WAIT_ROUTINE WaitRoutine,
  48. IN PCSR_THREAD WaitingThread,
  49. IN OUT PCSR_API_MSG WaitReplyMessage,
  50. IN PVOID WaitParameter)
  51. {
  52. PCSR_WAIT_BLOCK WaitBlock;
  53. if (!CsrInitializeWait( WaitRoutine,
  54. WaitingThread,
  55. WaitReplyMessage,
  56. WaitParameter,
  57. &WaitBlock
  58. )
  59. ) {
  60. return FALSE;
  61. }
  62. AcquireWaitListsLock();
  63. if ( WaitingThread->Flags & CSR_THREAD_DESTROYED ) {
  64. RtlFreeHeap( CsrHeap, 0, WaitBlock );
  65. ReleaseWaitListsLock();
  66. return FALSE;
  67. }
  68. WaitingThread->WaitBlock = WaitBlock;
  69. InsertTailList( WaitQueue, &WaitBlock->Link );
  70. ReleaseWaitListsLock();
  71. return( TRUE );
  72. }
  73. BOOLEAN
  74. CsrNotifyWaitBlock(
  75. IN PCSR_WAIT_BLOCK WaitBlock,
  76. IN PLIST_ENTRY WaitQueue,
  77. IN PVOID SatisfyParameter1,
  78. IN PVOID SatisfyParameter2,
  79. IN ULONG WaitFlags,
  80. IN BOOLEAN DereferenceThread
  81. )
  82. {
  83. if ((*WaitBlock->WaitRoutine)( WaitQueue,
  84. WaitBlock->WaitingThread,
  85. &WaitBlock->WaitReplyMessage,
  86. WaitBlock->WaitParameter,
  87. SatisfyParameter1,
  88. SatisfyParameter2,
  89. WaitFlags
  90. )
  91. ) {
  92. //
  93. // we don't take any locks other than the waitlist lock
  94. // because the only thing we have to worry about is the thread
  95. // going away beneath us and that's prevented by having
  96. // DestroyThread and DestroyProcess take the waitlist lock.
  97. //
  98. WaitBlock->WaitingThread->WaitBlock = NULL;
  99. if (WaitBlock->WaitReplyMessage.CaptureBuffer != NULL) {
  100. CsrReleaseCapturedArguments(&WaitBlock->WaitReplyMessage);
  101. }
  102. while (1) {
  103. NTSTATUS Status;
  104. Status = NtReplyPort (WaitBlock->WaitingThread->Process->ClientPort,
  105. (PPORT_MESSAGE)&WaitBlock->WaitReplyMessage);
  106. if (Status == STATUS_NO_MEMORY) {
  107. LARGE_INTEGER DelayTime;
  108. KdPrint (("CSRSS: Failed to reply to calling thread, retrying.\n"));
  109. DelayTime.QuadPart = Int32x32To64 (5000, -10000);
  110. NtDelayExecution (FALSE, &DelayTime);
  111. continue;
  112. }
  113. break;
  114. }
  115. if (DereferenceThread) {
  116. if ( WaitBlock->Link.Flink ) {
  117. RemoveEntryList( &WaitBlock->Link );
  118. }
  119. CsrDereferenceThread(WaitBlock->WaitingThread);
  120. RtlFreeHeap( CsrHeap, 0, WaitBlock );
  121. }
  122. else {
  123. //
  124. // indicate that this wait has been satisfied. when the
  125. // console unwinds to the point where it can release the
  126. // console lock, it will dereference the thread.
  127. //
  128. WaitBlock->WaitRoutine = NULL;
  129. }
  130. return( TRUE );
  131. }
  132. else {
  133. return( FALSE );
  134. }
  135. }
  136. BOOLEAN
  137. CsrNotifyWait(
  138. IN PLIST_ENTRY WaitQueue,
  139. IN BOOLEAN SatisfyAll,
  140. IN PVOID SatisfyParameter1,
  141. IN PVOID SatisfyParameter2
  142. )
  143. {
  144. PLIST_ENTRY ListHead, ListNext;
  145. PCSR_WAIT_BLOCK WaitBlock;
  146. BOOLEAN Result;
  147. Result = FALSE;
  148. AcquireWaitListsLock();
  149. ListHead = WaitQueue;
  150. ListNext = ListHead->Flink;
  151. while (ListNext != ListHead) {
  152. WaitBlock = CONTAINING_RECORD( ListNext, CSR_WAIT_BLOCK, Link );
  153. ListNext = ListNext->Flink;
  154. if (WaitBlock->WaitRoutine) {
  155. Result |= CsrNotifyWaitBlock( WaitBlock,
  156. WaitQueue,
  157. SatisfyParameter1,
  158. SatisfyParameter2,
  159. 0,
  160. FALSE
  161. );
  162. if (!SatisfyAll) {
  163. break;
  164. }
  165. }
  166. }
  167. ReleaseWaitListsLock();
  168. return( Result );
  169. }
  170. VOID
  171. CsrDereferenceWait(
  172. IN PLIST_ENTRY WaitQueue
  173. )
  174. {
  175. PLIST_ENTRY ListHead, ListNext;
  176. PCSR_WAIT_BLOCK WaitBlock;
  177. AcquireProcessStructureLock();
  178. AcquireWaitListsLock();
  179. ListHead = WaitQueue;
  180. ListNext = ListHead->Flink;
  181. while (ListNext != ListHead) {
  182. WaitBlock = CONTAINING_RECORD( ListNext, CSR_WAIT_BLOCK, Link );
  183. ListNext = ListNext->Flink;
  184. if (!WaitBlock->WaitRoutine) {
  185. if ( WaitBlock->Link.Flink ) {
  186. RemoveEntryList( &WaitBlock->Link );
  187. }
  188. CsrDereferenceThread(WaitBlock->WaitingThread);
  189. RtlFreeHeap( CsrHeap, 0, WaitBlock );
  190. }
  191. }
  192. ReleaseWaitListsLock();
  193. ReleaseProcessStructureLock();
  194. }
  195. VOID
  196. CsrMoveSatisfiedWait(
  197. IN PLIST_ENTRY DstWaitQueue,
  198. IN PLIST_ENTRY SrcWaitQueue
  199. )
  200. {
  201. PLIST_ENTRY ListHead, ListNext;
  202. PCSR_WAIT_BLOCK WaitBlock;
  203. AcquireWaitListsLock();
  204. ListHead = SrcWaitQueue;
  205. ListNext = ListHead->Flink;
  206. while (ListNext != ListHead) {
  207. WaitBlock = CONTAINING_RECORD( ListNext, CSR_WAIT_BLOCK, Link );
  208. ListNext = ListNext->Flink;
  209. if (!WaitBlock->WaitRoutine) {
  210. RemoveEntryList( &WaitBlock->Link );
  211. InsertTailList( DstWaitQueue, &WaitBlock->Link );
  212. }
  213. }
  214. ReleaseWaitListsLock();
  215. }