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.

217 lines
4.6 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1995 - 1999
  3. Module Name:
  4. Locks.cxx
  5. Abstract:
  6. Out of line methods for some of the syncronization classes
  7. defined in locks.hxx.
  8. Author:
  9. Mario Goertzel [MarioGo]
  10. Revision History:
  11. MarioGo 03-14-95 Moved from misc.cxx.
  12. MarioGo 01-27-96 Changed from busy (Sleep(0)) wait to event
  13. --*/
  14. #include <precomp.hxx>
  15. #include <locks.hxx>
  16. //
  17. // CShareLock methods
  18. //
  19. #if defined(NTENV) && !defined(_WIN64)
  20. // extern DWORD GetCurrentThreadId(void);
  21. #define GetCurrentThreadId() ((DWORD)NtCurrentTeb()->ClientId.UniqueThread)
  22. #endif
  23. CSharedLock::CSharedLock(RPC_STATUS &status)
  24. {
  25. exclusive_owner = 0;
  26. writers = 0;
  27. hevent = INVALID_HANDLE_VALUE; // Flag in the d'tor
  28. recursion_count = 0;
  29. if (status == RPC_S_OK)
  30. {
  31. __try
  32. {
  33. InitializeCriticalSection(&lock);
  34. }
  35. __except( GetExceptionCode() == STATUS_NO_MEMORY )
  36. {
  37. status = RPC_S_OUT_OF_MEMORY;
  38. }
  39. if (status == RPC_S_OK)
  40. {
  41. hevent = CreateEvent(0, FALSE, FALSE, 0);
  42. if (0 == hevent)
  43. {
  44. status = ERROR_NOT_ENOUGH_MEMORY;
  45. }
  46. }
  47. }
  48. }
  49. CSharedLock::~CSharedLock()
  50. {
  51. if (hevent != INVALID_HANDLE_VALUE)
  52. {
  53. DeleteCriticalSection(&lock);
  54. if (hevent) CloseHandle(hevent);
  55. }
  56. }
  57. void
  58. CSharedLock::LockShared()
  59. {
  60. // If the current thread owns this lock exclusively, then taking
  61. // a shared lock is just a no-op.
  62. readers++;
  63. LogEvent(SU_MUTEX, EV_INC, this, 0, readers);
  64. if (!HeldExclusive())
  65. {
  66. if (writers)
  67. {
  68. if ((readers--) == 0)
  69. {
  70. SetEvent(hevent);
  71. }
  72. EnterCriticalSection(&lock);
  73. readers++;
  74. LeaveCriticalSection(&lock);
  75. }
  76. ASSERT(exclusive_owner == 0);
  77. }
  78. }
  79. void
  80. CSharedLock::UnlockShared(void)
  81. {
  82. if (HeldExclusive())
  83. {
  84. ASSERT((LONG)readers > 0);
  85. readers--;
  86. }
  87. else
  88. {
  89. ASSERT((LONG)readers > 0);
  90. ASSERT(exclusive_owner == 0);
  91. if ( (readers--) == 0 && writers)
  92. {
  93. SetEvent(hevent);
  94. }
  95. }
  96. LogEvent(SU_MUTEX, EV_DEC, this, 0, readers);
  97. }
  98. void
  99. CSharedLock::LockExclusive(void)
  100. {
  101. EnterCriticalSection(&lock);
  102. // If the thread is an exclusive owner then a recursive lock
  103. // is a no-op.
  104. if (HeldExclusive())
  105. {
  106. LogEvent(SU_MUTEX, EV_INC, this, ULongToPtr(0x99999999), writers+1);
  107. }
  108. else
  109. {
  110. LogEvent(SU_MUTEX, EV_INC, this, ULongToPtr(0x99999999), writers+1);
  111. writers++;
  112. while(readers)
  113. {
  114. WaitForSingleObject(hevent, INFINITE);
  115. }
  116. ASSERT(writers);
  117. exclusive_owner = GetCurrentThreadId();
  118. }
  119. recursion_count++;
  120. }
  121. void
  122. CSharedLock::UnlockExclusive(void)
  123. {
  124. LogEvent(SU_MUTEX, EV_DEC, this, ULongToPtr(0x99999999), writers-1);
  125. ASSERT(HeldExclusive());
  126. ASSERT(writers);
  127. ASSERT(recursion_count >= 1);
  128. recursion_count--;
  129. // If the lock is held recursively, then releasing it is a no-op.
  130. if (recursion_count == 0)
  131. {
  132. exclusive_owner = 0;
  133. writers--;
  134. LeaveCriticalSection(&lock);
  135. }
  136. }
  137. void
  138. CSharedLock::Unlock()
  139. {
  140. // Either the lock is held exclusively by this thread or the thread
  141. // has a shared lock. (or the caller has a bug).
  142. if (HeldExclusive())
  143. {
  144. UnlockExclusive();
  145. }
  146. else
  147. {
  148. UnlockShared();
  149. }
  150. }
  151. void
  152. CSharedLock::ConvertToExclusive(void)
  153. {
  154. // If a shared lock is held recursively with an exclusive lock,
  155. // all that's needed is to unlock the shared lock and take an exclusive lock.
  156. if (HeldExclusive())
  157. {
  158. UnlockShared();
  159. LockExclusive();
  160. }
  161. else
  162. {
  163. ASSERT((LONG)readers > 0);
  164. ASSERT(exclusive_owner == 0);
  165. if ( (readers--) == 0 && writers )
  166. SetEvent(hevent);
  167. EnterCriticalSection(&lock);
  168. writers++;
  169. while(readers)
  170. {
  171. WaitForSingleObject(hevent, INFINITE);
  172. }
  173. ASSERT(writers);
  174. exclusive_owner = GetCurrentThreadId();
  175. recursion_count++;
  176. }
  177. }