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.

578 lines
12 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. Module Name:
  4. Locks
  5. Abstract:
  6. This module provides the definitions of common lock objects.
  7. Author:
  8. Doug Barlow (dbarlow) 10/24/1996
  9. Environment:
  10. Win32, C++ w/ exceptions
  11. Notes:
  12. ?Notes?
  13. --*/
  14. #ifndef _LOCKS_H_
  15. #define _LOCKS_H_
  16. #ifdef DBG
  17. #define REASONABLE_TIME 2 * 60 * 1000 // Two minutes
  18. #else
  19. #define REASONABLE_TIME INFINITE
  20. #endif
  21. extern DWORD
  22. WaitForAnyObject(
  23. DWORD dwTimeout,
  24. ...);
  25. extern DWORD
  26. WaitForAnObject(
  27. HANDLE hWaitOn,
  28. DWORD dwTimeout);
  29. #ifdef DBG
  30. #undef __SUBROUTINE__
  31. #define __SUBROUTINE__ TEXT("WaitForEverObject")
  32. inline void
  33. WaitForEverObject(
  34. HANDLE hWaitOn,
  35. DWORD dwTimeout,
  36. DEBUG_TEXT szReason,
  37. LPCTSTR szObject = NULL)
  38. {
  39. DWORD dwSts;
  40. while (ERROR_SUCCESS != (dwSts = WaitForAnObject(hWaitOn, dwTimeout)))
  41. CalaisWarning(__SUBROUTINE__, szReason, dwSts, szObject);
  42. }
  43. inline void
  44. WaitForEverObject(
  45. HANDLE hWaitOn,
  46. DWORD dwTimeout,
  47. DEBUG_TEXT szReason,
  48. DWORD dwObject)
  49. {
  50. DWORD dwSts;
  51. TCHAR szNum[16];
  52. wsprintf(szNum, TEXT("0x%08x"), dwObject);
  53. while (ERROR_SUCCESS != (dwSts = WaitForAnObject(hWaitOn, dwTimeout)))
  54. CalaisWarning(__SUBROUTINE__, szReason, dwSts, szNum);
  55. }
  56. #define WaitForever(hWaitOn, dwTimeout, szReason, szObject) \
  57. WaitForEverObject(hWaitOn, dwTimeout, szReason, szObject)
  58. #else
  59. inline void
  60. WaitForEverObject(
  61. HANDLE hWaitOn)
  62. {
  63. while (ERROR_SUCCESS != WaitForAnObject(hWaitOn, INFINITE));
  64. // Empty body
  65. }
  66. #define WaitForever(hWaitOn, dwTimeout, szReason, szObject) \
  67. WaitForEverObject(hWaitOn)
  68. #endif
  69. //
  70. // Critical Section Support.
  71. //
  72. // The following Classes and Macros aid in debugging Critical Section
  73. // Conflicts.
  74. //
  75. //
  76. //==============================================================================
  77. //
  78. // CCriticalSectionObject
  79. //
  80. class CCriticalSectionObject
  81. {
  82. public:
  83. // Constructors & Destructor
  84. CCriticalSectionObject(DWORD dwCsid = 0);
  85. ~CCriticalSectionObject();
  86. // Properties
  87. // Methods
  88. virtual void Enter(DEBUG_TEXT szOwner, DEBUG_TEXT szComment);
  89. virtual void Leave(void);
  90. #ifdef DBG
  91. LPCTSTR Description(void) const;
  92. #undef __SUBROUTINE__
  93. #define __SUBROUTINE__ TEXT("CCriticalSectionObject::Owner")
  94. LPCTSTR Owner(void) const
  95. { return (LPCTSTR)m_bfOwner.Access(); };
  96. #undef __SUBROUTINE__
  97. #define __SUBROUTINE__ TEXT("CCriticalSectionObject::Comment")
  98. LPCTSTR Comment(void) const
  99. { return (LPCTSTR)m_bfComment.Access(); };
  100. #undef __SUBROUTINE__
  101. #define __SUBROUTINE__ TEXT("CCriticalSectionObject::IsOwnedByMe")
  102. BOOL IsOwnedByMe(void) const
  103. { return (GetCurrentThreadId() == m_dwOwnerThread); };
  104. #endif
  105. // Operators
  106. protected:
  107. // Properties
  108. CRITICAL_SECTION m_csLock;
  109. #ifdef DBG
  110. DWORD m_dwCsid;
  111. CBuffer m_bfOwner;
  112. CBuffer m_bfComment;
  113. DWORD m_dwOwnerThread;
  114. DWORD m_dwRecursion;
  115. DWORD m_dwArrayEntry;
  116. static CDynamicArray<CCriticalSectionObject *> *mg_prgCSObjects;
  117. static CRITICAL_SECTION mg_csArrayLock;
  118. #endif
  119. // Methods
  120. };
  121. //
  122. //==============================================================================
  123. //
  124. // COwnCriticalSection
  125. //
  126. class COwnCriticalSection
  127. {
  128. public:
  129. // Constructors & Destructor
  130. #undef __SUBROUTINE__
  131. #define __SUBROUTINE__ TEXT("COwnCriticalSection::COwnCriticalSection")
  132. COwnCriticalSection(
  133. CCriticalSectionObject *pcs,
  134. DEBUG_TEXT szSubroutine,
  135. DEBUG_TEXT szComment)
  136. {
  137. m_pcsLock = pcs;
  138. m_pcsLock->Enter(szSubroutine, szComment);
  139. };
  140. #undef __SUBROUTINE__
  141. #define __SUBROUTINE__ TEXT("COwnCriticalSection::~COwnCriticalSection")
  142. ~COwnCriticalSection()
  143. {
  144. m_pcsLock->Leave();
  145. };
  146. // Properties
  147. // Methods
  148. // Operators
  149. protected:
  150. // Properties
  151. CCriticalSectionObject *m_pcsLock;
  152. // Methods
  153. };
  154. #define LockSection(cx, reason) \
  155. COwnCriticalSection csLock(cx, __SUBROUTINE__, reason)
  156. #ifndef DBG
  157. //
  158. //In-line the simple Critical Section calls.
  159. //
  160. #undef __SUBROUTINE__
  161. #define __SUBROUTINE__ TEXT("CCriticalSectionObject::CCriticalSectionObject")
  162. inline
  163. CCriticalSectionObject::CCriticalSectionObject(
  164. DWORD dwCsid)
  165. {
  166. BOOL fInited = FALSE;
  167. do
  168. {
  169. try
  170. {
  171. InitializeCriticalSection(&m_csLock);
  172. fInitied = TRUE;
  173. }
  174. catch (...)
  175. {
  176. Sleep(1000); // Sleep for 1 second.
  177. }
  178. } while (!fInited);
  179. }
  180. #undef __SUBROUTINE__
  181. #define __SUBROUTINE__ TEXT("CCriticalSectionObject::~CCriticalSectionObject")
  182. inline
  183. CCriticalSectionObject::~CCriticalSectionObject()
  184. {
  185. DeleteCriticalSection(&m_csLock);
  186. }
  187. #undef __SUBROUTINE__
  188. #define __SUBROUTINE__ TEXT("CCriticalSectionObject::Enter")
  189. inline void
  190. CCriticalSectionObject::Enter(
  191. DEBUG_TEXT szOwner,
  192. DEBUG_TEXT szComment)
  193. {
  194. BOOL fEntered = FALSE;
  195. do
  196. {
  197. try
  198. {
  199. EnterCriticalSection(&m_csLock);
  200. fEntered = TRUE;
  201. }
  202. catch (...)
  203. {
  204. Sleep(1000); // Sleep for 1 second.
  205. }
  206. } while (!fEntered);
  207. }
  208. #undef __SUBROUTINE__
  209. #define __SUBROUTINE__ TEXT("CCriticalSectionObject::Leave")
  210. inline void
  211. CCriticalSectionObject::Leave(
  212. void)
  213. {
  214. LeaveCriticalSection(&m_csLock);
  215. }
  216. #endif // !DBG
  217. //
  218. //==============================================================================
  219. //
  220. // CHandleObject
  221. //
  222. class CHandleObject
  223. {
  224. public:
  225. // Constructors & Destructor
  226. #undef __SUBROUTINE__
  227. #define __SUBROUTINE__ TEXT("CHandleObject::CHandleObject")
  228. CHandleObject(DEBUG_TEXT szName)
  229. #ifdef DBG
  230. : m_bfName((LPCBYTE)szName, (lstrlen(szName) + 1) * sizeof(TCHAR))
  231. #endif
  232. {
  233. m_hHandle = NULL;
  234. m_dwError = ERROR_SUCCESS;
  235. };
  236. #undef __SUBROUTINE__
  237. #define __SUBROUTINE__ TEXT("CHandleObject::~CHandleObject")
  238. ~CHandleObject()
  239. {
  240. if (IsValid())
  241. {
  242. #ifdef _DEBUG
  243. CalaisWarning(
  244. __SUBROUTINE__,
  245. DBGT("Unclosed handle '%1' -- fixing."),
  246. (DEBUG_TEXT)m_bfName.Access());
  247. #endif
  248. Close();
  249. }
  250. };
  251. // Properties
  252. // Methods
  253. #undef __SUBROUTINE__
  254. #define __SUBROUTINE__ TEXT("CHandleObject::IsValid")
  255. BOOL IsValid(void) const
  256. {
  257. return (NULL != m_hHandle) && (INVALID_HANDLE_VALUE != m_hHandle);
  258. };
  259. #undef __SUBROUTINE__
  260. #define __SUBROUTINE__ TEXT("CHandleObject::Value")
  261. HANDLE Value(void) const
  262. {
  263. #ifdef _DEBUG
  264. if (!IsValid())
  265. CalaisWarning(
  266. __SUBROUTINE__,
  267. DBGT("Accessing invalid '%1' handle value."),
  268. (DEBUG_TEXT)m_bfName.Access());
  269. #endif
  270. return m_hHandle;
  271. };
  272. #undef __SUBROUTINE__
  273. #define __SUBROUTINE__ TEXT("CHandleObject::GetLastError")
  274. DWORD GetLastError(void) const
  275. {
  276. return m_dwError;
  277. };
  278. #undef __SUBROUTINE__
  279. #define __SUBROUTINE__ TEXT("CHandleObject::Open")
  280. HANDLE Open(HANDLE h)
  281. {
  282. if ((NULL == h) || (INVALID_HANDLE_VALUE == h))
  283. {
  284. m_dwError = ::GetLastError();
  285. #ifdef _DEBUG
  286. CalaisWarning(
  287. __SUBROUTINE__,
  288. DBGT("Attempt to assign invalid handle value to '%1'."),
  289. (DEBUG_TEXT)m_bfName.Access());
  290. #endif
  291. }
  292. else
  293. m_dwError = ERROR_SUCCESS;
  294. if (IsValid())
  295. {
  296. #ifdef _DEBUG
  297. CalaisWarning(
  298. __SUBROUTINE__,
  299. DBGT("Overwriting handle '%1' -- fixing"),
  300. (DEBUG_TEXT)m_bfName.Access());
  301. #endif
  302. Close();
  303. }
  304. m_hHandle = h;
  305. return m_hHandle;
  306. };
  307. #undef __SUBROUTINE__
  308. #define __SUBROUTINE__ TEXT("CHandleObject::Close")
  309. DWORD Close(void)
  310. {
  311. DWORD dwSts = ERROR_SUCCESS;
  312. if (IsValid())
  313. {
  314. BOOL fSts;
  315. fSts = CloseHandle(m_hHandle);
  316. #ifdef DBG
  317. if (!fSts)
  318. {
  319. dwSts = GetLastError();
  320. CalaisWarning(
  321. __SUBROUTINE__,
  322. DBGT("Failed to close handle '%2': %1"),
  323. dwSts,
  324. (DEBUG_TEXT)m_bfName.Access());
  325. }
  326. #endif
  327. m_hHandle = NULL;
  328. }
  329. #ifdef DBG
  330. else
  331. {
  332. CalaisWarning(
  333. __SUBROUTINE__,
  334. DBGT("Attempt to re-close handle '%1'"),
  335. (DEBUG_TEXT)m_bfName.Access());
  336. }
  337. #endif
  338. return dwSts;
  339. };
  340. #undef __SUBROUTINE__
  341. #define __SUBROUTINE__ TEXT("CHandleObject::Relinquish")
  342. HANDLE Relinquish(void)
  343. {
  344. HANDLE hTmp = m_hHandle;
  345. #ifdef _DEBUG
  346. if (!IsValid())
  347. CalaisWarning(
  348. __SUBROUTINE__,
  349. DBGT("Relinquishing invalid '%1' handle"),
  350. (DEBUG_TEXT)m_bfName.Access());
  351. #endif
  352. m_hHandle = NULL;
  353. return hTmp;
  354. };
  355. // Operators
  356. #undef __SUBROUTINE__
  357. #define __SUBROUTINE__ TEXT("CHandleObject::operator HANDLE")
  358. operator HANDLE(void) const
  359. {
  360. ASSERT(IsValid());
  361. return Value();
  362. };
  363. #undef __SUBROUTINE__
  364. #define __SUBROUTINE__ TEXT("CHandleObject::operator=")
  365. HANDLE operator=(HANDLE h)
  366. {
  367. return Open(h);
  368. };
  369. protected:
  370. // Properties
  371. HANDLE m_hHandle;
  372. DWORD m_dwError;
  373. #ifdef DBG
  374. CBuffer m_bfName;
  375. #endif
  376. // Methods
  377. };
  378. //
  379. //==============================================================================
  380. //
  381. // CAccessLock
  382. //
  383. class CAccessLock
  384. {
  385. public:
  386. // Constructors & Destructor
  387. CAccessLock(DWORD dwTimeout = CALAIS_LOCK_TIMEOUT);
  388. ~CAccessLock();
  389. #ifdef DBG
  390. BOOL NotReadLocked(void);
  391. BOOL IsReadLocked(void);
  392. BOOL NotWriteLocked(void);
  393. BOOL IsWriteLocked(void);
  394. #endif
  395. protected:
  396. // Properties
  397. CCriticalSectionObject m_csLock;
  398. DWORD m_dwReadCount;
  399. DWORD m_dwWriteCount;
  400. DWORD m_dwTimeout;
  401. CHandleObject m_hSignalNoReaders;
  402. CHandleObject m_hSignalNoWriters;
  403. DWORD m_dwOwner;
  404. #ifdef DBG
  405. CDynamicArray<VOID> m_rgdwReaders;
  406. #endif
  407. // Methods
  408. void Wait(HANDLE hSignal);
  409. void Signal(HANDLE hSignal);
  410. void Unsignal(HANDLE hSignal);
  411. void WaitOnReaders(void)
  412. {
  413. Wait(m_hSignalNoReaders);
  414. };
  415. void WaitOnWriters(void)
  416. {
  417. Wait(m_hSignalNoWriters);
  418. };
  419. void SignalNoReaders(void)
  420. {
  421. Signal(m_hSignalNoReaders);
  422. };
  423. void SignalNoWriters(void)
  424. {
  425. Signal(m_hSignalNoWriters);
  426. };
  427. void UnsignalNoReaders(void)
  428. {
  429. Signal(m_hSignalNoReaders);
  430. };
  431. void UnsignalNoWriters(void)
  432. {
  433. Unsignal(m_hSignalNoWriters);
  434. };
  435. friend class CLockRead;
  436. friend class CLockWrite;
  437. };
  438. //
  439. //==============================================================================
  440. //
  441. // CLockRead
  442. //
  443. class CLockRead
  444. {
  445. public:
  446. // Constructors & Destructor
  447. CLockRead(CAccessLock *pLock);
  448. ~CLockRead();
  449. // Properties
  450. // Methods
  451. // Operators
  452. protected:
  453. // Properties
  454. CAccessLock * m_pLock;
  455. // Methods
  456. };
  457. //
  458. //==============================================================================
  459. //
  460. // CLockWrite
  461. //
  462. class CLockWrite
  463. {
  464. public:
  465. // Constructors & Destructor
  466. CLockWrite(CAccessLock *pLock);
  467. ~CLockWrite();
  468. // Properties
  469. // Methods
  470. // Operators
  471. protected:
  472. // Properties
  473. CAccessLock *m_pLock;
  474. // Methods
  475. };
  476. #endif // _LOCKS_H_