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.

463 lines
8.1 KiB

  1. /*++
  2. rwintrnl.h
  3. Reader/Writer locks internal header file
  4. This file defines several objects used to implement
  5. reader/writer locks, however these objects should
  6. not be directly used by any client of rw.h
  7. --*/
  8. #ifndef _RWINTRNL_H_
  9. #define _RWINTRNL_H_
  10. class CHandleInfo {
  11. /*++
  12. This class keeps track of all the handles we've allocated for
  13. use by various threads. We can't use Thread Local Storage
  14. directly because we can be dynamically unloaded, in which case
  15. we need to free all of our HANDLES !
  16. --*/
  17. private :
  18. //
  19. // Signature for our
  20. //
  21. DWORD m_dwSignature ;
  22. class CHandleInfo* m_pNext ;
  23. class CHandleInfo* m_pPrev ;
  24. CHandleInfo( CHandleInfo& ) ;
  25. CHandleInfo& operator=( CHandleInfo& ) ;
  26. //
  27. // Global lock to protect free and allocated lists !
  28. //
  29. static CRITICAL_SECTION s_InUseList ;
  30. //
  31. // Allocated CHandleInfo objects !
  32. //
  33. static CHandleInfo s_Head ;
  34. //
  35. // Free CHandleInfo objects
  36. //
  37. static CHandleInfo s_FreeHead ;
  38. //
  39. // Number of Free CHandleInfo objects in the s_FreeHead list
  40. //
  41. static DWORD s_cFreeList ;
  42. enum constants {
  43. //
  44. // Maximum number of CHandleInfo objects we'll hold onto !
  45. //
  46. MAX_FREE = 64,
  47. //
  48. // Initial number of CHandleInfo objects we'll allocate !
  49. //
  50. INITIAL_FREE = 32,
  51. //
  52. // Signature in our objects !
  53. //
  54. SIGNATURE = (DWORD)'hnwR'
  55. } ;
  56. //
  57. // Memory Allocation is done the hard way !
  58. //
  59. void* operator new( size_t size ) ;
  60. void operator delete( void *pv ) ;
  61. //
  62. // List Manipulation routines !
  63. //
  64. void
  65. InsertAtHead( CHandleInfo* pHead ) ;
  66. //
  67. // Remove the element from the list - returns this pointer !
  68. //
  69. CHandleInfo*
  70. RemoveList( ) ;
  71. public :
  72. //
  73. // Constructor and Destructor !
  74. //
  75. CHandleInfo() ;
  76. ~CHandleInfo() ;
  77. //
  78. // This is public for all to use !
  79. //
  80. HANDLE m_hSemaphore ;
  81. //
  82. // This is an auto-reset event handle available for anybody
  83. // and retrievable through GetPerThreadEvent() ;
  84. //
  85. HANDLE m_hEvent ;
  86. //
  87. // Initialize the class
  88. //
  89. static BOOL
  90. InitClass() ;
  91. //
  92. // Terminate the class - release all outstanding handles !
  93. //
  94. static void
  95. TermClass() ;
  96. //
  97. // Get a CHandleInfo object !
  98. //
  99. static CHandleInfo*
  100. AllocHandleInfo() ;
  101. //
  102. // release a CHandleInfo object !
  103. //
  104. static void
  105. ReleaseHandleInfo( CHandleInfo* ) ;
  106. //
  107. // Check that the object is valid !
  108. //
  109. BOOL
  110. IsValid() {
  111. return m_dwSignature == SIGNATURE &&
  112. m_pNext != 0 &&
  113. m_pPrev != 0 ;
  114. }
  115. } ;
  116. //
  117. // This class serves two purposes : to provide for a linkable object
  118. // on which we can queue threads blocked upon semaphore handles, and
  119. // a mechanism to get and set semaphore handles for reader/writer locks etc...
  120. //
  121. class CWaitingThread : public CQElement {
  122. private :
  123. enum {
  124. POOL_HANDLES = 64,
  125. } ;
  126. //
  127. // Semaphore that we can use to block the thread !
  128. //
  129. CHandleInfo *m_pInfo ;
  130. //
  131. // Var to hold error that may have occurred manipulating the lock !
  132. //
  133. DWORD m_dwError ;
  134. //
  135. // Thread Local Storage offset for holding the handles !
  136. //
  137. static DWORD g_dwThreadHandle ;
  138. //
  139. // Array of Handles to Semaphores which we stash away in case
  140. // we have to release the handle being used by a thread at some point !
  141. //
  142. static HANDLE g_rghHandlePool[ POOL_HANDLES ] ;
  143. //
  144. // No copying of these objects allowed !!!
  145. //
  146. CWaitingThread( CWaitingThread& ) ;
  147. CWaitingThread& operator=( CWaitingThread& ) ;
  148. public :
  149. #ifdef DEBUG
  150. //
  151. // Thread Id - handy for debuggiing
  152. //
  153. DWORD m_dwThreadId ;
  154. #endif
  155. CWaitingThread() ;
  156. //
  157. // Functions to be called from the DllEntryProc function !
  158. //
  159. static BOOL
  160. InitClass() ;
  161. static BOOL
  162. TermClass() ;
  163. //
  164. // Thread Entry/Exit routines which can allocate semaphore handles for us !
  165. //
  166. static void
  167. ThreadEnter() ;
  168. static void
  169. ThreadExit() ;
  170. //
  171. // Function which gives us our Event Handle
  172. //
  173. inline HANDLE
  174. GetThreadEvent() const ;
  175. //
  176. // Function which gives us our thread handle !
  177. //
  178. inline HANDLE
  179. GetThreadHandle() const ;
  180. //
  181. // Function which will release a HANDLE to the Pool of available
  182. // semaphore handles !
  183. //
  184. inline void
  185. PoolHandle(
  186. HANDLE h
  187. ) const ;
  188. //
  189. // Function which will remove a handle from our thread's TLS !
  190. // The argument must originally be from the calling thread's TLS
  191. //
  192. inline void
  193. ClearHandle(
  194. HANDLE h
  195. ) ;
  196. //
  197. // Function which blocks the calling thread !!
  198. //
  199. inline BOOL
  200. Wait() const ;
  201. //
  202. // Function which can release a thread !!
  203. //
  204. inline BOOL
  205. Release() const ;
  206. //
  207. // This function is used in debug builds to check the state of our semaphore handles !
  208. //
  209. static inline
  210. BOOL ValidateHandle(
  211. HANDLE h
  212. ) ;
  213. } ;
  214. typedef TLockQueue< CWaitingThread > TThreadQueue ;
  215. class CSingleReleaseQueue {
  216. private :
  217. //
  218. // Queue of threads waiting to own the lock !
  219. //
  220. TThreadQueue m_Waiting ;
  221. public :
  222. #ifdef DEBUG
  223. DWORD m_ThreadIdNext ;
  224. #endif
  225. CSingleReleaseQueue(
  226. BOOL IsSignalled = TRUE
  227. ) ;
  228. //
  229. // Release a single waiting thread !
  230. //
  231. void Release( ) ;
  232. //
  233. // Wait for the queue to become signalled !
  234. //
  235. void WaitForIt(
  236. CWaitingThread& myself
  237. ) ;
  238. //
  239. // Wait for the queue to become signalled
  240. //
  241. void WaitForIt( ) ;
  242. } ;
  243. //
  244. // This class is similar to a semaphore -
  245. // Threads block indefinately on WaitForIt() and another
  246. // thread may release as many threads as required by calling
  247. // Release().
  248. //
  249. class CEventQueue {
  250. private :
  251. //
  252. // Number of threads that should be allowed to pass
  253. // through the event !!!
  254. //
  255. long m_ReleaseCount ;
  256. //
  257. // Queue of threads blocked on this event !
  258. //
  259. TThreadQueue m_WaitingThreads ;
  260. //
  261. // Any thread may call this to release threads from the queue
  262. //
  263. BOOL ResumeThreads(
  264. CWaitingThread*
  265. ) ;
  266. public :
  267. //
  268. // Create an event queue object
  269. //
  270. CEventQueue(
  271. long cInitial = 0
  272. ) ;
  273. ~CEventQueue() ;
  274. void Release(
  275. long NumberToRelease
  276. ) ;
  277. void WaitForIt(
  278. CWaitingThread& myself
  279. ) ;
  280. void WaitForIt() ;
  281. void Reset() ;
  282. } ;
  283. //
  284. // Function which gives us our thread handle !
  285. //
  286. inline HANDLE
  287. CWaitingThread::GetThreadHandle() const {
  288. _ASSERT( ValidateHandle( m_pInfo->m_hSemaphore ) ) ;
  289. return m_pInfo->m_hSemaphore ;
  290. }
  291. //
  292. // Function which takes a handle (must not be ours)
  293. // and places it into a pool of handles available for other threads !
  294. //
  295. inline void
  296. CWaitingThread::PoolHandle( HANDLE h ) const {
  297. _ASSERT( h != m_pInfo->m_hSemaphore && h != 0 ) ;
  298. _ASSERT( ValidateHandle( h ) ) ;
  299. for( int i=0;
  300. i < sizeof( g_rghHandlePool ) / sizeof( g_rghHandlePool[0] ) &&
  301. h != 0;
  302. i++ ) {
  303. h = (HANDLE)InterlockedExchangePointer( (PVOID*)&g_rghHandlePool[i], h ) ;
  304. }
  305. if( h != 0 ) {
  306. _VERIFY( CloseHandle( h ) ) ;
  307. }
  308. }
  309. //
  310. // Release our Handle from TLS, somebody else is going to use it !
  311. //
  312. inline void
  313. CWaitingThread::ClearHandle( HANDLE h ) {
  314. _ASSERT( h != 0 && h == m_pInfo->m_hSemaphore ) ;
  315. m_pInfo->m_hSemaphore = 0 ;
  316. //TlsSetValue( g_dwThreadHandle, (LPVOID) 0 ) ;
  317. }
  318. //
  319. // Block on the handle held within our object !
  320. //
  321. inline BOOL
  322. CWaitingThread::Wait() const {
  323. _ASSERT( m_pInfo->m_hSemaphore != 0 ) ;
  324. return WAIT_OBJECT_0 == WaitForSingleObject( m_pInfo->m_hSemaphore, INFINITE ) ;
  325. }
  326. //
  327. // Release a thread which is blocked on the semaphore within !!
  328. //
  329. inline BOOL
  330. CWaitingThread::Release() const {
  331. _ASSERT( m_pInfo->m_hSemaphore != 0 ) ;
  332. _ASSERT( ValidateHandle( m_pInfo->m_hSemaphore ) ) ;
  333. return ReleaseSemaphore( m_pInfo->m_hSemaphore, 1, NULL ) ;
  334. }
  335. //
  336. //
  337. //
  338. inline BOOL
  339. CWaitingThread::ValidateHandle( HANDLE h ) {
  340. DWORD dw = WaitForSingleObject( h, 0 ) ;
  341. _ASSERT( dw == WAIT_TIMEOUT ) ;
  342. return dw == WAIT_TIMEOUT ;
  343. }
  344. inline HANDLE
  345. CWaitingThread::GetThreadEvent() const {
  346. return m_pInfo->m_hEvent ;
  347. }
  348. #endif