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.

223 lines
4.9 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1990 - 1999
  6. //
  7. // File: mutex.cxx
  8. //
  9. //--------------------------------------------------------------------------
  10. /* --------------------------------------------------------------------
  11. Microsoft OS/2 LAN Manager
  12. Copyright(c) Microsoft Corp., 1990
  13. -------------------------------------------------------------------- */
  14. /* --------------------------------------------------------------------
  15. File: mutex.cxx
  16. Description:
  17. This file contains the system independent mutex class for NT.
  18. History:
  19. mikemon ??-??-?? The beginning.
  20. mikemon 12-31-90 Upgraded the comments.
  21. -------------------------------------------------------------------- */
  22. #include <precomp.hxx>
  23. void
  24. MUTEX::CommonConstructor (
  25. OUT RPC_STATUS PAPI * RpcStatus,
  26. IN DWORD dwSpinCount
  27. )
  28. /*++
  29. Routine Description:
  30. We construct a mutex in this routine; the only interesting part is that
  31. we need to be able to return a success or failure status.
  32. Arguments:
  33. RpcStatus - Returns either RPC_S_OK or RPC_S_OUT_OF_MEMORY.
  34. --*/
  35. {
  36. CriticalSection.DebugInfo = 0;
  37. if ( *RpcStatus == RPC_S_OK )
  38. {
  39. if ( NT_SUCCESS(RtlInitializeCriticalSectionAndSpinCount(&CriticalSection, dwSpinCount)) )
  40. {
  41. *RpcStatus = RPC_S_OK;
  42. }
  43. else
  44. {
  45. *RpcStatus = RPC_S_OUT_OF_MEMORY;
  46. }
  47. }
  48. #ifdef NO_RECURSIVE_MUTEXES
  49. RecursionCount = 0;
  50. #endif // NO_RECURSIVE_MUTEXES
  51. }
  52. void MUTEX::Free(void)
  53. {
  54. NTSTATUS NtStatus;
  55. if ( IsSuccessfullyInitialized() )
  56. {
  57. NtStatus = RtlDeleteCriticalSection(&CriticalSection);
  58. ASSERT(NT_SUCCESS(NtStatus));
  59. }
  60. }
  61. #ifdef DEBUGRPC
  62. void
  63. MUTEX::EnumOwnedCriticalSections()
  64. {
  65. CRITICAL_SECTION_DEBUG * DebugInfo;
  66. return;
  67. HANDLE MyThreadId = ULongToPtr(GetCurrentThreadId());
  68. DWORD Count = NtCurrentTeb()->CountOfOwnedCriticalSections;
  69. // if (!Count)
  70. // {
  71. // DbgPrint("thread %x: taking %x\n", &CriticalSection);
  72. // return;
  73. // }
  74. DbgPrint("thread %x owns the following %d critical section(s):\n",
  75. MyThreadId, Count
  76. );
  77. DebugInfo = CriticalSection.DebugInfo;
  78. BOOL Found = FALSE;
  79. for (;;)
  80. {
  81. DebugInfo = CONTAINING_RECORD( DebugInfo->ProcessLocksList.Flink,
  82. RTL_CRITICAL_SECTION_DEBUG,
  83. ProcessLocksList
  84. );
  85. if (!DebugInfo->ProcessLocksList.Flink)
  86. {
  87. // DbgPrint("null forward link\n");
  88. break;
  89. }
  90. if (DebugInfo->ProcessLocksList.Flink == &CriticalSection.DebugInfo->ProcessLocksList)
  91. {
  92. // DbgPrint("circular list complete\n");
  93. break;
  94. }
  95. // DbgPrint("mutex %x owner %x\n",
  96. // DebugInfo->CriticalSection,
  97. // DebugInfo->CriticalSection
  98. // ? DebugInfo->CriticalSection->OwningThread
  99. // : 0
  100. // );
  101. if (DebugInfo->CriticalSection &&
  102. DebugInfo->CriticalSection->OwningThread == MyThreadId)
  103. {
  104. DbgPrint(" %x\n", DebugInfo->CriticalSection);
  105. Found = TRUE;
  106. }
  107. }
  108. if (Found)
  109. {
  110. DbgPrint("and is taking %x\n", &CriticalSection);
  111. DbgBreakPoint();
  112. }
  113. }
  114. #endif // DEBUG
  115. void
  116. MUTEX3::Request()
  117. {
  118. if (guard.Increment() > 0)
  119. {
  120. if (owner == GetCurrentThreadId())
  121. {
  122. guard.Decrement();
  123. ASSERT(guard.GetInteger() >= 0);
  124. recursion++;
  125. return;
  126. }
  127. event.Wait();
  128. ASSERT(guard.GetInteger() >= 0);
  129. }
  130. ASSERT(owner == 0);
  131. ASSERT(recursion == 0);
  132. owner = GetCurrentThreadId();
  133. recursion = 1;
  134. return;
  135. }
  136. void
  137. MUTEX3::Clear()
  138. {
  139. ASSERT(owner == GetCurrentThreadId());
  140. ASSERT(recursion > 0);
  141. if ( --recursion > 0)
  142. {
  143. return;
  144. }
  145. owner = 0;
  146. if (guard.Decrement() >= 0)
  147. {
  148. event.Raise();
  149. }
  150. }
  151. BOOL
  152. MUTEX3::TryRequest()
  153. {
  154. if (guard.CompareExchange(0, -1) == -1)
  155. {
  156. // Lock wasn't owned, now we own it.
  157. owner = GetCurrentThreadId();
  158. recursion = 1;
  159. return TRUE;
  160. }
  161. if (owner == GetCurrentThreadId())
  162. {
  163. // We can aquire it recursivly, just increment the count
  164. recursion++;
  165. return TRUE;
  166. }
  167. // Owned by another thread
  168. return FALSE;
  169. }