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.

446 lines
7.7 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 = 16,
  47. //
  48. // Initial number of CHandleInfo objects we'll allocate !
  49. //
  50. INITIAL_FREE = 8,
  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. // Initialize the class
  83. //
  84. static BOOL
  85. InitClass() ;
  86. //
  87. // Terminate the class - release all outstanding handles !
  88. //
  89. static void
  90. TermClass() ;
  91. //
  92. // Get a CHandleInfo object !
  93. //
  94. static CHandleInfo*
  95. AllocHandleInfo() ;
  96. //
  97. // release a CHandleInfo object !
  98. //
  99. static void
  100. ReleaseHandleInfo( CHandleInfo* ) ;
  101. //
  102. // Check that the object is valid !
  103. //
  104. BOOL
  105. IsValid() {
  106. return m_dwSignature == SIGNATURE &&
  107. m_pNext != 0 &&
  108. m_pPrev != 0 ;
  109. }
  110. } ;
  111. //
  112. // This class serves two purposes : to provide for a linkable object
  113. // on which we can queue threads blocked upon semaphore handles, and
  114. // a mechanism to get and set semaphore handles for reader/writer locks etc...
  115. //
  116. class CWaitingThread : public CQElement {
  117. private :
  118. enum {
  119. POOL_HANDLES = 64,
  120. } ;
  121. //
  122. // Semaphore that we can use to block the thread !
  123. //
  124. CHandleInfo *m_pInfo ;
  125. //
  126. // Var to hold error that may have occurred manipulating the lock !
  127. //
  128. DWORD m_dwError ;
  129. //
  130. // Thread Local Storage offset for holding the handles !
  131. //
  132. static DWORD g_dwThreadHandle ;
  133. //
  134. // Array of Handles to Semaphores which we stash away in case
  135. // we have to release the handle being used by a thread at some point !
  136. //
  137. static HANDLE g_rghHandlePool[ POOL_HANDLES ] ;
  138. //
  139. // No copying of these objects allowed !!!
  140. //
  141. CWaitingThread( CWaitingThread& ) ;
  142. CWaitingThread& operator=( CWaitingThread& ) ;
  143. public :
  144. #ifdef DEBUG
  145. //
  146. // Thread Id - handy for debuggiing
  147. //
  148. DWORD m_dwThreadId ;
  149. #endif
  150. CWaitingThread() ;
  151. //
  152. // Functions to be called from the DllEntryProc function !
  153. //
  154. static BOOL
  155. InitClass() ;
  156. static BOOL
  157. TermClass() ;
  158. //
  159. // Thread Entry/Exit routines which can allocate semaphore handles for us !
  160. //
  161. static void
  162. ThreadEnter() ;
  163. static void
  164. ThreadExit() ;
  165. //
  166. // Function which gives us our thread handle !
  167. //
  168. inline HANDLE
  169. GetThreadHandle() const ;
  170. //
  171. // Function which will release a HANDLE to the Pool of available
  172. // semaphore handles !
  173. //
  174. inline void
  175. PoolHandle(
  176. HANDLE h
  177. ) const ;
  178. //
  179. // Function which will remove a handle from our thread's TLS !
  180. // The argument must originally be from the calling thread's TLS
  181. //
  182. inline void
  183. ClearHandle(
  184. HANDLE h
  185. ) ;
  186. //
  187. // Function which blocks the calling thread !!
  188. //
  189. inline BOOL
  190. Wait() const ;
  191. //
  192. // Function which can release a thread !!
  193. //
  194. inline BOOL
  195. Release() const ;
  196. //
  197. // This function is used in debug builds to check the state of our semaphore handles !
  198. //
  199. static inline
  200. BOOL ValidateHandle(
  201. HANDLE h
  202. ) ;
  203. } ;
  204. typedef TLockQueue< CWaitingThread > TThreadQueue ;
  205. class CSingleReleaseQueue {
  206. private :
  207. //
  208. // Queue of threads waiting to own the lock !
  209. //
  210. TThreadQueue m_Waiting ;
  211. public :
  212. #ifdef DEBUG
  213. DWORD m_ThreadIdNext ;
  214. #endif
  215. CSingleReleaseQueue(
  216. BOOL IsSignalled = TRUE
  217. ) ;
  218. //
  219. // Release a single waiting thread !
  220. //
  221. void Release( ) ;
  222. //
  223. // Wait for the queue to become signalled !
  224. //
  225. void WaitForIt(
  226. CWaitingThread& myself
  227. ) ;
  228. //
  229. // Wait for the queue to become signalled
  230. //
  231. void WaitForIt( ) ;
  232. } ;
  233. //
  234. // This class is similar to a semaphore -
  235. // Threads block indefinately on WaitForIt() and another
  236. // thread may release as many threads as required by calling
  237. // Release().
  238. //
  239. class CEventQueue {
  240. private :
  241. //
  242. // Number of threads that should be allowed to pass
  243. // through the event !!!
  244. //
  245. long m_ReleaseCount ;
  246. //
  247. // Queue of threads blocked on this event !
  248. //
  249. TThreadQueue m_WaitingThreads ;
  250. //
  251. // Any thread may call this to release threads from the queue
  252. //
  253. BOOL ResumeThreads(
  254. CWaitingThread*
  255. ) ;
  256. public :
  257. //
  258. // Create an event queue object
  259. //
  260. CEventQueue(
  261. long cInitial = 0
  262. ) ;
  263. ~CEventQueue() ;
  264. void Release(
  265. long NumberToRelease
  266. ) ;
  267. void WaitForIt(
  268. CWaitingThread& myself
  269. ) ;
  270. void WaitForIt() ;
  271. void Reset() ;
  272. } ;
  273. //
  274. // Function which gives us our thread handle !
  275. //
  276. inline HANDLE
  277. CWaitingThread::GetThreadHandle() const {
  278. _ASSERT( ValidateHandle( m_pInfo->m_hSemaphore ) ) ;
  279. return m_pInfo->m_hSemaphore ;
  280. }
  281. //
  282. // Function which takes a handle (must not be ours)
  283. // and places it into a pool of handles available for other threads !
  284. //
  285. inline void
  286. CWaitingThread::PoolHandle( HANDLE h ) const {
  287. _ASSERT( h != m_pInfo->m_hSemaphore && h != 0 ) ;
  288. _ASSERT( ValidateHandle( h ) ) ;
  289. for( int i=0;
  290. i < sizeof( g_rghHandlePool ) / sizeof( g_rghHandlePool[0] ) &&
  291. h != 0;
  292. i++ ) {
  293. h = (HANDLE)InterlockedExchange( (long*)&g_rghHandlePool[i], (long)h ) ;
  294. }
  295. if( h != 0 ) {
  296. _VERIFY( CloseHandle( h ) ) ;
  297. }
  298. }
  299. //
  300. // Release our Handle from TLS, somebody else is going to use it !
  301. //
  302. inline void
  303. CWaitingThread::ClearHandle( HANDLE h ) {
  304. _ASSERT( h != 0 && h == m_pInfo->m_hSemaphore ) ;
  305. m_pInfo->m_hSemaphore = 0 ;
  306. //TlsSetValue( g_dwThreadHandle, (LPVOID) 0 ) ;
  307. }
  308. //
  309. // Block on the handle held within our object !
  310. //
  311. inline BOOL
  312. CWaitingThread::Wait() const {
  313. _ASSERT( m_pInfo->m_hSemaphore != 0 ) ;
  314. return WAIT_OBJECT_0 == WaitForSingleObject( m_pInfo->m_hSemaphore, INFINITE ) ;
  315. }
  316. //
  317. // Release a thread which is blocked on the semaphore within !!
  318. //
  319. inline BOOL
  320. CWaitingThread::Release() const {
  321. _ASSERT( m_pInfo->m_hSemaphore != 0 ) ;
  322. _ASSERT( ValidateHandle( m_pInfo->m_hSemaphore ) ) ;
  323. return ReleaseSemaphore( m_pInfo->m_hSemaphore, 1, NULL ) ;
  324. }
  325. //
  326. //
  327. //
  328. inline BOOL
  329. CWaitingThread::ValidateHandle( HANDLE h ) {
  330. DWORD dw = WaitForSingleObject( h, 0 ) ;
  331. _ASSERT( dw == WAIT_TIMEOUT ) ;
  332. return dw == WAIT_TIMEOUT ;
  333. }
  334. #endif