Source code of Windows XP (NT5)
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.

447 lines
11 KiB

  1. //============================================================================
  2. // Copyright (c) 1995, Microsoft Corporation
  3. // File: sync.h
  4. //
  5. // History:
  6. // Abolade Gbadegesin
  7. // K.S.Lokesh (added Dynamic Locking)
  8. //
  9. // Contains structures and macros used to implement synchronization.
  10. //============================================================================
  11. #ifndef _SYNC_H_
  12. #define _SYNC_H_
  13. //
  14. // type definition for multiple-reader/single-writer lock
  15. // Note: there is a similar facility provided by nturtl.h
  16. // through the structure RTL_RESOURCE and several functions.
  17. // However, that implementation has the potential for starving
  18. // a thread trying to acquire write accesss, if there are a large
  19. // number of threads interested in acquiring read access.
  20. // Such a scenario is avoided in the implementation given in this
  21. // header. However, a mapping is also given to the RTL_RESOURCE
  22. // functionality, so that DVMRP can be compiled to use either form
  23. //
  24. #ifdef DVMRP_RWL
  25. //
  26. // use DVMRP's definitions
  27. //
  28. typedef struct _READ_WRITE_LOCK {
  29. CRITICAL_SECTION RWL_ReadWriteBlock;
  30. LONG RWL_ReaderCount;
  31. HANDLE RWL_ReaderDoneEvent;
  32. } READ_WRITE_LOCK, *PREAD_WRITE_LOCK;
  33. DWORD CreateReadWriteLock(PREAD_WRITE_LOCK pRWL);
  34. VOID DeleteReadWriteLock(PREAD_WRITE_LOCK pRWL);
  35. VOID AcquireReadLock(PREAD_WRITE_LOCK pRWL);
  36. VOID ReleaseReadLock(PREAD_WRITE_LOCK pRWL);
  37. VOID AcquireWriteLock(PREAD_WRITE_LOCK pRWL);
  38. VOID ReleaseWriteLock(PREAD_WRITE_LOCK pRWL);
  39. //
  40. // macro functions for manipulating a read-write lock
  41. //
  42. #define CREATE_READ_WRITE_LOCK(pRWL) \
  43. CreateReadWriteLock(pRWL)
  44. #define DELETE_READ_WRITE_LOCK(pRWL) \
  45. DeleteReadWriteLock(pRWL)
  46. #define READ_WRITE_LOCK_CREATED(pRWL) \
  47. ((pRWL)->RWL_ReaderDoneEvent != NULL)
  48. // print locks.
  49. #ifdef LOCK_DBG
  50. #define ACQUIRE_READ_LOCK(pRWL, type, proc) {\
  51. Trace2(CS,"----to AcquireReadLock %s in %s", type, proc); \
  52. AcquireReadLock(pRWL); \
  53. Trace2(CS,"----GotReadLock %s in %s", type, proc); \
  54. }
  55. #define RELEASE_READ_LOCK(pRWL, type, proc) {\
  56. Trace2(CS,"----Released ReadLock %s in %s", type, proc); \
  57. ReleaseReadLock(pRWL); \
  58. }
  59. #define ACQUIRE_WRITE_LOCK(pRWL, type, proc) {\
  60. Trace2(CS,"----to AcquireWriteLock %s in %s", type, proc); \
  61. AcquireWriteLock(pRWL); \
  62. Trace2(CS,"----AcquiredWriteLock %s in %s", type, proc);\
  63. }
  64. #define RELEASE_WRITE_LOCK(pRWL, type, proc) {\
  65. Trace2(CS,"----Released WriteLock %s in %s", type, proc); \
  66. ReleaseWriteLock(pRWL);\
  67. }
  68. #else //LOCK_DBG
  69. #define ACQUIRE_READ_LOCK(pRWL, type, proc) \
  70. AcquireReadLock(pRWL)
  71. #define RELEASE_READ_LOCK(pRWL, type, proc) \
  72. ReleaseReadLock(pRWL)
  73. #define ACQUIRE_WRITE_LOCK(pRWL, type, proc) \
  74. AcquireWriteLock(pRWL)
  75. #define RELEASE_WRITE_LOCK(pRWL, type, proc) \
  76. ReleaseWriteLock(pRWL)
  77. #endif //LOCK_DBG
  78. #define READ_LOCK_TO_WRITE_LOCK(pRWL, type, proc) \
  79. (RELEASE_READ_LOCK(pRWL, type, proc), ACQUIRE_WRITE_LOCK(pRWL, type, proc))
  80. #define WRITE_LOCK_TO_READ_LOCK(pRWL) \
  81. (RELEASE_WRITE_LOCK(pRWL, type, proc), ACQUIRE_READ_LOCK(pRWL, type, proc))
  82. #else // i.e. !DVMRP_RWL
  83. //
  84. // use the RTL_RESOURCE mechanism
  85. //
  86. typedef RTL_RESOURCE READ_WRITE_LOCK, *PREAD_WRITE_LOCK;
  87. #define CREATE_READ_WRITE_LOCK(pRWL) \
  88. RtlInitializeResource((pRWL))
  89. #define DELETE_READ_WRITE_LOCK(pRWL) \
  90. RtlDeleteResource((pRWL))
  91. #define READ_WRITE_LOCK_CREATED(pRWL) (TRUE)
  92. #define ACQUIRE_READ_LOCK(pRWL) \
  93. RtlAcquireResourceShared((pRWL),TRUE)
  94. #define RELEASE_READ_LOCK(pRWL) \
  95. RtlReleaseResource((pRWL))
  96. #define ACQUIRE_WRITE_LOCK(pRWL) \
  97. RtlAcquireResourceExclusive((pRWL),TRUE)
  98. #define RELEASE_WRITE_LOCK(pRWL) \
  99. RtlReleaseResource((pRWL))
  100. #define READ_LOCK_TO_WRITE_LOCK(pRWL) \
  101. RtlConvertSharedToExclusive((pRWL))
  102. #define WRITE_LOCK_TO_READ_LOCK(pRWL) \
  103. RtlConvertExclusiveToShared((pRWL))
  104. #endif // DVMRP_RWL
  105. //
  106. // type definition for generic locked list
  107. // access is sychronized with a critical section
  108. //
  109. typedef struct _LOCKED_LIST {
  110. LIST_ENTRY Link;
  111. CRITICAL_SECTION Lock;
  112. DWORD CreatedFlag;
  113. } LOCKED_LIST, *PLOCKED_LIST;
  114. //
  115. // macro functions for manipulating the locked list
  116. //
  117. #define CREATE_LOCKED_LIST(pLL) {\
  118. InitializeListHead(&(pLL)->Link); \
  119. InitializeCriticalSection(&(pLL)->Lock); \
  120. (pLL)->CreatedFlag = 0x12345678; \
  121. }
  122. #define LOCKED_LIST_CREATED(pLL) \
  123. ((pLL)->CreatedFlag == 0x12345678)
  124. #define DELETE_LOCKED_LIST(pLL,type,field) { \
  125. PLIST_ENTRY _ple; \
  126. (pLL)->CreatedFlag = 0; \
  127. DeleteCriticalSection(&(pLL)->Lock); \
  128. while (!IsListEmpty(&(pLL)->Link)) { \
  129. _ple = RemoveHeadList(&(pLL)->Link); \
  130. DVMRP_FREE(CONTAINING_RECORD(_ple,type,field));\
  131. } \
  132. }
  133. #define ACQUIRE_LIST_LOCK(pLL, type, name) \
  134. ENTER_CRITICAL_SECTION(&(pLL)->Lock, type, name)
  135. #define RELEASE_LIST_LOCK(pLL, type, name) \
  136. LEAVE_CRITICAL_SECTION(&(pLL)->Lock, type, name)
  137. // for debugging, Set ids for each dynamic lock
  138. #ifdef LOCK_DBG
  139. extern DWORD DynamicCSLockId;
  140. extern DWORD DynamicRWLockId;
  141. #endif;
  142. typedef enum {
  143. LOCK_TYPE_CS, LOCK_TYPE_RW, LOCK_MODE_READ, LOCK_MODE_WRITE
  144. } LOCK_TYPE;
  145. //-----------------------------------------------------------------
  146. // struct DYNAMIC_CS_LOCK
  147. //
  148. // the dynamic lock struct which is allocated to anyone requesting it
  149. //-----------------------------------------------------------------
  150. typedef struct _DYNAMIC_CS_LOCK {
  151. CRITICAL_SECTION CS;
  152. union {
  153. DWORD Count; // number of threads waiting
  154. LIST_ENTRY Link; // link in list of free entries
  155. };
  156. #ifdef LOCK_DBG
  157. DWORD Id;
  158. #endif
  159. } DYNAMIC_CS_LOCK, *PDYNAMIC_CS_LOCK;
  160. //---------------------------------------
  161. // DYNAMICALLY_LOCKED_HASH_TABLE
  162. // AcquireDynamicCSLockedList and ReleaseDynamicCSLock depend on this struct defn
  163. //---------------------------------------
  164. typedef struct _DYNAMIC_CS_LOCKED_LIST {
  165. LIST_ENTRY Link;
  166. PDYNAMIC_CS_LOCK pDCSLock;
  167. } DYNAMIC_CS_LOCKED_LIST, *PDYNAMIC_CS_LOCKED_LIST;
  168. #define InitDynamicCSLockedList(pDCSLockedList) { \
  169. InitializeListHead(&(pDCSLockedList)->Link); \
  170. (pDCSLockedList)->pDCSLock = NULL; \
  171. }
  172. //
  173. // if more than DYNAMIC_LOCKS_CS_HIGH_THRESHOLD CS locks allocated
  174. // then any locks that are freed are destroyed
  175. //
  176. #define DYNAMIC_LOCKS_CS_HIGH_THRESHOLD 7
  177. //-----------------------------------------------------------------
  178. // struct DYNAMIC_LOCKS_STORE
  179. //
  180. // Contains the store of free dynamic CS locks which can be
  181. // allocated when required. Protected by a CS
  182. //-----------------------------------------------------------------
  183. typedef struct _DYNAMIC_LOCKS_STORE {
  184. CRITICAL_SECTION CS;
  185. LIST_ENTRY ListOfFreeLocks;
  186. DWORD CountAllocated;
  187. DWORD CountFree;
  188. } DYNAMIC_LOCKS_STORE, *PDYNAMIC_LOCKS_STORE;
  189. #define AcquireDynamicCSLockedList(pDCSLockedList, pDCSStore) \
  190. AcquireDynamicCSLock(&((pDCSLockedList)->pDCSLock), pDCSStore)
  191. #define ReleaseDynamicCSLockedList(pDCSLockedList, pDCSStore) \
  192. ReleaseDynamicCSLock(&(pDCSLockedList)->pDCSLock, pDCSStore)
  193. //
  194. // if more than DYNAMIC_LOCKS_CS_HIGH_THRESHOLD CS locks allocated
  195. // then any locks that are freed are destroyed
  196. //
  197. #define DYNAMIC_LOCKS_CS_HIGH_THRESHOLD 7
  198. //-----------------------------------------------------------------
  199. // struct DYNAMIC_RW_LOCK
  200. //
  201. // the dynamic lock struct which is allocated to anyone requesting it
  202. //-----------------------------------------------------------------
  203. typedef struct _DYNAMIC_RW_LOCK {
  204. READ_WRITE_LOCK RWL;
  205. union {
  206. DWORD Count; // number of threads waiting
  207. LIST_ENTRY Link; // link in list of free entries
  208. };
  209. #ifdef LOCK_DBG
  210. DWORD Id;
  211. #endif
  212. } DYNAMIC_RW_LOCK, *PDYNAMIC_RW_LOCK;
  213. //---------------------------------------
  214. // DYNAMICALLY_LOCKED_HASH_TABLE
  215. // AcquireDynamicRWLockedList and ReleaseDynamicRWLock depend on this struct defn
  216. //---------------------------------------
  217. typedef struct _DYNAMIC_RW_LOCKED_LIST {
  218. LIST_ENTRY Link;
  219. PDYNAMIC_RW_LOCK pDRWLock;
  220. } DYNAMIC_RW_LOCKED_LIST, *PDYNAMIC_RW_LOCKED_LIST;
  221. #define InitDynamicRWLockedList(pDRWLockedList) { \
  222. InitializeListHead(&(pDRWLockedList)->Link); \
  223. (pDRWLockedList)->pDRWLock = NULL; \
  224. }
  225. #define AcquireDynamicRWLockedList(pDRWLockedList, pDRWStore) \
  226. AcquireDynamicCSLock(&((pDRWLockedList)->pDRWLock), pDRWStore)
  227. #define ReleaseDynamicRWLockedList(pDRWLockedList, pDRWStore) \
  228. ReleaseDynamicRWLock(&(pDRWLockedList)->pDRWLock, pDRWStore)
  229. //
  230. // PROTOTYPES
  231. //
  232. DWORD
  233. InitializeDynamicLocks (
  234. PDYNAMIC_LOCKS_STORE pDLStore //ptr to Dynamic CS Store
  235. );
  236. VOID
  237. DeInitializeDynamicLocks (
  238. PDYNAMIC_LOCKS_STORE pDCSStore,
  239. LOCK_TYPE LockType //if True, then store of CS, else of RW locks
  240. );
  241. DWORD
  242. AcquireDynamicCSLock (
  243. PDYNAMIC_CS_LOCK *ppDCSLock,
  244. PDYNAMIC_LOCKS_STORE pDCSStore
  245. );
  246. PDYNAMIC_CS_LOCK
  247. GetDynamicCSLock (
  248. PDYNAMIC_LOCKS_STORE pDCSStore
  249. );
  250. VOID
  251. ReleaseDynamicCSLock (
  252. PDYNAMIC_CS_LOCK *ppDCSLock,
  253. PDYNAMIC_LOCKS_STORE pDCSStore
  254. );
  255. VOID
  256. FreeDynamicCSLock (
  257. PDYNAMIC_CS_LOCK pDCSLock,
  258. PDYNAMIC_LOCKS_STORE pDCSStore
  259. );
  260. DWORD
  261. AcquireDynamicRWLock (
  262. PDYNAMIC_RW_LOCK *ppDRWLock,
  263. LOCK_TYPE LockMode,
  264. PDYNAMIC_LOCKS_STORE pDRWStore
  265. );
  266. #define ACQUIRE_DYNAMIC_READ_LOCK(RWL, Store) \
  267. AcquireDynamicRWLock(DRWL, LOCK_MODE_READ, Store)
  268. #define RELEASE_DYNAMIC_READ_LOCK(RWL, Store) \
  269. ReleaseDynamicRWLock(DRWL,LOCK_MODE_READ, Store)
  270. #define ACQUIRE_DYNAMIC_WRITE_LOCK(RWL, Store) \
  271. AcquireDynamicRWLock(DRWL,LOCK_MODE_WRITE, Store)
  272. #define RELEASE_DYNAMIC_WRITE_LOCK(RWL, Store) \
  273. ReleaseDynamicRWLock(DRWL,LOCK_MODE_WRITE, Store)
  274. PDYNAMIC_RW_LOCK
  275. GetDynamicRWLock (
  276. PDYNAMIC_LOCKS_STORE pDRWStore
  277. );
  278. VOID
  279. ReleaseDynamicRWLock (
  280. PDYNAMIC_RW_LOCK *ppDRWLock,
  281. LOCK_TYPE LockMode,
  282. PDYNAMIC_LOCKS_STORE pDRWStore
  283. );
  284. VOID
  285. FreeDynamicRWLock (
  286. PDYNAMIC_RW_LOCK pDRWLock,
  287. PDYNAMIC_LOCKS_STORE pDRWStore
  288. );
  289. DWORD QueueDvmrpWorker();
  290. BOOL EnterDvmrpWorker();
  291. VOID LeaveDvmrpWorker();
  292. #endif // _SYNC_H_