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.

206 lines
5.9 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. mprlock.hxx
  5. Abstract:
  6. Contains data structures and function prototypes for the MPR's
  7. locking functions (converted from the Service Controller's).
  8. This file defines the following classes:
  9. CCountingResource
  10. CProviderLock
  11. CProviderExclusiveLock
  12. CProviderSharedLock
  13. Author:
  14. Jonathan Schwartz (jschwart) 19-May-1999
  15. Environment:
  16. User Mode -Win32
  17. Revision History:
  18. 19-May-1999 jschwart
  19. Created, converted from \nt\private\windows\screg\sc\server\lock.cxx.
  20. --*/
  21. #ifndef _MPRLOCK_INCLUDED_
  22. #define _MPRLOCK_INCLUDED_
  23. //+-------------------------------------------------------------------------
  24. //
  25. // Class: CCountingResource
  26. //
  27. // Purpose: This is an RTL_RESOURCE that, in the checked build, knows
  28. // its locking level for the current thread. The locking
  29. // level is stored in a TLS (thread local storage) slot. A
  30. // positive value indicates a shared lock on the resource and
  31. // a negative value indicates an exclusive lock, with the
  32. // absolute value indicating the number of recursive
  33. // acquisitions of the lock.
  34. //
  35. // History: 19-May-99 jschwart Created.
  36. //
  37. //--------------------------------------------------------------------------
  38. class CCountingResource
  39. {
  40. public:
  41. BOOL Initialize(LPCSTR ShortName, LPCSTR Name)
  42. {
  43. BOOL fRet = TRUE;
  44. __try
  45. {
  46. RtlInitializeResource(&_Lock);
  47. #if DBG
  48. _TlsIndex = TlsAlloc();
  49. ASSERT(_TlsIndex != 0xFFFFFFFF);
  50. _ShortName = ShortName;
  51. _Name = Name;
  52. #endif
  53. }
  54. __except(EXCEPTION_EXECUTE_HANDLER)
  55. {
  56. fRet = FALSE;
  57. }
  58. return fRet;
  59. }
  60. void Delete() {
  61. RtlDeleteResource(&_Lock);
  62. #if DBG
  63. TlsFree(_TlsIndex);
  64. #endif
  65. }
  66. #if DBG
  67. void GetShared();
  68. void GetExclusive();
  69. void Release();
  70. BOOL Have() const { return (CurrentLevel() != 0); }
  71. BOOL HaveExclusive() const
  72. { return (CurrentLevel() < 0); }
  73. #else
  74. void GetShared() { RtlAcquireResourceShared(&_Lock, TRUE); }
  75. void GetExclusive() { RtlAcquireResourceExclusive(&_Lock, TRUE); }
  76. void Release() { RtlReleaseResource(&_Lock); }
  77. #endif
  78. protected:
  79. #if DBG
  80. LONG CurrentLevel() const
  81. { return (LONG)(LONG_PTR)(TlsGetValue(_TlsIndex)); }
  82. void SetCurrentLevel(LONG Level)
  83. { ASSERT(TlsSetValue(_TlsIndex, LongToPtr(Level)) != 0); }
  84. #endif
  85. private:
  86. #if DBG
  87. DWORD _TlsIndex;
  88. LPCSTR _ShortName;
  89. LPCSTR _Name;
  90. #endif
  91. RTL_RESOURCE _Lock;
  92. };
  93. //+-------------------------------------------------------------------------
  94. //
  95. // Class: CProviderLock
  96. //
  97. // Purpose: This lock is used to synchronize multithreaded
  98. // access to the provider database.
  99. //
  100. // History: 19-May-99 jschwart Created.
  101. //
  102. //--------------------------------------------------------------------------
  103. class CProviderLock : public CCountingResource
  104. {
  105. };
  106. //
  107. // Globals
  108. //
  109. extern CProviderLock MPRProviderLock;
  110. //+-------------------------------------------------------------------------
  111. //
  112. // Safe wrapper classes that ensure that the Release method is called
  113. //
  114. // Use of these classes ensures proper, disciplined access to the locks.
  115. // In general, the locks should be acquired and released through these
  116. // safe classes only. Any direct access to the locks should be viewed
  117. // with suspicion.
  118. //
  119. // In order to avoid deadlock in the MPR, every MPR API must make the
  120. // following three calls IN ORDER:
  121. //
  122. // 1. MprCheckProviders -- acquires the exclusive lock and flushes
  123. // the providers if necessary
  124. //
  125. // 2. Acquire the shared lock (to prevent another API from flushing
  126. // the providers)
  127. //
  128. // 3. INIT_IF_NECESSARY
  129. //
  130. // INIT_IF_NECESSARY must come last to avoid the following race condition:
  131. //
  132. // 1. Thread 1 calls INIT_IF_NECESSARY and all is initialized
  133. //
  134. // 2. Providers change -- thread 2 catches it in MprCheckProviders and
  135. // flushes providers
  136. //
  137. // 3. Thread 1 acquires the read lock and finds no providers (though
  138. // they should be there -- fails or faults)
  139. //
  140. // In addition, the logic in MprCheckProviders requires APIs that use
  141. // INIT_IF_NECESSARY to call it after acquiring the read lock, as
  142. // MprCheckProviders does not acquire the MprInitCritSec.
  143. //
  144. // Note that this system assumes no WNet API calls are either made
  145. // recursively or re-entrant. This requires special care with the functions
  146. // in mprui.cxx as they ultimately call other WNet APIs in mprui.dll or
  147. // netplwiz.dll.
  148. //
  149. //--------------------------------------------------------------------------
  150. class CProviderSharedLock
  151. {
  152. public:
  153. CProviderSharedLock() { MPRProviderLock.GetShared(); }
  154. ~CProviderSharedLock() { MPRProviderLock.Release(); }
  155. };
  156. class CProviderExclusiveLock
  157. {
  158. public:
  159. CProviderExclusiveLock() { MPRProviderLock.GetExclusive(); }
  160. ~CProviderExclusiveLock() { MPRProviderLock.Release(); }
  161. };
  162. #endif // ifndef _MPRLOCK_INCLUDED_