1 /* $Id: list.c,v 1.10 2003/07/12 10:24:45 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 *****************************************************************/
17 #define NONAMELESSUNION
19 #include <ddk/ntddk.h>
22 #include <internal/debug.h>
24 static KSPIN_LOCK ExpGlobalListLock
= { 0, };
26 /* FUNCTIONS *************************************************************/
32 ExInterlockedInsertHeadList(PLIST_ENTRY ListHead
,
33 PLIST_ENTRY ListEntry
,
36 * FUNCTION: Inserts an entry at the head of a doubly linked list
38 * ListHead = Points to the head of the list
39 * ListEntry = Points to the entry to be inserted
40 * Lock = Caller supplied spinlock used to synchronize access
41 * RETURNS: The previous head of the list
47 KeAcquireSpinLock(Lock
,&oldlvl
);
48 if (IsListEmpty(ListHead
))
54 Old
= ListHead
->Flink
;
56 InsertHeadList(ListHead
,ListEntry
);
57 KeReleaseSpinLock(Lock
,oldlvl
);
67 ExInterlockedInsertTailList(PLIST_ENTRY ListHead
,
68 PLIST_ENTRY ListEntry
,
71 * FUNCTION: Inserts an entry at the tail of a doubly linked list
73 * ListHead = Points to the head of the list
74 * ListEntry = Points to the entry to be inserted
75 * Lock = Caller supplied spinlock used to synchronize access
76 * RETURNS: The previous head of the list
82 KeAcquireSpinLock(Lock
,&oldlvl
);
83 if (IsListEmpty(ListHead
))
89 Old
= ListHead
->Blink
;
91 InsertTailList(ListHead
,ListEntry
);
92 KeReleaseSpinLock(Lock
,oldlvl
);
102 ExInterlockedRemoveHeadList(PLIST_ENTRY Head
,
105 * FUNCTION: Removes the head of a double linked list
107 * Head = Points to the head of the list
108 * Lock = Lock for synchronizing access to the list
109 * RETURNS: The removed entry
115 KeAcquireSpinLock(Lock
,&oldlvl
);
116 if (IsListEmpty(Head
))
122 ret
= RemoveHeadList(Head
);
124 KeReleaseSpinLock(Lock
,oldlvl
);
130 ExInterlockedRemoveTailList(PLIST_ENTRY Head
,
133 * FUNCTION: Removes the tail of a double linked list
135 * Head = Points to the head of the list
136 * Lock = Lock for synchronizing access to the list
137 * RETURNS: The removed entry
143 KeAcquireSpinLock(Lock
,&oldlvl
);
144 if (IsListEmpty(Head
))
150 ret
= RemoveTailList(Head
);
152 KeReleaseSpinLock(Lock
,oldlvl
);
157 #ifdef ExInterlockedPopEntrySList
158 #undef ExInterlockedPopEntrySList
164 PSINGLE_LIST_ENTRY FASTCALL
165 ExInterlockedPopEntrySList(IN PSLIST_HEADER ListHead
,
168 * FUNCTION: Removes (pops) an entry from a sequenced list
170 * ListHead = Points to the head of the list
171 * Lock = Lock for synchronizing access to the list
172 * RETURNS: The removed entry
175 PSINGLE_LIST_ENTRY ret
;
178 KeAcquireSpinLock(Lock
,&oldlvl
);
179 ret
= PopEntryList(&ListHead
->s
.Next
);
183 ListHead
->s
.Sequence
++;
185 KeReleaseSpinLock(Lock
,oldlvl
);
190 #ifdef ExInterlockedPushEntrySList
191 #undef ExInterlockedPushEntrySList
197 PSINGLE_LIST_ENTRY FASTCALL
198 ExInterlockedPushEntrySList(IN PSLIST_HEADER ListHead
,
199 IN PSINGLE_LIST_ENTRY ListEntry
,
202 * FUNCTION: Inserts (pushes) an entry into a sequenced list
204 * ListHead = Points to the head of the list
205 * ListEntry = Points to the entry to be inserted
206 * Lock = Caller supplied spinlock used to synchronize access
207 * RETURNS: The previous head of the list
211 PSINGLE_LIST_ENTRY ret
;
213 KeAcquireSpinLock(Lock
,&oldlvl
);
214 ret
=ListHead
->s
.Next
.Next
;
215 PushEntryList(&ListHead
->s
.Next
,ListEntry
);
217 ListHead
->s
.Sequence
++;
218 KeReleaseSpinLock(Lock
,oldlvl
);
226 PSINGLE_LIST_ENTRY FASTCALL
227 ExInterlockedPopEntryList(IN PSINGLE_LIST_ENTRY ListHead
,
230 * FUNCTION: Removes (pops) an entry from a singly list
232 * ListHead = Points to the head of the list
233 * Lock = Lock for synchronizing access to the list
234 * RETURNS: The removed entry
237 PSINGLE_LIST_ENTRY ret
;
240 KeAcquireSpinLock(Lock
,&oldlvl
);
241 ret
= PopEntryList(ListHead
);
242 KeReleaseSpinLock(Lock
,oldlvl
);
250 PSINGLE_LIST_ENTRY FASTCALL
251 ExInterlockedPushEntryList(IN PSINGLE_LIST_ENTRY ListHead
,
252 IN PSINGLE_LIST_ENTRY ListEntry
,
255 * FUNCTION: Inserts (pushes) an entry into a singly linked list
257 * ListHead = Points to the head of the list
258 * ListEntry = Points to the entry to be inserted
259 * Lock = Caller supplied spinlock used to synchronize access
260 * RETURNS: The previous head of the list
264 PSINGLE_LIST_ENTRY ret
;
266 KeAcquireSpinLock(Lock
,&oldlvl
);
268 PushEntryList(ListHead
,ListEntry
);
269 KeReleaseSpinLock(Lock
,oldlvl
);
278 ExfInterlockedInsertHeadList(IN PLIST_ENTRY ListHead
,
279 IN PLIST_ENTRY ListEntry
,
282 * FUNCTION: Inserts an entry at the head of a doubly linked list
284 * ListHead = Points to the head of the list
285 * ListEntry = Points to the entry to be inserted
286 * Lock = Caller supplied spinlock used to synchronize access
287 * RETURNS: The previous head of the list
293 KeAcquireSpinLock(Lock
,&oldlvl
);
294 if (IsListEmpty(ListHead
))
300 Old
= ListHead
->Flink
;
302 InsertHeadList(ListHead
,ListEntry
);
303 KeReleaseSpinLock(Lock
,oldlvl
);
313 ExfInterlockedInsertTailList(IN PLIST_ENTRY ListHead
,
314 IN PLIST_ENTRY ListEntry
,
317 * FUNCTION: Inserts an entry at the tail of a doubly linked list
319 * ListHead = Points to the head of the list
320 * ListEntry = Points to the entry to be inserted
321 * Lock = Caller supplied spinlock used to synchronize access
322 * RETURNS: The previous head of the list
328 KeAcquireSpinLock(Lock
,&oldlvl
);
329 if (IsListEmpty(ListHead
))
335 Old
= ListHead
->Blink
;
337 InsertTailList(ListHead
,ListEntry
);
338 KeReleaseSpinLock(Lock
,oldlvl
);
347 PSINGLE_LIST_ENTRY FASTCALL
348 ExfInterlockedPopEntryList(IN PSINGLE_LIST_ENTRY ListHead
,
351 * FUNCTION: Removes (pops) an entry from a singly list
353 * ListHead = Points to the head of the list
354 * Lock = Lock for synchronizing access to the list
355 * RETURNS: The removed entry
358 PSINGLE_LIST_ENTRY ret
;
361 KeAcquireSpinLock(Lock
,&oldlvl
);
362 ret
= PopEntryList(ListHead
);
363 KeReleaseSpinLock(Lock
,oldlvl
);
371 PSINGLE_LIST_ENTRY FASTCALL
372 ExfInterlockedPushEntryList(IN PSINGLE_LIST_ENTRY ListHead
,
373 IN PSINGLE_LIST_ENTRY ListEntry
,
376 * FUNCTION: Inserts (pushes) an entry into a singly linked list
378 * ListHead = Points to the head of the list
379 * ListEntry = Points to the entry to be inserted
380 * Lock = Caller supplied spinlock used to synchronize access
381 * RETURNS: The previous head of the list
385 PSINGLE_LIST_ENTRY ret
;
387 KeAcquireSpinLock(Lock
,&oldlvl
);
389 PushEntryList(ListHead
,ListEntry
);
390 KeReleaseSpinLock(Lock
,oldlvl
);
399 ExfInterlockedRemoveHeadList(IN PLIST_ENTRY Head
,
402 * FUNCTION: Removes the head of a double linked list
404 * Head = Points to the head of the list
405 * Lock = Lock for synchronizing access to the list
406 * RETURNS: The removed entry
412 KeAcquireSpinLock(Lock
,&oldlvl
);
413 if (IsListEmpty(Head
))
419 ret
= RemoveHeadList(Head
);
421 KeReleaseSpinLock(Lock
,oldlvl
);
431 InterlockedPopEntrySList(IN PSLIST_HEADER ListHead
)
433 return (PSLIST_ENTRY
) ExInterlockedPopEntrySList(ListHead
,
443 InterlockedPushEntrySList(IN PSLIST_HEADER ListHead
,
444 IN PSLIST_ENTRY ListEntry
)
446 return (PSLIST_ENTRY
) ExInterlockedPushEntrySList(ListHead
,