1 /* $Id: list.c,v 1.13 2004/08/15 16:39:01 chorns Exp $
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 *****************************************************************/
18 #include <internal/debug.h>
20 static KSPIN_LOCK ExpGlobalListLock
= { 0, };
22 /* FUNCTIONS *************************************************************/
29 ExInterlockedFlushSList (
30 IN PSLIST_HEADER ListHead
33 PSLIST_ENTRY Old
= NULL
;
43 ExInterlockedInsertHeadList(PLIST_ENTRY ListHead
,
44 PLIST_ENTRY ListEntry
,
47 * FUNCTION: Inserts an entry at the head of a doubly linked list
49 * ListHead = Points to the head of the list
50 * ListEntry = Points to the entry to be inserted
51 * Lock = Caller supplied spinlock used to synchronize access
52 * RETURNS: The previous head of the list
58 KeAcquireSpinLock(Lock
,&oldlvl
);
59 if (IsListEmpty(ListHead
))
65 Old
= ListHead
->Flink
;
67 InsertHeadList(ListHead
,ListEntry
);
68 KeReleaseSpinLock(Lock
,oldlvl
);
78 ExInterlockedInsertTailList(PLIST_ENTRY ListHead
,
79 PLIST_ENTRY ListEntry
,
82 * FUNCTION: Inserts an entry at the tail of a doubly linked list
84 * ListHead = Points to the head of the list
85 * ListEntry = Points to the entry to be inserted
86 * Lock = Caller supplied spinlock used to synchronize access
87 * RETURNS: The previous head of the list
93 KeAcquireSpinLock(Lock
,&oldlvl
);
94 if (IsListEmpty(ListHead
))
100 Old
= ListHead
->Blink
;
102 InsertTailList(ListHead
,ListEntry
);
103 KeReleaseSpinLock(Lock
,oldlvl
);
113 ExInterlockedRemoveHeadList(PLIST_ENTRY Head
,
116 * FUNCTION: Removes the head of a double linked list
118 * Head = Points to the head of the list
119 * Lock = Lock for synchronizing access to the list
120 * RETURNS: The removed entry
126 KeAcquireSpinLock(Lock
,&oldlvl
);
127 if (IsListEmpty(Head
))
133 ret
= RemoveHeadList(Head
);
135 KeReleaseSpinLock(Lock
,oldlvl
);
141 ExInterlockedRemoveTailList(PLIST_ENTRY Head
,
144 * FUNCTION: Removes the tail of a double linked list
146 * Head = Points to the head of the list
147 * Lock = Lock for synchronizing access to the list
148 * RETURNS: The removed entry
154 KeAcquireSpinLock(Lock
,&oldlvl
);
155 if (IsListEmpty(Head
))
161 ret
= RemoveTailList(Head
);
163 KeReleaseSpinLock(Lock
,oldlvl
);
168 #ifdef ExInterlockedPopEntrySList
169 #undef ExInterlockedPopEntrySList
175 PSINGLE_LIST_ENTRY FASTCALL
176 ExInterlockedPopEntrySList(IN PSLIST_HEADER ListHead
,
179 * FUNCTION: Removes (pops) an entry from a sequenced list
181 * ListHead = Points to the head of the list
182 * Lock = Lock for synchronizing access to the list
183 * RETURNS: The removed entry
186 PSINGLE_LIST_ENTRY ret
;
189 KeAcquireSpinLock(Lock
,&oldlvl
);
190 ret
= PopEntryList(&ListHead
->Next
);
194 ListHead
->Sequence
++;
196 KeReleaseSpinLock(Lock
,oldlvl
);
201 #ifdef ExInterlockedPushEntrySList
202 #undef ExInterlockedPushEntrySList
208 PSINGLE_LIST_ENTRY FASTCALL
209 ExInterlockedPushEntrySList(IN PSLIST_HEADER ListHead
,
210 IN PSINGLE_LIST_ENTRY ListEntry
,
213 * FUNCTION: Inserts (pushes) an entry into a sequenced list
215 * ListHead = Points to the head of the list
216 * ListEntry = Points to the entry to be inserted
217 * Lock = Caller supplied spinlock used to synchronize access
218 * RETURNS: The previous head of the list
222 PSINGLE_LIST_ENTRY ret
;
224 KeAcquireSpinLock(Lock
,&oldlvl
);
225 ret
=ListHead
->Next
.Next
;
226 PushEntryList(&ListHead
->Next
,ListEntry
);
228 ListHead
->Sequence
++;
229 KeReleaseSpinLock(Lock
,oldlvl
);
237 PSINGLE_LIST_ENTRY FASTCALL
238 ExInterlockedPopEntryList(IN PSINGLE_LIST_ENTRY ListHead
,
241 * FUNCTION: Removes (pops) an entry from a singly list
243 * ListHead = Points to the head of the list
244 * Lock = Lock for synchronizing access to the list
245 * RETURNS: The removed entry
248 PSINGLE_LIST_ENTRY ret
;
251 KeAcquireSpinLock(Lock
,&oldlvl
);
252 ret
= PopEntryList(ListHead
);
253 KeReleaseSpinLock(Lock
,oldlvl
);
261 PSINGLE_LIST_ENTRY FASTCALL
262 ExInterlockedPushEntryList(IN PSINGLE_LIST_ENTRY ListHead
,
263 IN PSINGLE_LIST_ENTRY ListEntry
,
266 * FUNCTION: Inserts (pushes) an entry into a singly linked list
268 * ListHead = Points to the head of the list
269 * ListEntry = Points to the entry to be inserted
270 * Lock = Caller supplied spinlock used to synchronize access
271 * RETURNS: The previous head of the list
275 PSINGLE_LIST_ENTRY ret
;
277 KeAcquireSpinLock(Lock
,&oldlvl
);
279 PushEntryList(ListHead
,ListEntry
);
280 KeReleaseSpinLock(Lock
,oldlvl
);
289 ExfInterlockedInsertHeadList(IN PLIST_ENTRY ListHead
,
290 IN PLIST_ENTRY ListEntry
,
293 * FUNCTION: Inserts an entry at the head of a doubly linked list
295 * ListHead = Points to the head of the list
296 * ListEntry = Points to the entry to be inserted
297 * Lock = Caller supplied spinlock used to synchronize access
298 * RETURNS: The previous head of the list
304 KeAcquireSpinLock(Lock
,&oldlvl
);
305 if (IsListEmpty(ListHead
))
311 Old
= ListHead
->Flink
;
313 InsertHeadList(ListHead
,ListEntry
);
314 KeReleaseSpinLock(Lock
,oldlvl
);
324 ExfInterlockedInsertTailList(IN PLIST_ENTRY ListHead
,
325 IN PLIST_ENTRY ListEntry
,
328 * FUNCTION: Inserts an entry at the tail of a doubly linked list
330 * ListHead = Points to the head of the list
331 * ListEntry = Points to the entry to be inserted
332 * Lock = Caller supplied spinlock used to synchronize access
333 * RETURNS: The previous head of the list
339 KeAcquireSpinLock(Lock
,&oldlvl
);
340 if (IsListEmpty(ListHead
))
346 Old
= ListHead
->Blink
;
348 InsertTailList(ListHead
,ListEntry
);
349 KeReleaseSpinLock(Lock
,oldlvl
);
358 PSINGLE_LIST_ENTRY FASTCALL
359 ExfInterlockedPopEntryList(IN PSINGLE_LIST_ENTRY ListHead
,
362 * FUNCTION: Removes (pops) an entry from a singly list
364 * ListHead = Points to the head of the list
365 * Lock = Lock for synchronizing access to the list
366 * RETURNS: The removed entry
369 PSINGLE_LIST_ENTRY ret
;
372 KeAcquireSpinLock(Lock
,&oldlvl
);
373 ret
= PopEntryList(ListHead
);
374 KeReleaseSpinLock(Lock
,oldlvl
);
382 PSINGLE_LIST_ENTRY FASTCALL
383 ExfInterlockedPushEntryList(IN PSINGLE_LIST_ENTRY ListHead
,
384 IN PSINGLE_LIST_ENTRY ListEntry
,
387 * FUNCTION: Inserts (pushes) an entry into a singly linked list
389 * ListHead = Points to the head of the list
390 * ListEntry = Points to the entry to be inserted
391 * Lock = Caller supplied spinlock used to synchronize access
392 * RETURNS: The previous head of the list
396 PSINGLE_LIST_ENTRY ret
;
398 KeAcquireSpinLock(Lock
,&oldlvl
);
400 PushEntryList(ListHead
,ListEntry
);
401 KeReleaseSpinLock(Lock
,oldlvl
);
410 ExfInterlockedRemoveHeadList(IN PLIST_ENTRY Head
,
413 * FUNCTION: Removes the head of a double linked list
415 * Head = Points to the head of the list
416 * Lock = Lock for synchronizing access to the list
417 * RETURNS: The removed entry
423 KeAcquireSpinLock(Lock
,&oldlvl
);
424 if (IsListEmpty(Head
))
430 ret
= RemoveHeadList(Head
);
432 KeReleaseSpinLock(Lock
,oldlvl
);
442 InterlockedPopEntrySList(IN PSLIST_HEADER ListHead
)
444 return (PSLIST_ENTRY
) ExInterlockedPopEntrySList(ListHead
,
454 InterlockedPushEntrySList(IN PSLIST_HEADER ListHead
,
455 IN PSLIST_ENTRY ListEntry
)
457 return (PSLIST_ENTRY
) ExInterlockedPushEntrySList(ListHead
,