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.

502 lines
9.4 KiB

  1. /***************************************************************************
  2. Copyright (c) 2002 Microsoft Corporation
  3. Module Name:
  4. locklist.H
  5. Abstract:
  6. Private interface for Smartcard Driver Utility Library
  7. Environment:
  8. Kernel Mode Only
  9. Notes:
  10. THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  11. KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  12. IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  13. PURPOSE.
  14. Copyright (c) 2001 Microsoft Corporation. All Rights Reserved.
  15. Revision History:
  16. 05/14/2002 : created
  17. Authors:
  18. Randy Aull
  19. ****************************************************************************/
  20. #include "pch.h"
  21. #include "irplist.h"
  22. void
  23. LockedList_Init(
  24. PLOCKED_LIST LockedList,
  25. PKSPIN_LOCK ListLock
  26. )
  27. /*++
  28. Routine Description:
  29. Initializes a LOCKED_LIST structure
  30. Arguments:
  31. LockedList - Pointer to a LOCKED_LIST structure
  32. ListLock - Pointer to a SPIN_LOCK for the locked list
  33. Return Value:
  34. VOID
  35. --*/
  36. {
  37. InitializeListHead(&LockedList->ListHead);
  38. KeInitializeSpinLock(&LockedList->SpinLock);
  39. LockedList->ListLock = ListLock;
  40. LockedList->Count = 0;
  41. }
  42. void
  43. LockedList_EnqueueHead(
  44. PLOCKED_LIST LockedList,
  45. PLIST_ENTRY ListEntry
  46. )
  47. /*++
  48. Routine Description:
  49. Enqueue a List entry at the head of the locked list.
  50. Arguments:
  51. LockedList - Pointer to a LOCKED_LIST structure
  52. ListEntry - Pointer to a LIST_ENTRY structure
  53. Return Value:
  54. VOID
  55. --*/
  56. {
  57. KIRQL irql;
  58. LL_LOCK(LockedList, &irql);
  59. InsertHeadList(&LockedList->ListHead, ListEntry);
  60. LockedList->Count++;
  61. LL_UNLOCK(LockedList, irql) ;
  62. }
  63. void
  64. LockedList_EnqueueTail(
  65. PLOCKED_LIST LockedList,
  66. PLIST_ENTRY ListEntry
  67. )
  68. /*++
  69. Routine Description:
  70. Enqueue a List entry at the tail of the locked list.
  71. Arguments:
  72. LockedList - Pointer to a LOCKED_LIST structure
  73. ListEntry - Pointer to a LIST_ENTRY structure
  74. Return Value:
  75. VOID
  76. --*/
  77. {
  78. KIRQL irql;
  79. LL_LOCK(LockedList, &irql);
  80. InsertTailList(&LockedList->ListHead, ListEntry);
  81. LockedList->Count++;
  82. LL_UNLOCK(LockedList, irql) ;
  83. }
  84. void
  85. LockedList_EnqueueAfter(
  86. PLOCKED_LIST LockedList,
  87. PLIST_ENTRY Entry,
  88. PLIST_ENTRY Location
  89. )
  90. /*++
  91. Routine Description:
  92. Enqueue a List entry at a specific point in the LockedList.
  93. Arguments:
  94. LockedList - Pointer to a LOCKED_LIST structure
  95. Entry - Pointer to a LIST_ENTRY structure
  96. Location - Pointer to a LIST_ENTRY already contained in the LockedList
  97. Return Value:
  98. VOID
  99. Notes:
  100. It the Location is NULL, the entry is added to the tail of the list
  101. --*/
  102. {
  103. if (Location == NULL) {
  104. LL_ADD_TAIL(LockedList, Entry);
  105. }
  106. else {
  107. Entry->Flink = Location->Flink;
  108. Location->Flink->Blink = Entry;
  109. Location->Flink = Entry;
  110. Entry->Blink = Location;
  111. LockedList->Count++;
  112. }
  113. }
  114. PLIST_ENTRY
  115. LockedList_RemoveHead(
  116. PLOCKED_LIST LockedList
  117. )
  118. /*++
  119. Routine Description:
  120. Remove the head LIST_ENTRY from a LockedList.
  121. Arguments:
  122. LockedList - Pointer to a LOCKED_LIST structure
  123. Return Value:
  124. PLIST_ENTRY - Pointer to the head list of the Locked List
  125. NULL - if the Locked List is empty
  126. --*/
  127. {
  128. PLIST_ENTRY ple;
  129. KIRQL irql;
  130. ple = NULL;
  131. LL_LOCK(LockedList, &irql);
  132. if (!IsListEmpty(&LockedList->ListHead)) {
  133. ple = RemoveHeadList(&LockedList->ListHead);
  134. LockedList->Count--;
  135. }
  136. LL_UNLOCK(LockedList, irql);
  137. return ple;
  138. }
  139. PLIST_ENTRY
  140. LockedList_RemoveEntryLocked(
  141. PLOCKED_LIST LockedList,
  142. PLIST_ENTRY Entry)
  143. /*++
  144. Routine Description:
  145. Remove a specific entry from the LockedList. Assumes that the caller has
  146. acquired the spinlock
  147. Arguments:
  148. LockedList - Pointer to a LOCKED_LIST structure
  149. Entry - Pointer to a LIST_ENTRY structure
  150. Return Value:
  151. PLIST_ENTRY - Pointer to the Entry.
  152. --*/
  153. {
  154. ASSERT(!IsListEmpty(&LockedList->ListHead));
  155. ASSERT(LockedList->Count > 0);
  156. RemoveEntryList(Entry);
  157. LockedList->Count--;
  158. return Entry;
  159. }
  160. PLIST_ENTRY
  161. LockedList_RemoveEntry(
  162. PLOCKED_LIST LockedList,
  163. PLIST_ENTRY Entry
  164. )
  165. /*++
  166. Routine Description:
  167. Remove a specific entry from the LockedList
  168. Arguments:
  169. LockedList - Pointer to a LOCKED_LIST structure
  170. Entry - Pointer to a LIST_ENTRY structure
  171. Return Value:
  172. PLIST_ENTRY - Pointer to the Entry.
  173. --*/
  174. {
  175. PLIST_ENTRY ple;
  176. KIRQL irql;
  177. LL_LOCK(LockedList, &irql);
  178. ple = LockedList_RemoveEntryLocked(LockedList, Entry);
  179. LL_UNLOCK(LockedList, irql);
  180. return ple;
  181. }
  182. LONG
  183. LockedList_GetCount(
  184. PLOCKED_LIST LockedList
  185. )
  186. /*++
  187. Routine Description:
  188. Obtains the number of Entries in the LockedList
  189. Arguments:
  190. LockedList - Pointer to a LOCKED_LIST structure
  191. Return Value:
  192. LONG - Number of elements in the LockedList
  193. --*/
  194. {
  195. LONG count;
  196. KIRQL irql;
  197. LL_LOCK(LockedList, &irql);
  198. count = LockedList->Count;
  199. LL_UNLOCK(LockedList, irql) ;
  200. return count;
  201. }
  202. LONG
  203. LockedList_Drain(
  204. PLOCKED_LIST LockedList,
  205. PLIST_ENTRY DrainListHead
  206. )
  207. /*++
  208. Routine Description:
  209. Drains the elements from the LockedList into the DrainListHead and
  210. returns the number of elements
  211. Arguments:
  212. LockedList - Pointer to a LOCKED_LIST structure
  213. DrainListHead - Pointer to a LIST_ENTRY
  214. Return Value:
  215. LONG - Number of elements drained from LockedList into the DrainListHead
  216. --*/
  217. {
  218. PLIST_ENTRY ple;
  219. LONG count;
  220. KIRQL irql;
  221. count = 0;
  222. InitializeListHead(DrainListHead);
  223. LL_LOCK(LockedList, &irql);
  224. while (!IsListEmpty(&LockedList->ListHead)) {
  225. ple = RemoveHeadList(&LockedList->ListHead);
  226. LockedList->Count--;
  227. InsertTailList(DrainListHead, ple);
  228. count++;
  229. }
  230. ASSERT(LockedList->Count == 0);
  231. ASSERT(IsListEmpty(&LockedList->ListHead));
  232. LL_UNLOCK(LockedList, irql) ;
  233. return count;
  234. }
  235. BOOLEAN
  236. List_Process(
  237. PLIST_ENTRY ListHead,
  238. PFNLOCKED_LIST_PROCESS Process,
  239. PVOID ProcessContext
  240. )
  241. /*++
  242. Routine Description:
  243. Iterate over the list, call the process function for each element.
  244. Arguments:
  245. ListHead - Pointer to a LIST_ENTRY
  246. Process - Callback function for each element in the list. If the callback
  247. returns FALSE we break out of the iteration.
  248. ProcessContext - Context for the callback, supplied by the caller
  249. Return Value:
  250. TRUE - Walked over the entire list
  251. FALSE - Process function returned FALSE and stopped iteration
  252. --*/
  253. {
  254. PLIST_ENTRY ple;
  255. BOOLEAN result;
  256. //
  257. // We return if we iterated over the entire list.
  258. //
  259. result = TRUE;
  260. for (ple = ListHead->Flink; ple != ListHead; ple = ple->Flink) {
  261. //
  262. // If the Process callback wants to stop iterating over the list, then
  263. // it will return FALSE.
  264. //
  265. result = Process(ProcessContext, ple);
  266. if (result == FALSE) {
  267. break;
  268. }
  269. }
  270. return result;
  271. }
  272. BOOLEAN
  273. LockedList_ProcessLocked(
  274. PLOCKED_LIST LockedList,
  275. PFNLOCKED_LIST_PROCESS Process,
  276. PVOID ProcessContext
  277. )
  278. /*++
  279. Routine Description:
  280. Iterate over the list, call the process function for each element. Assumes
  281. the LockedList spinlock is acquired by the caller
  282. Arguments:
  283. LockedList - Pointer to the LOCKED_LIST
  284. Process - Callback function for each element in the list. If the callback
  285. returns FALSE we break out of the iteration.
  286. ProcessContext - Context for the callback, supplied by the caller
  287. Return Value:
  288. TRUE - Walked over the entire list
  289. FALSE - Process function returned FALSE and stopped iteration
  290. --*/
  291. {
  292. return List_Process(&LockedList->ListHead, Process, ProcessContext);
  293. }
  294. BOOLEAN
  295. LockedList_Process(
  296. PLOCKED_LIST LockedList,
  297. BOOLEAN LockAtPassive,
  298. PFNLOCKED_LIST_PROCESS Process,
  299. PVOID ProcessContext
  300. )
  301. /*++
  302. Routine Description:
  303. Iterate over the list, call the process function for each element.
  304. Arguments:
  305. LockedList - Pointer to the LOCKED_LIST
  306. LockAtPassive - If
  307. Process - Callback function for each element in the list. If the callback
  308. returns FALSE we break out of the iteration.
  309. ProcessContext - Context for the callback, supplied by the caller
  310. Return Value:
  311. TRUE - Walked over the entire list
  312. FALSE - Process function returned FALSE and stopped iteration
  313. --*/
  314. {
  315. KIRQL irql;
  316. BOOLEAN result;
  317. if (LockAtPassive) {
  318. LL_LOCK(LockedList, &irql);
  319. }
  320. else {
  321. LL_LOCK_AT_DPC(LockedList);
  322. }
  323. result = List_Process(&LockedList->ListHead, Process, ProcessContext);
  324. if (LockAtPassive) {
  325. LL_UNLOCK(LockedList, irql);
  326. }
  327. else {
  328. LL_UNLOCK_FROM_DPC(LockedList);
  329. }
  330. return result;
  331. }