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.

454 lines
12 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 IGMP can be compiled to use either form
  23. //
  24. #ifdef IGMP_RWL
  25. //
  26. // use IGMP'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. !IGMP_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 // IGMP_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. IGMP_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. DWORD Count; // number of threads waiting
  153. LIST_ENTRY Link; // link in list of free entries
  154. #ifdef LOCK_DBG
  155. DWORD Id;
  156. #endif
  157. #if DEBUG_FLAGS_SIGNATURE
  158. DWORD Signature;//0xfadfad03
  159. DWORD InAndOut;
  160. #endif
  161. } DYNAMIC_CS_LOCK, *PDYNAMIC_CS_LOCK;
  162. #if DEBUG_FLAGS_SIGNATURE
  163. #define DYNAMIC_LOCK_SET_SIGNATURE(pDCSLock) {\
  164. (pDCSLock)->Signature = 0xfadfad03;\
  165. (pDCSLock)->InAndOut = 0;\
  166. }
  167. #define DYNAMIC_LOCK_CHECK_SIGNATURE_DECR(pDCSLock) {\
  168. if ((pDCSLock)->Signature!=0xfadfad03) \
  169. DbgBreakPoint(); \
  170. if ((pDCSLock)->InAndOut--<=0) DbgBreakPoint(); \
  171. }
  172. #define DYNAMIC_LOCK_CHECK_SIGNATURE_INCR(pDCSLock) \
  173. if (++(pDCSLock)->InAndOut == 0) DbgBreakPoint();
  174. #else
  175. #define DYNAMIC_LOCK_SET_SIGNATURE(pDCSLock)
  176. #define DYNAMIC_LOCK_CHECK_SIGNATURE_DECR(pDCSLock)
  177. #define DYNAMIC_LOCK_CHECK_SIGNATURE_INCR(pDCSLock)
  178. #endif //DEBUG_FLAGS_SIGNATURE
  179. //---------------------------------------
  180. // DYNAMICALLY_LOCKED_HASH_TABLE
  181. // AcquireDynamicCSLockedList and ReleaseDynamicCSLock depend on this struct defn
  182. //---------------------------------------
  183. typedef struct _DYNAMIC_CS_LOCKED_LIST {
  184. LIST_ENTRY Link;
  185. PDYNAMIC_CS_LOCK pDCSLock;
  186. } DYNAMIC_CS_LOCKED_LIST, *PDYNAMIC_CS_LOCKED_LIST;
  187. #define InitDynamicCSLockedList(pDCSLockedList) { \
  188. InitializeListHead(&(pDCSLockedList)->Link); \
  189. (pDCSLockedList)->pDCSLock = NULL; \
  190. }
  191. //
  192. // if more than DYNAMIC_LOCKS_HIGH_THRESHOLD CS locks allocated
  193. // then any locks that are freed are destroyed
  194. //
  195. #define DYNAMIC_LOCKS_HIGH_THRESHOLD 7
  196. //-----------------------------------------------------------------
  197. // struct DYNAMIC_LOCKS_STORE
  198. //
  199. // Contains the store of free dynamic CS locks which can be
  200. // allocated when required. Protected by a CS
  201. //-----------------------------------------------------------------
  202. typedef struct _DYNAMIC_LOCKS_STORE {
  203. CRITICAL_SECTION CS;
  204. LIST_ENTRY ListOfFreeLocks;
  205. DWORD CountAllocated;
  206. DWORD CountFree;
  207. } DYNAMIC_LOCKS_STORE, *PDYNAMIC_LOCKS_STORE;
  208. #define AcquireDynamicCSLockedList(pDCSLockedList, pDCSStore) \
  209. AcquireDynamicCSLock(&((pDCSLockedList)->pDCSLock), pDCSStore)
  210. #define ReleaseDynamicCSLockedList(pDCSLockedList, pDCSStore) \
  211. ReleaseDynamicCSLock(&(pDCSLockedList)->pDCSLock, pDCSStore)
  212. //-----------------------------------------------------------------
  213. // struct DYNAMIC_RW_LOCK
  214. //
  215. // the dynamic lock struct which is allocated to anyone requesting it
  216. //-----------------------------------------------------------------
  217. typedef struct _DYNAMIC_RW_LOCK {
  218. READ_WRITE_LOCK RWL;
  219. DWORD Count; // number of threads waiting
  220. LIST_ENTRY Link; // link in list of free entries
  221. #ifdef LOCK_DBG
  222. DWORD Id;
  223. #endif
  224. #if DEBUG_FLAGS_SIGNATURE
  225. DWORD Signature;//0xfadfad03
  226. DWORD InAndOut;
  227. #endif
  228. } DYNAMIC_RW_LOCK, *PDYNAMIC_RW_LOCK;
  229. //---------------------------------------
  230. // DYNAMICALLY_LOCKED_HASH_TABLE
  231. // AcquireDynamicRWLockedList and ReleaseDynamicRWLock depend on this struct defn
  232. //---------------------------------------
  233. typedef struct _DYNAMIC_RW_LOCKED_LIST {
  234. LIST_ENTRY Link;
  235. PDYNAMIC_RW_LOCK pDRWLock;
  236. } DYNAMIC_RW_LOCKED_LIST, *PDYNAMIC_RW_LOCKED_LIST;
  237. #define InitDynamicRWLockedList(pDRWLockedList) { \
  238. InitializeListHead(&(pDRWLockedList)->Link); \
  239. (pDRWLockedList)->pDRWLock = NULL; \
  240. }
  241. #define AcquireDynamicRWLockedList(pDRWLockedList, pDRWStore) \
  242. AcquireDynamicCSLock(&((pDRWLockedList)->pDRWLock), pDRWStore)
  243. #define ReleaseDynamicRWLockedList(pDRWLockedList, pDRWStore) \
  244. ReleaseDynamicRWLock(&(pDRWLockedList)->pDRWLock, pDRWStore)
  245. //
  246. // PROTOTYPES
  247. //
  248. DWORD
  249. InitializeDynamicLocksStore (
  250. PDYNAMIC_LOCKS_STORE pDLStore //ptr to Dynamic CS Store
  251. );
  252. VOID
  253. DeInitializeDynamicLocksStore (
  254. PDYNAMIC_LOCKS_STORE pDCSStore,
  255. LOCK_TYPE LockType //if True, then store of CS, else of RW locks
  256. );
  257. DWORD
  258. AcquireDynamicCSLock (
  259. PDYNAMIC_CS_LOCK *ppDCSLock,
  260. PDYNAMIC_LOCKS_STORE pDCSStore
  261. );
  262. PDYNAMIC_CS_LOCK
  263. GetDynamicCSLock (
  264. PDYNAMIC_LOCKS_STORE pDCSStore
  265. );
  266. VOID
  267. ReleaseDynamicCSLock (
  268. PDYNAMIC_CS_LOCK *ppDCSLock,
  269. PDYNAMIC_LOCKS_STORE pDCSStore
  270. );
  271. VOID
  272. FreeDynamicCSLock (
  273. PDYNAMIC_CS_LOCK pDCSLock,
  274. PDYNAMIC_LOCKS_STORE pDCSStore
  275. );
  276. DWORD
  277. AcquireDynamicRWLock (
  278. PDYNAMIC_RW_LOCK *ppDRWLock,
  279. LOCK_TYPE LockMode,
  280. PDYNAMIC_LOCKS_STORE pDRWStore
  281. );
  282. PDYNAMIC_RW_LOCK
  283. GetDynamicRWLock (
  284. PDYNAMIC_LOCKS_STORE pDRWStore
  285. );
  286. VOID
  287. ReleaseDynamicRWLock (
  288. PDYNAMIC_RW_LOCK *ppDRWLock,
  289. LOCK_TYPE LockMode,
  290. PDYNAMIC_LOCKS_STORE pDRWStore
  291. );
  292. VOID
  293. FreeDynamicRWLock (
  294. PDYNAMIC_RW_LOCK pDRWLock,
  295. PDYNAMIC_LOCKS_STORE pDRWStore
  296. );
  297. BOOL EnterIgmpApi();
  298. VOID LeaveIgmpApi();
  299. DWORD QueueIgmpWorker();
  300. BOOL EnterIgmpWorker();
  301. VOID LeaveIgmpWorker();
  302. #endif // _SYNC_H_