1 /* $Id: list.c,v 1.12 2004/06/23 21:01:27 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 *****************************************************************/
17 //#define NONAMELESSUNION
19 #include <ddk/ntddk.h>
22 #include <internal/debug.h>
24 static KSPIN_LOCK ExpGlobalListLock
= { 0, };
26 /* FUNCTIONS *************************************************************/
33 ExInterlockedFlushSList (
34 IN PSLIST_HEADER ListHead
37 PSLIST_ENTRY Old
= NULL
;
47 ExInterlockedInsertHeadList(PLIST_ENTRY ListHead
,
48 PLIST_ENTRY ListEntry
,
51 * FUNCTION: Inserts an entry at the head of a doubly linked list
53 * ListHead = Points to the head of the list
54 * ListEntry = Points to the entry to be inserted
55 * Lock = Caller supplied spinlock used to synchronize access
56 * RETURNS: The previous head of the list
62 KeAcquireSpinLock(Lock
,&oldlvl
);
63 if (IsListEmpty(ListHead
))
69 Old
= ListHead
->Flink
;
71 InsertHeadList(ListHead
,ListEntry
);
72 KeReleaseSpinLock(Lock
,oldlvl
);
82 ExInterlockedInsertTailList(PLIST_ENTRY ListHead
,
83 PLIST_ENTRY ListEntry
,
86 * FUNCTION: Inserts an entry at the tail of a doubly linked list
88 * ListHead = Points to the head of the list
89 * ListEntry = Points to the entry to be inserted
90 * Lock = Caller supplied spinlock used to synchronize access
91 * RETURNS: The previous head of the list
97 KeAcquireSpinLock(Lock
,&oldlvl
);
98 if (IsListEmpty(ListHead
))
104 Old
= ListHead
->Blink
;
106 InsertTailList(ListHead
,ListEntry
);
107 KeReleaseSpinLock(Lock
,oldlvl
);
117 ExInterlockedRemoveHeadList(PLIST_ENTRY Head
,
120 * FUNCTION: Removes the head of a double linked list
122 * Head = Points to the head of the list
123 * Lock = Lock for synchronizing access to the list
124 * RETURNS: The removed entry
130 KeAcquireSpinLock(Lock
,&oldlvl
);
131 if (IsListEmpty(Head
))
137 ret
= RemoveHeadList(Head
);
139 KeReleaseSpinLock(Lock
,oldlvl
);
145 ExInterlockedRemoveTailList(PLIST_ENTRY Head
,
148 * FUNCTION: Removes the tail of a double linked list
150 * Head = Points to the head of the list
151 * Lock = Lock for synchronizing access to the list
152 * RETURNS: The removed entry
158 KeAcquireSpinLock(Lock
,&oldlvl
);
159 if (IsListEmpty(Head
))
165 ret
= RemoveTailList(Head
);
167 KeReleaseSpinLock(Lock
,oldlvl
);
172 #ifdef ExInterlockedPopEntrySList
173 #undef ExInterlockedPopEntrySList
179 PSINGLE_LIST_ENTRY FASTCALL
180 ExInterlockedPopEntrySList(IN PSLIST_HEADER ListHead
,
183 * FUNCTION: Removes (pops) an entry from a sequenced list
185 * ListHead = Points to the head of the list
186 * Lock = Lock for synchronizing access to the list
187 * RETURNS: The removed entry
190 PSINGLE_LIST_ENTRY ret
;
193 KeAcquireSpinLock(Lock
,&oldlvl
);
194 ret
= PopEntryList(&ListHead
->Next
);
198 ListHead
->Sequence
++;
200 KeReleaseSpinLock(Lock
,oldlvl
);
205 #ifdef ExInterlockedPushEntrySList
206 #undef ExInterlockedPushEntrySList
212 PSINGLE_LIST_ENTRY FASTCALL
213 ExInterlockedPushEntrySList(IN PSLIST_HEADER ListHead
,
214 IN PSINGLE_LIST_ENTRY ListEntry
,
217 * FUNCTION: Inserts (pushes) an entry into a sequenced list
219 * ListHead = Points to the head of the list
220 * ListEntry = Points to the entry to be inserted
221 * Lock = Caller supplied spinlock used to synchronize access
222 * RETURNS: The previous head of the list
226 PSINGLE_LIST_ENTRY ret
;
228 KeAcquireSpinLock(Lock
,&oldlvl
);
229 ret
=ListHead
->Next
.Next
;
230 PushEntryList(&ListHead
->Next
,ListEntry
);
232 ListHead
->Sequence
++;
233 KeReleaseSpinLock(Lock
,oldlvl
);
241 PSINGLE_LIST_ENTRY FASTCALL
242 ExInterlockedPopEntryList(IN PSINGLE_LIST_ENTRY ListHead
,
245 * FUNCTION: Removes (pops) an entry from a singly list
247 * ListHead = Points to the head of the list
248 * Lock = Lock for synchronizing access to the list
249 * RETURNS: The removed entry
252 PSINGLE_LIST_ENTRY ret
;
255 KeAcquireSpinLock(Lock
,&oldlvl
);
256 ret
= PopEntryList(ListHead
);
257 KeReleaseSpinLock(Lock
,oldlvl
);
265 PSINGLE_LIST_ENTRY FASTCALL
266 ExInterlockedPushEntryList(IN PSINGLE_LIST_ENTRY ListHead
,
267 IN PSINGLE_LIST_ENTRY ListEntry
,
270 * FUNCTION: Inserts (pushes) an entry into a singly linked list
272 * ListHead = Points to the head of the list
273 * ListEntry = Points to the entry to be inserted
274 * Lock = Caller supplied spinlock used to synchronize access
275 * RETURNS: The previous head of the list
279 PSINGLE_LIST_ENTRY ret
;
281 KeAcquireSpinLock(Lock
,&oldlvl
);
283 PushEntryList(ListHead
,ListEntry
);
284 KeReleaseSpinLock(Lock
,oldlvl
);
293 ExfInterlockedInsertHeadList(IN PLIST_ENTRY ListHead
,
294 IN PLIST_ENTRY ListEntry
,
297 * FUNCTION: Inserts an entry at the head of a doubly linked list
299 * ListHead = Points to the head of the list
300 * ListEntry = Points to the entry to be inserted
301 * Lock = Caller supplied spinlock used to synchronize access
302 * RETURNS: The previous head of the list
308 KeAcquireSpinLock(Lock
,&oldlvl
);
309 if (IsListEmpty(ListHead
))
315 Old
= ListHead
->Flink
;
317 InsertHeadList(ListHead
,ListEntry
);
318 KeReleaseSpinLock(Lock
,oldlvl
);
328 ExfInterlockedInsertTailList(IN PLIST_ENTRY ListHead
,
329 IN PLIST_ENTRY ListEntry
,
332 * FUNCTION: Inserts an entry at the tail of a doubly linked list
334 * ListHead = Points to the head of the list
335 * ListEntry = Points to the entry to be inserted
336 * Lock = Caller supplied spinlock used to synchronize access
337 * RETURNS: The previous head of the list
343 KeAcquireSpinLock(Lock
,&oldlvl
);
344 if (IsListEmpty(ListHead
))
350 Old
= ListHead
->Blink
;
352 InsertTailList(ListHead
,ListEntry
);
353 KeReleaseSpinLock(Lock
,oldlvl
);
362 PSINGLE_LIST_ENTRY FASTCALL
363 ExfInterlockedPopEntryList(IN PSINGLE_LIST_ENTRY ListHead
,
366 * FUNCTION: Removes (pops) an entry from a singly list
368 * ListHead = Points to the head of the list
369 * Lock = Lock for synchronizing access to the list
370 * RETURNS: The removed entry
373 PSINGLE_LIST_ENTRY ret
;
376 KeAcquireSpinLock(Lock
,&oldlvl
);
377 ret
= PopEntryList(ListHead
);
378 KeReleaseSpinLock(Lock
,oldlvl
);
386 PSINGLE_LIST_ENTRY FASTCALL
387 ExfInterlockedPushEntryList(IN PSINGLE_LIST_ENTRY ListHead
,
388 IN PSINGLE_LIST_ENTRY ListEntry
,
391 * FUNCTION: Inserts (pushes) an entry into a singly linked list
393 * ListHead = Points to the head of the list
394 * ListEntry = Points to the entry to be inserted
395 * Lock = Caller supplied spinlock used to synchronize access
396 * RETURNS: The previous head of the list
400 PSINGLE_LIST_ENTRY ret
;
402 KeAcquireSpinLock(Lock
,&oldlvl
);
404 PushEntryList(ListHead
,ListEntry
);
405 KeReleaseSpinLock(Lock
,oldlvl
);
414 ExfInterlockedRemoveHeadList(IN PLIST_ENTRY Head
,
417 * FUNCTION: Removes the head of a double linked list
419 * Head = Points to the head of the list
420 * Lock = Lock for synchronizing access to the list
421 * RETURNS: The removed entry
427 KeAcquireSpinLock(Lock
,&oldlvl
);
428 if (IsListEmpty(Head
))
434 ret
= RemoveHeadList(Head
);
436 KeReleaseSpinLock(Lock
,oldlvl
);
446 InterlockedPopEntrySList(IN PSLIST_HEADER ListHead
)
448 return (PSLIST_ENTRY
) ExInterlockedPopEntrySList(ListHead
,
458 InterlockedPushEntrySList(IN PSLIST_HEADER ListHead
,
459 IN PSLIST_ENTRY ListEntry
)
461 return (PSLIST_ENTRY
) ExInterlockedPushEntrySList(ListHead
,