537 lines
15 KiB
C++
537 lines
15 KiB
C++
/**
|
|
* PROJECT: ExectOS
|
|
* COPYRIGHT: See COPYING.md in the top level directory
|
|
* FILE: xtoskrnl/rtl/amd64/slist.cc
|
|
* DESCRIPTION: Singly linked list manipulation routines for AMD64 architecture
|
|
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
|
* Aiken Harris <harraiken91@gmail.com>
|
|
*/
|
|
|
|
#include <xtos.hh>
|
|
|
|
|
|
/**
|
|
* Retrieves the first entry from a singly linked list without removing it from the list.
|
|
*
|
|
* @param ListHead
|
|
* Supplies a pointer to a structure that serves as the list header.
|
|
*
|
|
* @return This routine returns a pointer to the first entry in the list, or NULLPTR if the list is empty.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTCDECL
|
|
PSINGLE_LIST_ENTRY
|
|
RTL::SinglyList::GetFirstEntry(IN PSINGLE_LIST_HEADER ListHead)
|
|
{
|
|
/* Check if the list is empty */
|
|
if(ListEmpty(ListHead))
|
|
{
|
|
/* Empty list, return NULLPTR */
|
|
return NULLPTR;
|
|
}
|
|
|
|
/* Check if the header is initialized as a modern 16-byte header */
|
|
if(ListHead->Header16.HeaderType)
|
|
{
|
|
/* Extract pointer from Region */
|
|
return (PSINGLE_LIST_ENTRY)(ListHead->Region & ~0xFLL);
|
|
}
|
|
else
|
|
{
|
|
/* Decompress and return the pointer */
|
|
return (PSINGLE_LIST_ENTRY)(((ULONG64)ListHead & 0xFFFFF8000000000FULL) |
|
|
((ULONG64)ListHead->Header8.NextEntry << 4));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Initializes a structure representing the head of a singly linked list.
|
|
*
|
|
* @param ListHead
|
|
* Supplies a pointer to a structure that serves as the list header.
|
|
*
|
|
* @return This routine does not return any value.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTCDECL
|
|
VOID
|
|
RTL::SinglyList::InitializeListHead(IN PSINGLE_LIST_HEADER ListHead)
|
|
{
|
|
/* Initialize the singly linked list head */
|
|
ListHead->Alignment = 0;
|
|
ListHead->Region = 0;
|
|
ListHead->Header16.HeaderType = 1;
|
|
}
|
|
|
|
/**
|
|
* Inserts an entry at the head of a singly linked list.
|
|
*
|
|
* @param ListHead
|
|
* Supplies a pointer to the head of the list.
|
|
*
|
|
* @param Entry
|
|
* Supplies a pointer to the entry that will be inserted in the list.
|
|
*
|
|
* @return This routine returns a pointer to the original first entry in the list.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTCDECL
|
|
PSINGLE_LIST_ENTRY
|
|
RTL::SinglyList::InsertHeadList(IN OUT PSINGLE_LIST_HEADER ListHead,
|
|
IN PSINGLE_LIST_ENTRY Entry)
|
|
{
|
|
PSINGLE_LIST_ENTRY OriginalEntry;
|
|
|
|
/* Store the original first entry */
|
|
OriginalEntry = RTL::SinglyList::GetFirstEntry(ListHead);
|
|
|
|
/* Insert entry at the head of the list */
|
|
Entry->Next = OriginalEntry;
|
|
|
|
/* Check if the header is initialized as a modern 16-byte header */
|
|
if(ListHead->Header16.HeaderType)
|
|
{
|
|
/* Update pointer and increment depth and sequence */
|
|
ListHead->Region = ((ULONG64)Entry & ~0xFLL) | (ListHead->Region & 0xFLL);
|
|
ListHead->Header16.Depth++;
|
|
ListHead->Header16.Sequence++;
|
|
}
|
|
else
|
|
{
|
|
/* Update pointer and increment depth and sequence */
|
|
ListHead->Header8.NextEntry = ((ULONG64)Entry >> 4) & 0x7FFFFFFFFFULL;
|
|
ListHead->Header8.Depth++;
|
|
ListHead->Header8.Sequence++;
|
|
}
|
|
|
|
/* Return original first entry */
|
|
return OriginalEntry;
|
|
}
|
|
|
|
/**
|
|
* Inserts an entry at the tail of a singly linked list.
|
|
*
|
|
* @param ListHead
|
|
* Supplies a pointer to the head of the list.
|
|
*
|
|
* @param Entry
|
|
* Supplies a pointer to the entry that will be inserted in the list.
|
|
*
|
|
* @return This routine returns a pointer to the original last entry in the list.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTCDECL
|
|
PSINGLE_LIST_ENTRY
|
|
RTL::SinglyList::InsertTailList(IN OUT PSINGLE_LIST_HEADER ListHead,
|
|
IN PSINGLE_LIST_ENTRY Entry)
|
|
{
|
|
PSINGLE_LIST_ENTRY CurrentEntry, OriginalEntry;
|
|
|
|
/* Set Next pointer of the new entry to NULLPTR */
|
|
Entry->Next = NULLPTR;
|
|
|
|
/* Check if the list is empty */
|
|
if(ListEmpty(ListHead))
|
|
{
|
|
/* Store the original last entry */
|
|
OriginalEntry = NULLPTR;
|
|
|
|
/* Check if the header is initialized as a modern 16-byte header */
|
|
if(ListHead->Header16.HeaderType)
|
|
{
|
|
/* Insert entry at the head */
|
|
ListHead->Region = ((ULONG64)Entry & ~0xFLL) | (ListHead->Region & 0xFLL);
|
|
}
|
|
else
|
|
{
|
|
/* Insert entry at the head */
|
|
ListHead->Header8.NextEntry = ((ULONG64)Entry >> 4) & 0x7FFFFFFFFFULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Traverse the list to find the last entry */
|
|
CurrentEntry = RTL::SinglyList::GetFirstEntry(ListHead);
|
|
while(CurrentEntry->Next != NULLPTR)
|
|
{
|
|
/* Move to the next entry */
|
|
CurrentEntry = CurrentEntry->Next;
|
|
}
|
|
|
|
/* Store the original last entry */
|
|
OriginalEntry = CurrentEntry;
|
|
|
|
/* Insert entry at the tail */
|
|
CurrentEntry->Next = Entry;
|
|
}
|
|
|
|
/* Check if the header is initialized as a modern 16-byte header */
|
|
if(ListHead->Header16.HeaderType)
|
|
{
|
|
/* Increment list depth and sequence */
|
|
ListHead->Header16.Depth++;
|
|
ListHead->Header16.Sequence++;
|
|
}
|
|
else
|
|
{
|
|
/* Increment list depth and sequence */
|
|
ListHead->Header8.Depth++;
|
|
ListHead->Header8.Sequence++;
|
|
}
|
|
|
|
/* Return original last entry */
|
|
return OriginalEntry;
|
|
}
|
|
|
|
/**
|
|
* Indicates whether a singly linked list structure is empty, or not initialized at all.
|
|
*
|
|
* @param ListHead
|
|
* Supplies a pointer to a structure that represents the head of the list.
|
|
*
|
|
* @return This routine returns TRUE if there are currently no entries in the list or FALSE otherwise.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTCDECL
|
|
BOOLEAN
|
|
RTL::SinglyList::ListEmpty(IN PSINGLE_LIST_HEADER ListHead)
|
|
{
|
|
/* Check if the list is uninitialized */
|
|
if(ListHead == NULLPTR)
|
|
{
|
|
/* Empty list, return TRUE */
|
|
return TRUE;
|
|
}
|
|
|
|
/* Check if the header is initialized as a modern 16-byte header */
|
|
if(ListHead->Header16.HeaderType)
|
|
{
|
|
/* Check if the list is empty */
|
|
return ((ListHead->Region & ~0xFLL) == 0);
|
|
}
|
|
else
|
|
{
|
|
/* Check if the list is empty */
|
|
return (ListHead->Header8.NextEntry == 0);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Queries the current depth (number of entries) of a singly linked list.
|
|
*
|
|
* @param ListHead
|
|
* Supplies a pointer to a structure that represents the head of the singly linked list.
|
|
*
|
|
* @return This routine returns the number of entries currently in the list, or zero if the list head is NULLPTR.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTAPI
|
|
USHORT
|
|
RTL::SinglyList::QueryListDepth(IN PSINGLE_LIST_HEADER ListHead)
|
|
{
|
|
/* Check if the list head is initialized and valid */
|
|
if(ListHead == NULLPTR)
|
|
{
|
|
/* Return zero */
|
|
return 0;
|
|
}
|
|
|
|
/* Check if the header is initialized as a modern 16-byte header */
|
|
if(ListHead->Header16.HeaderType)
|
|
{
|
|
/* Return the list depth */
|
|
return (USHORT)ListHead->Header16.Depth;
|
|
}
|
|
else
|
|
{
|
|
/* Return the list depth */
|
|
return (USHORT)ListHead->Header8.Depth;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Removes an entry from a singly linked list.
|
|
*
|
|
* @param ListHead
|
|
* Supplies a pointer to the head of the list.
|
|
*
|
|
* @param Entry
|
|
* Supplies a pointer to the entry that will be removed from the list.
|
|
*
|
|
* @return This routine does not return any value.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTCDECL
|
|
VOID
|
|
RTL::SinglyList::RemoveEntryList(IN PSINGLE_LIST_HEADER ListHead,
|
|
IN PSINGLE_LIST_ENTRY Entry)
|
|
{
|
|
PSINGLE_LIST_ENTRY FirstEntry, PreviousEntry;
|
|
|
|
/* Check if the list is empty */
|
|
if(ListEmpty(ListHead))
|
|
{
|
|
/* List is empty, nothing to remove, return */
|
|
return;
|
|
}
|
|
|
|
/* Retrieve the first entry dynamically */
|
|
FirstEntry = RTL::SinglyList::GetFirstEntry(ListHead);
|
|
|
|
/* Check if the entry is the first one */
|
|
if(FirstEntry == Entry)
|
|
{
|
|
/* Check if the header is initialized as a modern 16-byte header */
|
|
if(ListHead->Header16.HeaderType)
|
|
{
|
|
/* Remove the first entry and decrement depth */
|
|
ListHead->Region = ((ULONG64)Entry->Next & ~0xFLL) | (ListHead->Region & 0xFLL);
|
|
ListHead->Header16.Depth--;
|
|
}
|
|
else
|
|
{
|
|
/* Remove the first entry and decrement depth */
|
|
ListHead->Header8.NextEntry = ((ULONG64)Entry->Next >> 4) & 0x7FFFFFFFFFULL;
|
|
ListHead->Header8.Depth--;
|
|
}
|
|
|
|
/* Nothing else to do, return */
|
|
return;
|
|
}
|
|
|
|
/* Find the previous entry */
|
|
PreviousEntry = FirstEntry;
|
|
while(PreviousEntry->Next != Entry)
|
|
{
|
|
/* Move to the next entry */
|
|
PreviousEntry = PreviousEntry->Next;
|
|
|
|
/* Check if we reached the end of the list */
|
|
if(PreviousEntry == NULLPTR)
|
|
{
|
|
/* Entry not found, return */
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* Remove the entry */
|
|
PreviousEntry->Next = Entry->Next;
|
|
|
|
/* Check if the header is initialized as a modern 16-byte header */
|
|
if(ListHead->Header16.HeaderType)
|
|
{
|
|
/* Decrement depth */
|
|
ListHead->Header16.Depth--;
|
|
}
|
|
else
|
|
{
|
|
/* Decrement depth */
|
|
ListHead->Header8.Depth--;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Splices a singly linked list at the head of another list. The source list is reinitialized to empty.
|
|
*
|
|
* @param ListHead
|
|
* Supplies a pointer to a structure that represents the head of the list.
|
|
*
|
|
* @param SpliceList
|
|
* Supplies a pointer to a structure that represents the head of the list that will be spliced.
|
|
*
|
|
* @return This routine returns a pointer to the original first entry in the list.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTCDECL
|
|
PSINGLE_LIST_ENTRY
|
|
RTL::SinglyList::SpliceHeadList(IN OUT PSINGLE_LIST_HEADER ListHead,
|
|
IN OUT PSINGLE_LIST_HEADER SpliceList)
|
|
{
|
|
PSINGLE_LIST_ENTRY LastEntry, OriginalEntry, SpliceFirstEntry;
|
|
|
|
/* Store the original first entry */
|
|
OriginalEntry = RTL::SinglyList::GetFirstEntry(ListHead);
|
|
|
|
/* Check if the list to splice is empty */
|
|
if(ListEmpty(SpliceList))
|
|
{
|
|
/* Nothing to splice, return original first entry */
|
|
return OriginalEntry;
|
|
}
|
|
|
|
/* Find the last entry of the list to splice */
|
|
SpliceFirstEntry = RTL::SinglyList::GetFirstEntry(SpliceList);
|
|
LastEntry = SpliceFirstEntry;
|
|
while(LastEntry->Next != NULLPTR)
|
|
{
|
|
/* Move to the next entry */
|
|
LastEntry = LastEntry->Next;
|
|
}
|
|
|
|
/* Splice the list at the head of destination */
|
|
LastEntry->Next = OriginalEntry;
|
|
|
|
/* Check if the header is initialized as a modern 16-byte header */
|
|
if(ListHead->Header16.HeaderType)
|
|
{
|
|
/* Update destination list header pointers and values */
|
|
ListHead->Region = ((ULONG64)SpliceFirstEntry & ~0xFLL) | (ListHead->Region & 0xFLL);
|
|
ListHead->Header16.Depth += RTL::SinglyList::QueryListDepth(SpliceList);
|
|
ListHead->Header16.Sequence++;
|
|
|
|
/* Reinitialize the source list and preserve format flags */
|
|
SpliceList->Region &= 0xFLL;
|
|
SpliceList->Header16.Depth = 0;
|
|
}
|
|
else
|
|
{
|
|
/* Update destination list header pointers and values */
|
|
ListHead->Header8.NextEntry = ((ULONG64)SpliceFirstEntry >> 4) & 0x7FFFFFFFFFULL;
|
|
ListHead->Header8.Depth += RTL::SinglyList::QueryListDepth(SpliceList);
|
|
ListHead->Header8.Sequence++;
|
|
|
|
/* Reinitialize the source list and preserve format flags */
|
|
SpliceList->Header8.NextEntry = 0;
|
|
SpliceList->Header8.Depth = 0;
|
|
}
|
|
|
|
/* Return the original first entry */
|
|
return OriginalEntry;
|
|
}
|
|
|
|
/**
|
|
* Splices a singly linked list at the tail of another list. The source list is reinitialized to empty.
|
|
*
|
|
* @param ListHead
|
|
* Supplies a pointer to the head of the destination list.
|
|
*
|
|
* @param SpliceList
|
|
* Supplies a pointer to the head of the list that will be spliced.
|
|
*
|
|
* @return This routine returns a pointer to the original last entry in the list.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTCDECL
|
|
PSINGLE_LIST_ENTRY
|
|
RTL::SinglyList::SpliceTailList(IN OUT PSINGLE_LIST_HEADER ListHead,
|
|
IN OUT PSINGLE_LIST_HEADER SpliceList)
|
|
{
|
|
PSINGLE_LIST_ENTRY LastEntry, OriginalEntry, SpliceFirstEntry;
|
|
|
|
/* Get the first entry of the list to splice */
|
|
SpliceFirstEntry = RTL::SinglyList::GetFirstEntry(SpliceList);
|
|
|
|
/* Check if the destination list is empty */
|
|
if(ListEmpty(ListHead))
|
|
{
|
|
/* Destination is empty, original last entry is NULLPTR */
|
|
OriginalEntry = NULLPTR;
|
|
|
|
/* Check if the header is initialized as a modern 16-byte header */
|
|
if(ListHead->Header16.HeaderType)
|
|
{
|
|
/* Move the splice list to the destination head */
|
|
ListHead->Region = ((ULONG64)SpliceFirstEntry & ~0xFLL) | (ListHead->Region & 0xFLL);
|
|
}
|
|
else
|
|
{
|
|
/* Move the splice list to the destination head */
|
|
ListHead->Header8.NextEntry = ((ULONG64)SpliceFirstEntry >> 4) & 0x7FFFFFFFFFULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Find the last entry of the destination list */
|
|
LastEntry = RTL::SinglyList::GetFirstEntry(ListHead);
|
|
while(LastEntry->Next != NULLPTR)
|
|
{
|
|
/* Move to the next entry */
|
|
LastEntry = LastEntry->Next;
|
|
}
|
|
|
|
/* Store the original last entry */
|
|
OriginalEntry = LastEntry;
|
|
|
|
/* Splice the list at the tail of destination */
|
|
LastEntry->Next = SpliceFirstEntry;
|
|
}
|
|
|
|
/* Check if the header is initialized as a modern 16-byte header */
|
|
if(ListHead->Header16.HeaderType)
|
|
{
|
|
/* Update depth and sequence of the destination list */
|
|
ListHead->Header16.Depth += RTL::SinglyList::QueryListDepth(SpliceList);
|
|
ListHead->Header16.Sequence++;
|
|
|
|
/* Reinitialize the source list to empty while preserving format flags */
|
|
SpliceList->Region &= 0xFLL;
|
|
SpliceList->Header16.Depth = 0;
|
|
}
|
|
else
|
|
{
|
|
/* Update depth and sequence of the destination list */
|
|
ListHead->Header8.Depth += RTL::SinglyList::QueryListDepth(SpliceList);
|
|
ListHead->Header8.Sequence++;
|
|
|
|
/* Reinitialize the source list to empty while preserving format flags */
|
|
SpliceList->Header8.NextEntry = 0;
|
|
SpliceList->Header8.Depth = 0;
|
|
}
|
|
|
|
/* Return the original last entry */
|
|
return OriginalEntry;
|
|
}
|
|
|
|
/**
|
|
* Retrieves the first entry from a singly linked list and removes it from the list.
|
|
*
|
|
* @param ListHead
|
|
* Pointer to a structure that serves as the list header.
|
|
*
|
|
* @return This routine returns a pointer to the first entry in the list, or NULLPTR if the list is empty.
|
|
*
|
|
* @since XT 1.0
|
|
*/
|
|
XTCDECL
|
|
PSINGLE_LIST_ENTRY
|
|
RTL::SinglyList::TakeFirstEntry(IN PSINGLE_LIST_HEADER ListHead)
|
|
{
|
|
PSINGLE_LIST_ENTRY Entry;
|
|
|
|
/* Check if the list is empty */
|
|
if(ListEmpty(ListHead))
|
|
{
|
|
/* List is empty, return NULLPTR */
|
|
return NULLPTR;
|
|
}
|
|
|
|
/* Get the first entry dynamically */
|
|
Entry = RTL::SinglyList::GetFirstEntry(ListHead);
|
|
|
|
/* Check if the header is initialized as a modern 16-byte header */
|
|
if(ListHead->Header16.HeaderType)
|
|
{
|
|
/* Remove entry from the list and decrement depth */
|
|
ListHead->Region = ((ULONG64)Entry->Next & ~0xFLL) | (ListHead->Region & 0xFLL);
|
|
ListHead->Header16.Depth--;
|
|
}
|
|
else
|
|
{
|
|
/* Remove entry from the list and decrement depth */
|
|
ListHead->Header8.NextEntry = ((ULONG64)Entry->Next >> 4) & 0x7FFFFFFFFFULL;
|
|
ListHead->Header8.Depth--;
|
|
}
|
|
|
|
/* Return the first entry */
|
|
return Entry;
|
|
}
|