1 /* $Id: list.c,v 1.6 2002/09/07 15:12:50 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 *****************************************************************/
19 #include <internal/debug.h>
21 static KSPIN_LOCK ExpGlobalInterlockedLock
= 0;
23 /* FUNCTIONS *************************************************************/
26 ExInterlockedInsertHeadList(PLIST_ENTRY ListHead
,
27 PLIST_ENTRY ListEntry
,
30 * FUNCTION: Inserts an entry at the head of a doubly linked list
32 * ListHead = Points to the head of the list
33 * ListEntry = Points to the entry to be inserted
34 * Lock = Caller supplied spinlock used to synchronize access
35 * RETURNS: The previous head of the list
41 KeAcquireSpinLock(Lock
,&oldlvl
);
42 if (IsListEmpty(ListHead
))
48 Old
= ListHead
->Flink
;
50 InsertHeadList(ListHead
,ListEntry
);
51 KeReleaseSpinLock(Lock
,oldlvl
);
58 ExInterlockedInsertTailList(PLIST_ENTRY ListHead
,
59 PLIST_ENTRY ListEntry
,
62 * FUNCTION: Inserts an entry at the tail of a doubly linked list
64 * ListHead = Points to the head of the list
65 * ListEntry = Points to the entry to be inserted
66 * Lock = Caller supplied spinlock used to synchronize access
67 * RETURNS: The previous head of the list
73 KeAcquireSpinLock(Lock
,&oldlvl
);
74 if (IsListEmpty(ListHead
))
80 Old
= ListHead
->Blink
;
82 InsertTailList(ListHead
,ListEntry
);
83 KeReleaseSpinLock(Lock
,oldlvl
);
90 ExInterlockedRemoveHeadList(PLIST_ENTRY Head
,
93 * FUNCTION: Removes the head of a double linked list
95 * Head = Points to the head of the list
96 * Lock = Lock for synchronizing access to the list
97 * RETURNS: The removed entry
103 KeAcquireSpinLock(Lock
,&oldlvl
);
104 if (IsListEmpty(Head
))
110 ret
= RemoveHeadList(Head
);
112 KeReleaseSpinLock(Lock
,oldlvl
);
117 ExInterlockedRemoveTailList(PLIST_ENTRY Head
,
120 * FUNCTION: Removes the tail 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
= RemoveTailList(Head
);
139 KeReleaseSpinLock(Lock
,oldlvl
);
143 #undef ExInterlockedPopEntrySList
145 PSINGLE_LIST_ENTRY FASTCALL
146 ExInterlockedPopEntrySList(IN PSLIST_HEADER ListHead
,
149 * FUNCTION: Removes (pops) an entry from a sequenced list
151 * ListHead = Points to the head of the list
152 * Lock = Lock for synchronizing access to the list
153 * RETURNS: The removed entry
156 PSINGLE_LIST_ENTRY ret
;
159 KeAcquireSpinLock(Lock
,&oldlvl
);
160 ret
= PopEntryList(&ListHead
->Next
);
164 ListHead
->Sequence
++;
166 KeReleaseSpinLock(Lock
,oldlvl
);
170 #undef ExInterlockedPushEntrySList
172 PSINGLE_LIST_ENTRY FASTCALL
173 ExInterlockedPushEntrySList(IN PSLIST_HEADER ListHead
,
174 IN PSINGLE_LIST_ENTRY ListEntry
,
177 * FUNCTION: Inserts (pushes) an entry into a sequenced list
179 * ListHead = Points to the head of the list
180 * ListEntry = Points to the entry to be inserted
181 * Lock = Caller supplied spinlock used to synchronize access
182 * RETURNS: The previous head of the list
186 PSINGLE_LIST_ENTRY ret
;
188 KeAcquireSpinLock(Lock
,&oldlvl
);
189 ret
=ListHead
->Next
.Next
;
190 PushEntryList(&ListHead
->Next
,ListEntry
);
192 ListHead
->Sequence
++;
193 KeReleaseSpinLock(Lock
,oldlvl
);
198 PSINGLE_LIST_ENTRY FASTCALL
199 ExInterlockedPopEntryList(IN PSINGLE_LIST_ENTRY ListHead
,
202 * FUNCTION: Removes (pops) an entry from a singly list
204 * ListHead = Points to the head of the list
205 * Lock = Lock for synchronizing access to the list
206 * RETURNS: The removed entry
209 PSINGLE_LIST_ENTRY ret
;
212 KeAcquireSpinLock(Lock
,&oldlvl
);
213 ret
= PopEntryList(ListHead
);
214 KeReleaseSpinLock(Lock
,oldlvl
);
219 PSINGLE_LIST_ENTRY FASTCALL
220 ExInterlockedPushEntryList(IN PSINGLE_LIST_ENTRY ListHead
,
221 IN PSINGLE_LIST_ENTRY ListEntry
,
224 * FUNCTION: Inserts (pushes) an entry into a singly linked list
226 * ListHead = Points to the head of the list
227 * ListEntry = Points to the entry to be inserted
228 * Lock = Caller supplied spinlock used to synchronize access
229 * RETURNS: The previous head of the list
233 PSINGLE_LIST_ENTRY ret
;
235 KeAcquireSpinLock(Lock
,&oldlvl
);
237 PushEntryList(ListHead
,ListEntry
);
238 KeReleaseSpinLock(Lock
,oldlvl
);
244 ExfInterlockedInsertHeadList(IN PLIST_ENTRY ListHead
,
245 IN PLIST_ENTRY ListEntry
,
248 * FUNCTION: Inserts an entry at the head of a doubly linked list
250 * ListHead = Points to the head of the list
251 * ListEntry = Points to the entry to be inserted
252 * Lock = Caller supplied spinlock used to synchronize access
253 * RETURNS: The previous head of the list
259 KeAcquireSpinLock(Lock
,&oldlvl
);
260 if (IsListEmpty(ListHead
))
266 Old
= ListHead
->Flink
;
268 InsertHeadList(ListHead
,ListEntry
);
269 KeReleaseSpinLock(Lock
,oldlvl
);
276 ExfInterlockedInsertTailList(IN PLIST_ENTRY ListHead
,
277 IN PLIST_ENTRY ListEntry
,
280 * FUNCTION: Inserts an entry at the tail of a doubly linked list
282 * ListHead = Points to the head of the list
283 * ListEntry = Points to the entry to be inserted
284 * Lock = Caller supplied spinlock used to synchronize access
285 * RETURNS: The previous head of the list
291 KeAcquireSpinLock(Lock
,&oldlvl
);
292 if (IsListEmpty(ListHead
))
298 Old
= ListHead
->Blink
;
300 InsertTailList(ListHead
,ListEntry
);
301 KeReleaseSpinLock(Lock
,oldlvl
);
307 PSINGLE_LIST_ENTRY FASTCALL
308 ExfInterlockedPopEntryList(IN PSINGLE_LIST_ENTRY ListHead
,
311 * FUNCTION: Removes (pops) an entry from a singly list
313 * ListHead = Points to the head of the list
314 * Lock = Lock for synchronizing access to the list
315 * RETURNS: The removed entry
318 PSINGLE_LIST_ENTRY ret
;
321 KeAcquireSpinLock(Lock
,&oldlvl
);
322 ret
= PopEntryList(ListHead
);
323 KeReleaseSpinLock(Lock
,oldlvl
);
328 PSINGLE_LIST_ENTRY FASTCALL
329 ExfInterlockedPushEntryList(IN PSINGLE_LIST_ENTRY ListHead
,
330 IN PSINGLE_LIST_ENTRY ListEntry
,
333 * FUNCTION: Inserts (pushes) an entry into a singly linked list
335 * ListHead = Points to the head of the list
336 * ListEntry = Points to the entry to be inserted
337 * Lock = Caller supplied spinlock used to synchronize access
338 * RETURNS: The previous head of the list
342 PSINGLE_LIST_ENTRY ret
;
344 KeAcquireSpinLock(Lock
,&oldlvl
);
346 PushEntryList(ListHead
,ListEntry
);
347 KeReleaseSpinLock(Lock
,oldlvl
);
353 ExfInterlockedRemoveHeadList(IN PLIST_ENTRY Head
,
356 * FUNCTION: Removes the head of a double linked list
358 * Head = Points to the head of the list
359 * Lock = Lock for synchronizing access to the list
360 * RETURNS: The removed entry
366 KeAcquireSpinLock(Lock
,&oldlvl
);
367 if (IsListEmpty(Head
))
373 ret
= RemoveHeadList(Head
);
375 KeReleaseSpinLock(Lock
,oldlvl
);
382 InterlockedPopEntrySList(
383 IN PSLIST_HEADER ListHead
)
388 KeAcquireSpinLock(&ExpGlobalInterlockedLock
, &OldIrql
);
389 Value
= PopEntryList(&ListHead
->Next
);
393 ListHead
->Sequence
++;
395 KeReleaseSpinLock(&ExpGlobalInterlockedLock
, OldIrql
);
402 InterlockedPushEntrySList(
403 IN PSLIST_HEADER ListHead
,
404 IN PSLIST_ENTRY ListEntry
)
409 KeAcquireSpinLock(&ExpGlobalInterlockedLock
, &OldIrql
);
410 Value
= ListHead
->Next
.Next
;
411 PushEntryList(&ListHead
->Next
, ListEntry
);
413 ListHead
->Sequence
++;
414 KeReleaseSpinLock(&ExpGlobalInterlockedLock
, OldIrql
);