1 /* $Id: list.c,v 1.14 2004/10/12 00:56:46 ion 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
35 Old
= &ListHead
->Next
;
36 ListHead
->Next
.Next
= 0;
45 ExInterlockedInsertHeadList(PLIST_ENTRY ListHead
,
46 PLIST_ENTRY ListEntry
,
49 * FUNCTION: Inserts an entry at the head of a doubly linked list
51 * ListHead = Points to the head of the list
52 * ListEntry = Points to the entry to be inserted
53 * Lock = Caller supplied spinlock used to synchronize access
54 * RETURNS: The previous head of the list
60 KeAcquireSpinLock(Lock
,&oldlvl
);
61 if (IsListEmpty(ListHead
))
67 Old
= ListHead
->Flink
;
69 InsertHeadList(ListHead
,ListEntry
);
70 KeReleaseSpinLock(Lock
,oldlvl
);
80 ExInterlockedInsertTailList(PLIST_ENTRY ListHead
,
81 PLIST_ENTRY ListEntry
,
84 * FUNCTION: Inserts an entry at the tail of a doubly linked list
86 * ListHead = Points to the head of the list
87 * ListEntry = Points to the entry to be inserted
88 * Lock = Caller supplied spinlock used to synchronize access
89 * RETURNS: The previous head of the list
95 KeAcquireSpinLock(Lock
,&oldlvl
);
96 if (IsListEmpty(ListHead
))
102 Old
= ListHead
->Blink
;
104 InsertTailList(ListHead
,ListEntry
);
105 KeReleaseSpinLock(Lock
,oldlvl
);
115 ExInterlockedRemoveHeadList(PLIST_ENTRY Head
,
118 * FUNCTION: Removes the head of a double linked list
120 * Head = Points to the head of the list
121 * Lock = Lock for synchronizing access to the list
122 * RETURNS: The removed entry
128 KeAcquireSpinLock(Lock
,&oldlvl
);
129 if (IsListEmpty(Head
))
135 ret
= RemoveHeadList(Head
);
137 KeReleaseSpinLock(Lock
,oldlvl
);
143 ExInterlockedRemoveTailList(PLIST_ENTRY Head
,
146 * FUNCTION: Removes the tail of a double linked list
148 * Head = Points to the head of the list
149 * Lock = Lock for synchronizing access to the list
150 * RETURNS: The removed entry
156 KeAcquireSpinLock(Lock
,&oldlvl
);
157 if (IsListEmpty(Head
))
163 ret
= RemoveTailList(Head
);
165 KeReleaseSpinLock(Lock
,oldlvl
);
170 #ifdef ExInterlockedPopEntrySList
171 #undef ExInterlockedPopEntrySList
177 PSINGLE_LIST_ENTRY FASTCALL
178 ExInterlockedPopEntrySList(IN PSLIST_HEADER ListHead
,
181 * FUNCTION: Removes (pops) an entry from a sequenced list
183 * ListHead = Points to the head of the list
184 * Lock = Lock for synchronizing access to the list
185 * RETURNS: The removed entry
188 PSINGLE_LIST_ENTRY ret
;
191 KeAcquireSpinLock(Lock
,&oldlvl
);
192 ret
= PopEntryList(&ListHead
->Next
);
196 ListHead
->Sequence
++;
198 KeReleaseSpinLock(Lock
,oldlvl
);
203 #ifdef ExInterlockedPushEntrySList
204 #undef ExInterlockedPushEntrySList
210 PSINGLE_LIST_ENTRY FASTCALL
211 ExInterlockedPushEntrySList(IN PSLIST_HEADER ListHead
,
212 IN PSINGLE_LIST_ENTRY ListEntry
,
215 * FUNCTION: Inserts (pushes) an entry into a sequenced list
217 * ListHead = Points to the head of the list
218 * ListEntry = Points to the entry to be inserted
219 * Lock = Caller supplied spinlock used to synchronize access
220 * RETURNS: The previous head of the list
224 PSINGLE_LIST_ENTRY ret
;
226 KeAcquireSpinLock(Lock
,&oldlvl
);
227 ret
=ListHead
->Next
.Next
;
228 PushEntryList(&ListHead
->Next
,ListEntry
);
230 ListHead
->Sequence
++;
231 KeReleaseSpinLock(Lock
,oldlvl
);
239 PSINGLE_LIST_ENTRY FASTCALL
240 ExInterlockedPopEntryList(IN PSINGLE_LIST_ENTRY ListHead
,
243 * FUNCTION: Removes (pops) an entry from a singly list
245 * ListHead = Points to the head of the list
246 * Lock = Lock for synchronizing access to the list
247 * RETURNS: The removed entry
250 PSINGLE_LIST_ENTRY ret
;
253 KeAcquireSpinLock(Lock
,&oldlvl
);
254 ret
= PopEntryList(ListHead
);
255 KeReleaseSpinLock(Lock
,oldlvl
);
263 PSINGLE_LIST_ENTRY FASTCALL
264 ExInterlockedPushEntryList(IN PSINGLE_LIST_ENTRY ListHead
,
265 IN PSINGLE_LIST_ENTRY ListEntry
,
268 * FUNCTION: Inserts (pushes) an entry into a singly linked list
270 * ListHead = Points to the head of the list
271 * ListEntry = Points to the entry to be inserted
272 * Lock = Caller supplied spinlock used to synchronize access
273 * RETURNS: The previous head of the list
277 PSINGLE_LIST_ENTRY ret
;
279 KeAcquireSpinLock(Lock
,&oldlvl
);
281 PushEntryList(ListHead
,ListEntry
);
282 KeReleaseSpinLock(Lock
,oldlvl
);
291 ExfInterlockedInsertHeadList(IN PLIST_ENTRY ListHead
,
292 IN PLIST_ENTRY ListEntry
,
295 * FUNCTION: Inserts an entry at the head of a doubly linked list
297 * ListHead = Points to the head of the list
298 * ListEntry = Points to the entry to be inserted
299 * Lock = Caller supplied spinlock used to synchronize access
300 * RETURNS: The previous head of the list
306 KeAcquireSpinLock(Lock
,&oldlvl
);
307 if (IsListEmpty(ListHead
))
313 Old
= ListHead
->Flink
;
315 InsertHeadList(ListHead
,ListEntry
);
316 KeReleaseSpinLock(Lock
,oldlvl
);
326 ExfInterlockedInsertTailList(IN PLIST_ENTRY ListHead
,
327 IN PLIST_ENTRY ListEntry
,
330 * FUNCTION: Inserts an entry at the tail of a doubly linked list
332 * ListHead = Points to the head of the list
333 * ListEntry = Points to the entry to be inserted
334 * Lock = Caller supplied spinlock used to synchronize access
335 * RETURNS: The previous head of the list
341 KeAcquireSpinLock(Lock
,&oldlvl
);
342 if (IsListEmpty(ListHead
))
348 Old
= ListHead
->Blink
;
350 InsertTailList(ListHead
,ListEntry
);
351 KeReleaseSpinLock(Lock
,oldlvl
);
360 PSINGLE_LIST_ENTRY FASTCALL
361 ExfInterlockedPopEntryList(IN PSINGLE_LIST_ENTRY ListHead
,
364 * FUNCTION: Removes (pops) an entry from a singly list
366 * ListHead = Points to the head of the list
367 * Lock = Lock for synchronizing access to the list
368 * RETURNS: The removed entry
371 PSINGLE_LIST_ENTRY ret
;
374 KeAcquireSpinLock(Lock
,&oldlvl
);
375 ret
= PopEntryList(ListHead
);
376 KeReleaseSpinLock(Lock
,oldlvl
);
384 PSINGLE_LIST_ENTRY FASTCALL
385 ExfInterlockedPushEntryList(IN PSINGLE_LIST_ENTRY ListHead
,
386 IN PSINGLE_LIST_ENTRY ListEntry
,
389 * FUNCTION: Inserts (pushes) an entry into a singly linked list
391 * ListHead = Points to the head of the list
392 * ListEntry = Points to the entry to be inserted
393 * Lock = Caller supplied spinlock used to synchronize access
394 * RETURNS: The previous head of the list
398 PSINGLE_LIST_ENTRY ret
;
400 KeAcquireSpinLock(Lock
,&oldlvl
);
402 PushEntryList(ListHead
,ListEntry
);
403 KeReleaseSpinLock(Lock
,oldlvl
);
412 ExfInterlockedRemoveHeadList(IN PLIST_ENTRY Head
,
415 * FUNCTION: Removes the head of a double linked list
417 * Head = Points to the head of the list
418 * Lock = Lock for synchronizing access to the list
419 * RETURNS: The removed entry
425 KeAcquireSpinLock(Lock
,&oldlvl
);
426 if (IsListEmpty(Head
))
432 ret
= RemoveHeadList(Head
);
434 KeReleaseSpinLock(Lock
,oldlvl
);
444 InterlockedPopEntrySList(IN PSLIST_HEADER ListHead
)
446 return (PSLIST_ENTRY
) ExInterlockedPopEntrySList(ListHead
,
456 InterlockedPushEntrySList(IN PSLIST_HEADER ListHead
,
457 IN PSLIST_ENTRY ListEntry
)
459 return (PSLIST_ENTRY
) ExInterlockedPushEntrySList(ListHead
,