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.

222 lines
5.2 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. critsect.asm
  5. Abstract:
  6. This module implements functions to support user mode critical sections.
  7. Author:
  8. David N. Cutler (davec) 25-Jun-2000
  9. Environment:
  10. Any mode.
  11. Revision History:
  12. --*/
  13. #include "ldrp.h"
  14. #include "ntos.h"
  15. NTSTATUS
  16. RtlEnterCriticalSection(
  17. IN PRTL_CRITICAL_SECTION CriticalSection
  18. )
  19. /*++
  20. Routine Description:
  21. This function enters a critical section.
  22. Arguments:
  23. CriticalSection - Supplies a pointer to a critical section.
  24. Return Value:
  25. STATUS_SUCCESS is returned or a exception can be raised if the wait
  26. for the resoruce fails.
  27. --*/
  28. {
  29. ULONG64 SpinCount;
  30. HANDLE Thread;
  31. //
  32. // If the current thread owns the critical section, then increment
  33. // the lock count and the recursion count and return success.
  34. //
  35. Thread = NtCurrentTeb()->ClientId.UniqueThread;
  36. if (Thread == CriticalSection->OwningThread) {
  37. ASSERT(CriticalSection->LockCount >= 0);
  38. InterlockedIncrement(&CriticalSection->LockCount);
  39. CriticalSection->RecursionCount += 1;
  40. return STATUS_SUCCESS;
  41. }
  42. //
  43. // If the critical section spin count is nonzero, then spin attempting
  44. // to enter critical section until the critical section is entered, the
  45. // spin count reaches zero, or there are waiters for the critical section.
  46. //
  47. SpinCount = CriticalSection->SpinCount;
  48. if (SpinCount != 0) {
  49. do {
  50. //
  51. // If the critical section is free, then attempt to enter the
  52. // critical section. Otherwise, spin if the spin count is not
  53. // zero and there are no waiters for the critical section.
  54. //
  55. if (CriticalSection->LockCount == - 1) {
  56. if (InterlockedCompareExchange(&CriticalSection->LockCount,
  57. 0,
  58. - 1) == - 1) {
  59. CriticalSection->OwningThread = Thread;
  60. CriticalSection->RecursionCount = 1;
  61. return STATUS_SUCCESS;
  62. }
  63. } else if (CriticalSection->LockCount > 0) {
  64. break;
  65. }
  66. SpinCount -= 1;
  67. } while (SpinCount != 0);
  68. }
  69. //
  70. // Attempt to enter the critical section. If the critical section is not
  71. // free, then wait for ownership to be granted.
  72. //
  73. if (InterlockedIncrement(&CriticalSection->LockCount) != 0) {
  74. RtlpWaitForCriticalSection(CriticalSection);
  75. }
  76. //
  77. // Set owning thread, initialization the recusrion count, and return
  78. // success.
  79. //
  80. CriticalSection->OwningThread = Thread;
  81. CriticalSection->RecursionCount = 1;
  82. return STATUS_SUCCESS;
  83. }
  84. NTSTATUS
  85. RtlLeaveCriticalSection(
  86. IN PRTL_CRITICAL_SECTION CriticalSection
  87. )
  88. /*++
  89. Routine Description:
  90. This function leaves a critical section.
  91. Arguments:
  92. CriticalSection - Supplies a pointer to a critical section.
  93. Return Value:
  94. STATUS_SUCCESS is returned.
  95. --*/
  96. {
  97. //
  98. // Decrement the recursion count. If the resultant recursion count is
  99. // zero, then leave the critical section.
  100. //
  101. ASSERT(NtCurrentTeb()->ClientId.UniqueThread == CriticalSection->OwningThread);
  102. if ((CriticalSection->RecursionCount -= 1) == 0) {
  103. CriticalSection->OwningThread = NULL;
  104. if (InterlockedDecrement(&CriticalSection->LockCount) >= 0) {
  105. RtlpUnWaitCriticalSection(CriticalSection);
  106. }
  107. } else {
  108. InterlockedDecrement(&CriticalSection->LockCount);
  109. }
  110. return STATUS_SUCCESS;
  111. }
  112. BOOLEAN
  113. RtlTryEnterCriticalSection (
  114. IN PRTL_CRITICAL_SECTION CriticalSection
  115. )
  116. /*++
  117. Routine Description:
  118. This function attempts to enter a critical section without blocking.
  119. Arguments:
  120. CriticalSection (a0) - Supplies a pointer to a critical section.
  121. Return Value:
  122. If the critical section was successfully entered, then a value of TRUE
  123. is returned. Otherwise, a value of FALSE is returned.
  124. --*/
  125. {
  126. HANDLE Thread;
  127. //
  128. // If the current thread owns the critical section, then increment
  129. // the lock count and the recursion count and return TRUE.
  130. //
  131. Thread = NtCurrentTeb()->ClientId.UniqueThread;
  132. if (Thread == CriticalSection->OwningThread) {
  133. ASSERT(CriticalSection->LockCount >= 0);
  134. InterlockedIncrement(&CriticalSection->LockCount);
  135. CriticalSection->RecursionCount += 1;
  136. return TRUE;
  137. }
  138. //
  139. // Attempt to enter the critical section. If the attempt is successful,
  140. // then set the owning thread, initialize the recursion count, and return
  141. // TRUE. Otherwise, return FALSE.
  142. //
  143. if (InterlockedCompareExchange(&CriticalSection->LockCount,
  144. 0,
  145. - 1) == - 1) {
  146. CriticalSection->OwningThread = Thread;
  147. CriticalSection->RecursionCount = 1;
  148. return TRUE;
  149. } else {
  150. return FALSE;
  151. }
  152. }