2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/rtl/list.c
5 * PURPOSE: Manages linked lists
6 * PROGRAMMER: David Welch (welch@mcmail.com)
9 /* INCLUDES *****************************************************************/
11 #include <ddk/ntddk.h>
14 #include <internal/debug.h>
16 /* FUNCTIONS *************************************************************/
18 static BOOLEAN
CheckEntry(PLIST_ENTRY ListEntry
)
20 assert(ListEntry
!=NULL
);
21 assert(ListEntry
->Blink
!=NULL
);
22 assert(ListEntry
->Blink
->Flink
!=NULL
);
23 assert(ListEntry
->Flink
!=NULL
);
24 assert(ListEntry
->Flink
->Blink
!=NULL
);
28 BOOLEAN
IsListEmpty(PLIST_ENTRY ListHead
)
30 * FUNCTION: Determines if a list is empty
32 * ListHead = Head of the list
33 * RETURNS: True if there are no entries in the list
36 return(ListHead
->Flink
==ListHead
);
39 VOID
RemoveEntryList(PLIST_ENTRY ListEntry
)
44 DPRINT("RemoveEntryList(ListEntry %x)\n", ListEntry
);
46 assert(CheckEntry(ListEntry
));
48 OldFlink
=ListEntry
->Flink
;
49 OldBlink
=ListEntry
->Blink
;
51 OldFlink
->Blink
=OldBlink
;
52 OldBlink
->Flink
=OldFlink
;
54 assert(CheckEntry(ListEntry
));
56 DPRINT("RemoveEntryList()\n");
59 PLIST_ENTRY
RemoveTailList(PLIST_ENTRY ListHead
)
61 * FUNCTION: Remove the tail entry from a double linked list
63 * ListHead = Head of the list to remove from
64 * RETURNS: The removed entry
67 PLIST_ENTRY Old
= ListHead
->Blink
;
68 RemoveEntryList(ListHead
->Blink
);
72 PLIST_ENTRY
RemoveHeadList(PLIST_ENTRY ListHead
)
76 DPRINT("RemoveHeadList(ListHead %x)\n",ListHead
);
78 assert(CheckEntry(ListHead
));
80 Old
= ListHead
->Flink
;
81 RemoveEntryList(ListHead
->Flink
);
83 assert(CheckEntry(ListHead
));
85 DPRINT("RemoveHeadList()\n");
90 VOID
InitializeListHead(PLIST_ENTRY ListHead
)
92 * FUNCTION: Initializes a double linked list
94 * ListHead = Caller supplied storage for the head of the list
97 ListHead
->Flink
= ListHead
->Blink
= ListHead
;
100 VOID
InsertTailList(PLIST_ENTRY ListHead
, PLIST_ENTRY ListEntry
)
102 * FUNCTION: Inserts an entry in a double linked list
104 * ListHead = Head of the list
105 * Entry = Entry to insert
110 Blink
= ListHead
->Blink
;
111 ListEntry
->Flink
=ListHead
;
112 ListEntry
->Blink
=Blink
;
113 Blink
->Flink
=ListEntry
;
114 ListHead
->Blink
=ListEntry
;
117 VOID
InsertHeadList(PLIST_ENTRY ListHead
, PLIST_ENTRY ListEntry
)
119 PLIST_ENTRY OldFlink
;
121 OldFlink
= ListHead
->Flink
;
122 ListEntry
->Flink
= OldFlink
;
123 ListEntry
->Blink
= ListHead
;
124 OldFlink
->Blink
= ListEntry
;
125 ListHead
->Flink
= ListEntry
;
128 PLIST_ENTRY
ExInterlockedInsertTailList(PLIST_ENTRY ListHead
,
129 PLIST_ENTRY ListEntry
,
135 KeAcquireSpinLock(Lock
,&oldlvl
);
136 if (IsListEmpty(ListHead
))
142 Old
= ListHead
->Blink
;
144 InsertTailList(ListHead
,ListEntry
);
145 KeReleaseSpinLock(Lock
,oldlvl
);
150 PLIST_ENTRY
ExInterlockedInsertHeadList(PLIST_ENTRY ListHead
,
151 PLIST_ENTRY ListEntry
,
154 * FUNCTION: Inserts an entry at the head of a doubly linked list
156 * ListHead = Points to the head of the list
157 * ListEntry = Points to the entry to be inserted
158 * Lock = Caller supplied spinlock used to synchronise access
159 * RETURNS: The previous head of the list
165 KeAcquireSpinLock(Lock
,&oldlvl
);
166 if (IsListEmpty(ListHead
))
172 Old
= ListHead
->Flink
;
174 InsertHeadList(ListHead
,ListEntry
);
175 KeReleaseSpinLock(Lock
,oldlvl
);
181 PLIST_ENTRY
ExInterlockedRemoveHeadList(PLIST_ENTRY Head
,
184 * FUNCTION: Removes the head of a double linked list
187 * Lock = Lock for synchronizing access to the list
188 * RETURNS: The removed entry
194 KeAcquireSpinLock(Lock
,&oldlvl
);
195 if (IsListEmpty(Head
))
201 ret
= RemoveHeadList(Head
);
203 KeReleaseSpinLock(Lock
,oldlvl
);
207 PLIST_ENTRY
ExInterlockedRemoveTailList(PLIST_ENTRY Head
,
210 * FUNCTION: Removes the tail of a double linked list
213 * Lock = Lock for synchronizing access to the list
214 * RETURNS: The removed entry
220 KeAcquireSpinLock(Lock
,&oldlvl
);
221 if (IsListEmpty(Head
))
227 ret
= RemoveTailList(Head
);
229 KeReleaseSpinLock(Lock
,oldlvl
);