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.

264 lines
7.3 KiB

  1. #ifndef __SHARELOCK_H__
  2. #define __SHARELOCK_H__
  3. //////////////////////////////////////////////////////////////////////
  4. //
  5. // The standard include files.
  6. //
  7. // The standard include files setup a consistent environment
  8. // for all of the modules in a program. The structure of each
  9. // header file is as follows:
  10. // 1. Standard include files.
  11. // 2. Include files for inherited classes.
  12. // 3. Constants exported from the class.
  13. // 4. Data structures exported from the class.
  14. // 5. Class specification.
  15. // 6. Inline functions.
  16. // Sections that are not required are omitted.
  17. //
  18. //////////////////////////////////////////////////////////////////////
  19. // #include "Global.h"
  20. // #include "NewEx.h"
  21. // #include "Standard.h"
  22. // #include "System.h"
  23. #include <irtlmisc.h>
  24. typedef int SBIT32;
  25. //////////////////////////////////////////////////////////////////////
  26. //
  27. // Sharelock and Semaphore locking.
  28. //
  29. // This class provides a very conservative locking scheme.
  30. // The assumption behind the code is that locks will be
  31. // held for a very short time. A lock can be obtained in
  32. // either exclusive mode or shared mode. If the lock is not
  33. // available the caller waits by spinning or if that fails
  34. // by sleeping.
  35. //
  36. //////////////////////////////////////////////////////////////////////
  37. class IRTL_DLLEXP CSharelock
  38. {
  39. private:
  40. // internally used constants
  41. enum Internal
  42. {
  43. // The Windows NT kernel requires a maximum wakeup count when
  44. // creating a semaphore.
  45. m_MaxShareLockUsers = 256
  46. };
  47. //
  48. // Private data.
  49. //
  50. volatile LONG m_lExclusive;
  51. volatile LONG m_lTotalUsers;
  52. SBIT32 m_lMaxSpins;
  53. SBIT32 m_lMaxUsers;
  54. HANDLE m_hSemaphore;
  55. volatile LONG m_lWaiting;
  56. #ifdef _DEBUG
  57. //
  58. // Counters for debugging builds.
  59. //
  60. volatile LONG m_lTotalExclusiveLocks;
  61. volatile LONG m_lTotalShareLocks;
  62. volatile LONG m_lTotalSleeps;
  63. volatile LONG m_lTotalSpins;
  64. volatile LONG m_lTotalTimeouts;
  65. volatile LONG m_lTotalWaits;
  66. #endif
  67. public:
  68. //
  69. // Public functions.
  70. //
  71. CSharelock( SBIT32 lNewMaxSpins = 4096, SBIT32 lNewMaxUsers = 256 );
  72. inline SBIT32 ActiveUsers( void ) { return (SBIT32) m_lTotalUsers; }
  73. inline void ChangeExclusiveLockToSharedLock( void );
  74. inline BOOLEAN ChangeSharedLockToExclusiveLock( SBIT32 lSleep = INFINITE );
  75. inline BOOLEAN ClaimExclusiveLock( SBIT32 lSleep = INFINITE );
  76. inline BOOLEAN ClaimShareLock( SBIT32 lSleep = INFINITE );
  77. inline void ReleaseExclusiveLock( void );
  78. inline void ReleaseShareLock( void );
  79. BOOLEAN UpdateMaxSpins( SBIT32 lNewMaxSpins );
  80. BOOLEAN UpdateMaxUsers( SBIT32 lNewMaxUsers );
  81. ~CSharelock( void );
  82. private:
  83. //
  84. // Private functions.
  85. //
  86. BOOLEAN SleepWaitingForLock( SBIT32 lSleep );
  87. BOOLEAN WaitForExclusiveLock( SBIT32 lSleep );
  88. BOOLEAN WaitForShareLock( SBIT32 lSleep );
  89. void WakeAllSleepers( void );
  90. private:
  91. //
  92. // Disabled operations.
  93. //
  94. CSharelock( const CSharelock & Copy );
  95. void operator=( const CSharelock & Copy );
  96. };
  97. /********************************************************************/
  98. /* */
  99. /* Change an exclusive lock to a shread lock. */
  100. /* */
  101. /* Downgrade the existing exclusive lock to a shared lock. */
  102. /* */
  103. /********************************************************************/
  104. inline void CSharelock::ChangeExclusiveLockToSharedLock( void )
  105. {
  106. (void) InterlockedDecrement( (LPLONG) & m_lExclusive );
  107. #ifdef _DEBUG
  108. (void) InterlockedIncrement( (LPLONG) & m_lTotalShareLocks );
  109. #endif
  110. }
  111. /********************************************************************/
  112. /* */
  113. /* Change a shared lock to an exclusive lock. */
  114. /* */
  115. /* Upgrade the existing shared lock to an exclusive lock. */
  116. /* */
  117. /********************************************************************/
  118. inline BOOLEAN CSharelock::ChangeSharedLockToExclusiveLock( SBIT32 lSleep )
  119. {
  120. (void) InterlockedIncrement( (LPLONG) & m_lExclusive );
  121. if ( m_lTotalUsers != 1 )
  122. {
  123. if ( ! WaitForExclusiveLock( lSleep ) )
  124. { return FALSE; }
  125. }
  126. #ifdef _DEBUG
  127. (void) InterlockedIncrement( (LPLONG) & m_lTotalExclusiveLocks );
  128. #endif
  129. return TRUE;
  130. }
  131. //////////////////////////////////////////////////////////////////////
  132. //
  133. // Claim an exclusive lock.
  134. //
  135. // Claim an exclusive lock if available else wait or exit.
  136. //
  137. //////////////////////////////////////////////////////////////////////
  138. inline BOOLEAN CSharelock::ClaimExclusiveLock( SBIT32 lSleep )
  139. {
  140. (void) InterlockedIncrement( (LPLONG) & m_lExclusive );
  141. (void) InterlockedIncrement( (LPLONG) & m_lTotalUsers );
  142. if ( m_lTotalUsers != 1 )
  143. {
  144. if ( ! WaitForExclusiveLock( lSleep ) )
  145. {
  146. return FALSE;
  147. }
  148. }
  149. #ifdef _DEBUG
  150. InterlockedIncrement( (LPLONG) & m_lTotalExclusiveLocks );
  151. #endif
  152. return TRUE;
  153. }
  154. //////////////////////////////////////////////////////////////////////
  155. //
  156. // Claim a shared lock.
  157. //
  158. // Claim a shared lock if available else wait or exit.
  159. //
  160. //////////////////////////////////////////////////////////////////////
  161. inline BOOLEAN CSharelock::ClaimShareLock( SBIT32 lSleep )
  162. {
  163. (void) InterlockedIncrement( (LPLONG) & m_lTotalUsers );
  164. if ( (m_lExclusive > 0) || (m_lTotalUsers > m_lMaxUsers) )
  165. {
  166. if ( ! WaitForShareLock( lSleep ) )
  167. {
  168. return FALSE;
  169. }
  170. }
  171. #ifdef _DEBUG
  172. InterlockedIncrement( (LPLONG) & m_lTotalShareLocks );
  173. #endif
  174. return TRUE;
  175. }
  176. //////////////////////////////////////////////////////////////////////
  177. //
  178. // Release an exclusive lock.
  179. //
  180. // Release an exclusive lock and if needed wakeup any sleepers.
  181. //
  182. //////////////////////////////////////////////////////////////////////
  183. inline void CSharelock::ReleaseExclusiveLock( void )
  184. {
  185. (void) InterlockedDecrement( (LPLONG) & m_lTotalUsers );
  186. (void) InterlockedDecrement( (LPLONG) & m_lExclusive );
  187. if ( m_lWaiting > 0 )
  188. {
  189. WakeAllSleepers();
  190. }
  191. }
  192. //////////////////////////////////////////////////////////////////////
  193. //
  194. // Release a shared lock.
  195. //
  196. // Release a shared lock and if needed wakeup any sleepers.
  197. //
  198. //////////////////////////////////////////////////////////////////////
  199. inline void CSharelock::ReleaseShareLock( void )
  200. {
  201. (void) InterlockedDecrement( (LPLONG) & m_lTotalUsers );
  202. if ( m_lWaiting > 0 )
  203. {
  204. WakeAllSleepers();
  205. }
  206. }
  207. #endif // __SHARELOCK_H__