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.

360 lines
7.7 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. reslock.cxx
  5. Abstract:
  6. Contains methods for RESOURCE_LOCK class
  7. Contents:
  8. RESOURCE_LOCK::Acquire()
  9. RESOURCE_LOCK::Release()
  10. Author:
  11. Richard L Firth (rfirth) 18-Jun-1996
  12. Revision History:
  13. 18-Jun-1996 rfirth
  14. Created
  15. --*/
  16. #include <wininetp.h>
  17. //
  18. // class members
  19. //
  20. #ifdef OLD_VERSION
  21. BOOL
  22. RESOURCE_LOCK::Acquire(
  23. IN BOOL bExclusiveMode
  24. )
  25. /*++
  26. Routine Description:
  27. Acquires the resource protected by this lock. Acquires for non-exclusive
  28. (read) or exclusive (write) ownership
  29. Arguments:
  30. bExclusiveMode - TRUE if we are acquiring the resource for exclusive
  31. (write) ownership
  32. Return Value:
  33. BOOL
  34. TRUE - resource is acquired
  35. FALSE - failed to acquire resource (timeout?)
  36. --*/
  37. {
  38. DEBUG_ENTER((DBG_RESLOCK,
  39. Bool,
  40. "RESOURCE_LOCK::Acquire",
  41. "%B",
  42. bExclusiveMode
  43. ));
  44. INET_ASSERT(this != NULL);
  45. //INET_ASSERT(IsInitialized());
  46. //INET_ASSERT(IsValid());
  47. if (!IsInitialized()) {
  48. DEBUG_LEAVE(FALSE);
  49. return FALSE;
  50. }
  51. BOOL acquired = TRUE;
  52. //_CritSect.Lock();
  53. if (bExclusiveMode) {
  54. //
  55. // acquired for exclusive ownership (write access). Set the owning
  56. // thread id and wait for the last current reader to release. Note
  57. // that if we're being re-entered, the Lock() has already
  58. // done the work of checking the thread id and updating re-entrancy
  59. // counts, so if its already not zero, we know it must be us
  60. //
  61. ++_WriteCount;
  62. if (_ThreadId == 0) {
  63. _ThreadId = GetCurrentThreadId();
  64. #if INET_DEBUG
  65. INET_ASSERT(_ThreadId != _ThreadIdReader);
  66. #endif
  67. acquired = Wait(_hWriteEvent);
  68. _CritSect.Lock();
  69. } else {
  70. INET_ASSERT(_ThreadId == GetCurrentThreadId());
  71. }
  72. } else {
  73. //
  74. // don't allow re-entry if already held for exclusive access
  75. //
  76. INET_ASSERT(_ThreadId == 0);
  77. //
  78. // acquired for non-exclusive ownership (read access). Just increase
  79. // the number of active readers. If this is the first then inhibit the
  80. // writer
  81. //
  82. if (InterlockedIncrement(&_Readers) == 0) {
  83. #if INET_DEBUG
  84. if (_ThreadIdReader == 0) {
  85. _ThreadIdReader = GetCurrentThreadId();
  86. }
  87. #endif
  88. ResetEvent(_hWriteEvent);
  89. }
  90. //
  91. // reader doesn't need to keep hold of critical section
  92. //
  93. //_CritSect.Unlock();
  94. }
  95. DEBUG_LEAVE(acquired);
  96. return acquired;
  97. }
  98. VOID
  99. RESOURCE_LOCK::Release(
  100. VOID
  101. )
  102. /*++
  103. Routine Description:
  104. Releases a resource previously acquired by RESOURCE_LOCK::Acquire()
  105. Arguments:
  106. None.
  107. Return Value:
  108. None.
  109. --*/
  110. {
  111. DEBUG_ENTER((DBG_RESLOCK,
  112. None,
  113. "RESOURCE_LOCK::Release",
  114. NULL
  115. ));
  116. INET_ASSERT(this != NULL);
  117. //INET_ASSERT(IsInitialized());
  118. //INET_ASSERT(IsValid());
  119. if (!IsInitialized()) {
  120. DEBUG_LEAVE(0);
  121. return;
  122. }
  123. if ((_ThreadId != 0) && (_ThreadId == GetCurrentThreadId())) {
  124. INET_ASSERT(_WriteCount > 0);
  125. if (--_WriteCount == 0) {
  126. //
  127. // we acquired _hWriteEvent; signal it to allow next writer to continue
  128. //
  129. SetEvent(_hWriteEvent);
  130. //
  131. // this resource no longer owned for exclusive access
  132. //
  133. _ThreadId = 0;
  134. }
  135. _CritSect.Unlock();
  136. } else if (InterlockedDecrement(&_Readers) < 0) {
  137. INET_ASSERT(_Readers >= -1);
  138. //
  139. // we are last currently active reader; allow waiting writer to continue
  140. //
  141. #if INET_DEBUG
  142. if (_ThreadIdReader == GetCurrentThreadId()) {
  143. _ThreadIdReader = 0;
  144. }
  145. #endif
  146. SetEvent(_hWriteEvent);
  147. }
  148. DEBUG_LEAVE(0);
  149. }
  150. #else
  151. BOOL
  152. RESOURCE_LOCK::Acquire(
  153. IN BOOL bExclusiveMode
  154. )
  155. {
  156. DEBUG_ENTER((DBG_RESLOCK,
  157. Bool,
  158. "RESOURCE_LOCK::Acquire",
  159. "%B",
  160. bExclusiveMode
  161. ));
  162. BOOL fReturn = TRUE;
  163. if (!IsInitialized()) {
  164. fReturn = FALSE;
  165. goto quit;
  166. }
  167. if (bExclusiveMode) {
  168. do {
  169. DEBUG_PRINT(RESLOCK,
  170. INFO,
  171. ("Waiting on WriteEvent\n")
  172. );
  173. if (_ThreadId != GetCurrentThreadId()) {
  174. Wait(_hWriteEvent);
  175. }
  176. if (!_CritSect.Lock())
  177. {
  178. DEBUG_PRINT(RESLOCK,
  179. ERROR,
  180. ("Failed to obtain critsec lock after waiting on WriteEvent\n")
  181. );
  182. fReturn = FALSE;
  183. break;
  184. }
  185. INET_ASSERT((_ThreadId == 0) || (_ThreadId == GetCurrentThreadId()));
  186. if ((_Readers == -1)
  187. && ((_ThreadId == 0) || (_ThreadId == GetCurrentThreadId()))) {
  188. _ThreadId = GetCurrentThreadId();
  189. if (++_WriteCount == 1) {
  190. ResetEvent(_hWriteEvent);
  191. }
  192. break;
  193. }
  194. DEBUG_PRINT(RESLOCK,
  195. INFO,
  196. ("trying again\n")
  197. );
  198. _CritSect.Unlock();
  199. } while ( 1 );
  200. } else {
  201. if (_CritSect.Lock()) {
  202. if (++_Readers == 0) {
  203. DEBUG_PRINT(RESLOCK,
  204. INFO,
  205. ("Resetting WriteEvent\n")
  206. );
  207. ResetEvent(_hWriteEvent);
  208. }
  209. _CritSect.Unlock();
  210. }
  211. else {
  212. DEBUG_PRINT(RESLOCK,
  213. ERROR,
  214. ("Failed to obtain critsec lock after waiting on WriteEvent\n")
  215. );
  216. fReturn = FALSE;
  217. }
  218. }
  219. quit:
  220. DEBUG_LEAVE(fReturn);
  221. return fReturn;
  222. }
  223. VOID
  224. RESOURCE_LOCK::Release(
  225. VOID
  226. )
  227. {
  228. DEBUG_ENTER((DBG_RESLOCK,
  229. None,
  230. "RESOURCE_LOCK::Release",
  231. NULL
  232. ));
  233. if (IsInitialized()) {
  234. if (_ThreadId == GetCurrentThreadId()) {
  235. DEBUG_PRINT(RESLOCK,
  236. INFO,
  237. ("Clearing writer\n")
  238. );
  239. if (--_WriteCount == 0) {
  240. _ThreadId = 0;
  241. SetEvent(_hWriteEvent);
  242. }
  243. _CritSect.Unlock();
  244. } else {
  245. if (_CritSect.Lock()) {
  246. if (--_Readers == -1) {
  247. DEBUG_PRINT(RESLOCK,
  248. INFO,
  249. ("Setting WriteEvent\n")
  250. );
  251. SetEvent(_hWriteEvent);
  252. }
  253. _CritSect.Unlock();
  254. }
  255. else {
  256. DEBUG_PRINT(RESLOCK,
  257. INFO,
  258. ("Couldn't set WriteEvent due to not enough memory\n")
  259. );
  260. }
  261. }
  262. }
  263. DEBUG_LEAVE(0);
  264. }
  265. #endif // OLD_VERSION