3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ex/list.c
6 * PURPOSE: Manages double linked lists, single linked lists and
8 * PROGRAMMERS: David Welch (welch@mcmail.com)
9 * Casper S. Hornstrup (chorns@users.sourceforge.net)
11 * 02-07-2001 CSH Implemented sequenced lists
14 /* INCLUDES *****************************************************************/
17 //#define NONAMELESSUNION
19 #include <ddk/ntddk.h>
22 #include <internal/debug.h>
25 static KSPIN_LOCK ExpGlobalListLock = { 0, };
26 #endif /* LIBCAPTIVE */
28 /* FUNCTIONS *************************************************************/
34 ExInterlockedInsertHeadList(PLIST_ENTRY ListHead,
35 PLIST_ENTRY ListEntry,
38 * FUNCTION: Inserts an entry at the head of a doubly linked list
40 * ListHead = Points to the head of the list
41 * ListEntry = Points to the entry to be inserted
42 * Lock = Caller supplied spinlock used to synchronize access
43 * RETURNS: The previous head of the list
49 KeAcquireSpinLock(Lock,&oldlvl);
50 if (IsListEmpty(ListHead))
56 Old = ListHead->Flink;
58 InsertHeadList(ListHead,ListEntry);
59 KeReleaseSpinLock(Lock,oldlvl);
69 ExInterlockedInsertTailList(PLIST_ENTRY ListHead,
70 PLIST_ENTRY ListEntry,
73 * FUNCTION: Inserts an entry at the tail of a doubly linked list
75 * ListHead = Points to the head of the list
76 * ListEntry = Points to the entry to be inserted
77 * Lock = Caller supplied spinlock used to synchronize access
78 * RETURNS: The previous head of the list
84 KeAcquireSpinLock(Lock,&oldlvl);
85 if (IsListEmpty(ListHead))
91 Old = ListHead->Blink;
93 InsertTailList(ListHead,ListEntry);
94 KeReleaseSpinLock(Lock,oldlvl);
104 ExInterlockedRemoveHeadList(PLIST_ENTRY Head,
107 * FUNCTION: Removes the head of a double linked list
109 * Head = Points to the head of the list
110 * Lock = Lock for synchronizing access to the list
111 * RETURNS: The removed entry
117 KeAcquireSpinLock(Lock,&oldlvl);
118 if (IsListEmpty(Head))
124 ret = RemoveHeadList(Head);
126 KeReleaseSpinLock(Lock,oldlvl);
132 ExInterlockedRemoveTailList(PLIST_ENTRY Head,
135 * FUNCTION: Removes the tail of a double linked list
137 * Head = Points to the head of the list
138 * Lock = Lock for synchronizing access to the list
139 * RETURNS: The removed entry
145 KeAcquireSpinLock(Lock,&oldlvl);
146 if (IsListEmpty(Head))
152 ret = RemoveTailList(Head);
154 KeReleaseSpinLock(Lock,oldlvl);
159 #ifdef ExInterlockedPopEntrySList
160 #undef ExInterlockedPopEntrySList
166 PSINGLE_LIST_ENTRY FASTCALL
167 ExInterlockedPopEntrySList(IN PSLIST_HEADER ListHead,
170 * FUNCTION: Removes (pops) an entry from a sequenced list
172 * ListHead = Points to the head of the list
173 * Lock = Lock for synchronizing access to the list
174 * RETURNS: The removed entry
177 PSINGLE_LIST_ENTRY ret;
180 KeAcquireSpinLock(Lock,&oldlvl);
181 ret = PopEntryList(&ListHead->Next);
185 ListHead->Sequence++;
187 KeReleaseSpinLock(Lock,oldlvl);
192 #ifdef ExInterlockedPushEntrySList
193 #undef ExInterlockedPushEntrySList
199 PSINGLE_LIST_ENTRY FASTCALL
200 ExInterlockedPushEntrySList(IN PSLIST_HEADER ListHead,
201 IN PSINGLE_LIST_ENTRY ListEntry,
204 * FUNCTION: Inserts (pushes) an entry into a sequenced list
206 * ListHead = Points to the head of the list
207 * ListEntry = Points to the entry to be inserted
208 * Lock = Caller supplied spinlock used to synchronize access
209 * RETURNS: The previous head of the list
213 PSINGLE_LIST_ENTRY ret;
215 KeAcquireSpinLock(Lock,&oldlvl);
216 ret=ListHead->Next.Next;
217 PushEntryList(&ListHead->Next,ListEntry);
219 ListHead->Sequence++;
220 KeReleaseSpinLock(Lock,oldlvl);
228 PSINGLE_LIST_ENTRY FASTCALL
229 ExInterlockedPopEntryList(IN PSINGLE_LIST_ENTRY ListHead,
232 * FUNCTION: Removes (pops) an entry from a singly list
234 * ListHead = Points to the head of the list
235 * Lock = Lock for synchronizing access to the list
236 * RETURNS: The removed entry
239 PSINGLE_LIST_ENTRY ret;
242 KeAcquireSpinLock(Lock,&oldlvl);
243 ret = PopEntryList(ListHead);
244 KeReleaseSpinLock(Lock,oldlvl);
252 PSINGLE_LIST_ENTRY FASTCALL
253 ExInterlockedPushEntryList(IN PSINGLE_LIST_ENTRY ListHead,
254 IN PSINGLE_LIST_ENTRY ListEntry,
257 * FUNCTION: Inserts (pushes) an entry into a singly linked list
259 * ListHead = Points to the head of the list
260 * ListEntry = Points to the entry to be inserted
261 * Lock = Caller supplied spinlock used to synchronize access
262 * RETURNS: The previous head of the list
266 PSINGLE_LIST_ENTRY ret;
268 KeAcquireSpinLock(Lock,&oldlvl);
270 PushEntryList(ListHead,ListEntry);
271 KeReleaseSpinLock(Lock,oldlvl);
280 ExfInterlockedInsertHeadList(IN PLIST_ENTRY ListHead,
281 IN PLIST_ENTRY ListEntry,
284 * FUNCTION: Inserts an entry at the head of a doubly linked list
286 * ListHead = Points to the head of the list
287 * ListEntry = Points to the entry to be inserted
288 * Lock = Caller supplied spinlock used to synchronize access
289 * RETURNS: The previous head of the list
295 KeAcquireSpinLock(Lock,&oldlvl);
296 if (IsListEmpty(ListHead))
302 Old = ListHead->Flink;
304 InsertHeadList(ListHead,ListEntry);
305 KeReleaseSpinLock(Lock,oldlvl);
315 ExfInterlockedInsertTailList(IN PLIST_ENTRY ListHead,
316 IN PLIST_ENTRY ListEntry,
319 * FUNCTION: Inserts an entry at the tail of a doubly linked list
321 * ListHead = Points to the head of the list
322 * ListEntry = Points to the entry to be inserted
323 * Lock = Caller supplied spinlock used to synchronize access
324 * RETURNS: The previous head of the list
330 KeAcquireSpinLock(Lock,&oldlvl);
331 if (IsListEmpty(ListHead))
337 Old = ListHead->Blink;
340 if (!ListHead->Flink && !ListHead->Blink)
341 InitializeListHead(ListHead);
342 #endif /* LIBCAPTIVE */
343 InsertTailList(ListHead,ListEntry);
344 KeReleaseSpinLock(Lock,oldlvl);
353 PSINGLE_LIST_ENTRY FASTCALL
354 ExfInterlockedPopEntryList(IN PSINGLE_LIST_ENTRY ListHead,
357 * FUNCTION: Removes (pops) an entry from a singly list
359 * ListHead = Points to the head of the list
360 * Lock = Lock for synchronizing access to the list
361 * RETURNS: The removed entry
364 PSINGLE_LIST_ENTRY ret;
367 KeAcquireSpinLock(Lock,&oldlvl);
368 ret = PopEntryList(ListHead);
369 KeReleaseSpinLock(Lock,oldlvl);
377 PSINGLE_LIST_ENTRY FASTCALL
378 ExfInterlockedPushEntryList(IN PSINGLE_LIST_ENTRY ListHead,
379 IN PSINGLE_LIST_ENTRY ListEntry,
382 * FUNCTION: Inserts (pushes) an entry into a singly linked list
384 * ListHead = Points to the head of the list
385 * ListEntry = Points to the entry to be inserted
386 * Lock = Caller supplied spinlock used to synchronize access
387 * RETURNS: The previous head of the list
391 PSINGLE_LIST_ENTRY ret;
393 KeAcquireSpinLock(Lock,&oldlvl);
395 PushEntryList(ListHead,ListEntry);
396 KeReleaseSpinLock(Lock,oldlvl);
405 ExfInterlockedRemoveHeadList(IN PLIST_ENTRY Head,
408 * FUNCTION: Removes the head of a double linked list
410 * Head = Points to the head of the list
411 * Lock = Lock for synchronizing access to the list
412 * RETURNS: The removed entry
418 KeAcquireSpinLock(Lock,&oldlvl);
419 if (IsListEmpty(Head))
425 ret = RemoveHeadList(Head);
427 KeReleaseSpinLock(Lock,oldlvl);
438 InterlockedPopEntrySList(IN PSLIST_HEADER ListHead)
440 return (PSLIST_ENTRY) ExInterlockedPopEntrySList(ListHead,
450 InterlockedPushEntrySList(IN PSLIST_HEADER ListHead,
451 IN PSLIST_ENTRY ListEntry)
453 return (PSLIST_ENTRY) ExInterlockedPushEntrySList(ListHead,
458 #endif /* LIBCAPTIVE */