summaryrefslogtreecommitdiffstats
path: root/private/ntos/mm/addrsup.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/mm/addrsup.c')
-rw-r--r--private/ntos/mm/addrsup.c1432
1 files changed, 1432 insertions, 0 deletions
diff --git a/private/ntos/mm/addrsup.c b/private/ntos/mm/addrsup.c
new file mode 100644
index 000000000..8d3b34772
--- /dev/null
+++ b/private/ntos/mm/addrsup.c
@@ -0,0 +1,1432 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ addrsup.c
+
+Abstract:
+
+ This module contains the routine to manipulate the virtual address
+ descriptor tree.
+
+Author:
+
+ Lou Perazzoli (loup) 19-May-1989
+
+ Ripped off and modified from timersup.c
+ The support for siblings was removed and a routine to locate
+ the corresponding virtual address descriptor for a given address
+ was added.
+
+Environment:
+
+ Kernel mode only, working set mutex held, APC's disabled.
+
+Revision History:
+
+--*/
+
+#include "mi.h"
+
+#if (_MSC_VER >= 800)
+#pragma warning(disable:4010) /* Allow pretty pictures without the noise */
+#endif
+
+VOID
+MiReorderTree (
+ IN PMMADDRESS_NODE Node,
+ IN OUT PMMADDRESS_NODE *Root
+ );
+
+
+VOID
+MiReorderTree (
+ IN PMMADDRESS_NODE Node,
+ IN OUT PMMADDRESS_NODE *Root
+ )
+
+/*++
+
+Routine Description:
+
+ This function reorders the Node tree by applying various splay functions
+ to the tree. This is a local function that is called by the insert Node
+ routine.
+
+Arguments:
+
+ Node - Supplies a pointer to a virtual address descriptor.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PMMADDRESS_NODE GrandParent;
+ PMMADDRESS_NODE Parent;
+ PMMADDRESS_NODE SplayNode;
+
+ //
+ // Reorder Node tree to make it as balanced as possible with as little
+ // work as possible.
+ //
+
+ SplayNode = Node;
+
+ while (SplayNode != *Root) {
+
+ Parent = SplayNode->Parent;
+ if (Parent == *Root) {
+
+ //
+ // Splay node's parent is the root of the tree. Rotate the tree
+ // left or right depending on whether the splay node is the left
+ // of right child of its parent.
+ //
+ // Pictorially:
+ //
+ // Right Left
+ //
+ // P X P X
+ // / \ / \ / \ / \
+ // X C -> A P C X -> P A
+ // / \ / \ / \ / \
+ // A B B C B A C B
+ //
+
+ *Root = SplayNode;
+ SplayNode->Parent = (PMMADDRESS_NODE)NULL;
+ Parent->Parent = SplayNode;
+ if (SplayNode == Parent->LeftChild) {
+
+ //
+ // Splay node is the left child of its parent. Rotate tree
+ // right.
+ //
+
+ Parent->LeftChild = SplayNode->RightChild;
+ if (SplayNode->RightChild) {
+ SplayNode->RightChild->Parent = Parent;
+ }
+ SplayNode->RightChild = Parent;
+ } else {
+
+ //
+ // Splay node is the right child of its parent. Rotate tree
+ // left.
+ //
+
+ Parent->RightChild = SplayNode->LeftChild;
+ if (SplayNode->LeftChild) {
+ SplayNode->LeftChild->Parent = Parent;
+ }
+ SplayNode->LeftChild = Parent;
+ }
+ break;
+ } else {
+ GrandParent = Parent->Parent;
+ if ((SplayNode == Parent->LeftChild) &&
+ (Parent == GrandParent->LeftChild)) {
+
+ //
+ // Both the splay node and the parent node are left children
+ // of their parents. Rotate tree right and make the parent
+ // the root of the new subtree.
+ //
+ // Pictorially:
+ //
+ // G P
+ // / \ / \
+ // P D X G
+ // / \ -> / \ / \
+ // X C A B C D
+ // / \
+ // A B
+ //
+
+ if (GrandParent == *Root) {
+ *Root = Parent;
+ Parent->Parent = (PMMADDRESS_NODE)NULL;
+ } else {
+ Parent->Parent = GrandParent->Parent;
+ if (GrandParent == GrandParent->Parent->LeftChild) {
+ GrandParent->Parent->LeftChild = Parent;
+ } else {
+ GrandParent->Parent->RightChild = Parent;
+ }
+ }
+ GrandParent->LeftChild = Parent->RightChild;
+ if (Parent->RightChild) {
+ Parent->RightChild->Parent = GrandParent;
+ }
+ GrandParent->Parent = Parent;
+ Parent->RightChild = GrandParent;
+ SplayNode = Parent;
+ } else if ((SplayNode == Parent->RightChild) &&
+ (Parent == GrandParent->RightChild)) {
+
+ //
+ // Both the splay node and the parent node are right children
+ // of their parents. Rotate tree left and make the parent
+ // the root of the new subtree.
+ //
+ // Pictorially:
+ //
+ // G P
+ // / \ / \
+ // D P G X
+ // / \ -> / \ / \
+ // C X D C B A
+ // / \
+ // A B
+ //
+
+ if (GrandParent == *Root) {
+ *Root = Parent;
+ Parent->Parent = (PMMADDRESS_NODE)NULL;
+ } else {
+ Parent->Parent = GrandParent->Parent;
+ if (GrandParent == GrandParent->Parent->LeftChild) {
+ GrandParent->Parent->LeftChild = Parent;
+ } else {
+ GrandParent->Parent->RightChild = Parent;
+ }
+ }
+ GrandParent->RightChild = Parent->LeftChild;
+ if (Parent->LeftChild) {
+ Parent->LeftChild->Parent = GrandParent;
+ }
+ GrandParent->Parent = Parent;
+ Parent->LeftChild = GrandParent;
+ SplayNode = Parent;
+ } else if ((SplayNode == Parent->LeftChild) &&
+ (Parent == GrandParent->RightChild)) {
+
+ //
+ // Splay node is the left child of its parent and parent is
+ // the right child of its parent. Rotate tree left and make
+ // splay node the root of the new subtree.
+ //
+ // Pictorially:
+ //
+ // G X
+ // / \ / \
+ // A P G P
+ // / \ -> / \ / \
+ // X D A B C D
+ // / \
+ // B C
+ //
+
+ if (GrandParent == *Root) {
+ *Root = SplayNode;
+ SplayNode->Parent = (PMMADDRESS_NODE)NULL;
+ } else {
+ SplayNode->Parent = GrandParent->Parent;
+ if (GrandParent == GrandParent->Parent->LeftChild) {
+ GrandParent->Parent->LeftChild = SplayNode;
+ } else {
+ GrandParent->Parent->RightChild = SplayNode;
+ }
+ }
+ Parent->LeftChild = SplayNode->RightChild;
+ if (SplayNode->RightChild) {
+ SplayNode->RightChild->Parent = Parent;
+ }
+ GrandParent->RightChild = SplayNode->LeftChild;
+ if (SplayNode->LeftChild) {
+ SplayNode->LeftChild->Parent = GrandParent;
+ }
+ Parent->Parent = SplayNode;
+ GrandParent->Parent = SplayNode;
+ SplayNode->LeftChild = GrandParent;
+ SplayNode->RightChild = Parent;
+ } else {
+
+ //
+ // Splay node is the right child of its parent and parent is
+ // the left child of its parent. Rotate tree right and make
+ // splay node the root of the new subtree.
+ //
+ // Pictorially:
+ //
+ // G X
+ // / \ / \
+ // P A P G
+ // / \ -> / \ / \
+ // D X D C B A
+ // / \
+ // C B
+ //
+
+ if (GrandParent == *Root) {
+ *Root = SplayNode;
+ SplayNode->Parent = (PMMADDRESS_NODE)NULL;
+ } else {
+ SplayNode->Parent = GrandParent->Parent;
+ if (GrandParent == GrandParent->Parent->LeftChild) {
+ GrandParent->Parent->LeftChild = SplayNode;
+ } else {
+ GrandParent->Parent->RightChild = SplayNode;
+ }
+ }
+ Parent->RightChild = SplayNode->LeftChild;
+ if (SplayNode->LeftChild) {
+ SplayNode->LeftChild->Parent = Parent;
+ }
+ GrandParent->LeftChild = SplayNode->RightChild;
+ if (SplayNode->RightChild) {
+ SplayNode->RightChild->Parent = GrandParent;
+ }
+ Parent->Parent = SplayNode;
+ GrandParent->Parent = SplayNode;
+ SplayNode->LeftChild = Parent;
+ SplayNode->RightChild = GrandParent;
+ }
+ }
+ }
+ return;
+}
+
+PMMADDRESS_NODE
+FASTCALL
+MiGetNextNode (
+ IN PMMADDRESS_NODE Node
+ )
+
+/*++
+
+Routine Description:
+
+ This function locates the virtual address descriptor which contains
+ the address range which logically follows the specified address range.
+
+Arguments:
+
+ Node - Supplies a pointer to a virtual address descriptor.
+
+Return Value:
+
+ Returns a pointer to the virtual address descriptor containing the
+ next address range, NULL if none.
+
+--*/
+
+{
+ PMMADDRESS_NODE Next;
+ PMMADDRESS_NODE Parent;
+ PMMADDRESS_NODE Left;
+
+ Next = Node;
+
+ if (Next->RightChild == (PMMADDRESS_NODE)NULL) {
+
+ while ((Parent = Next->Parent) != (PMMADDRESS_NODE)NULL) {
+
+ //
+ // Locate the first ancestor of this node of which this
+ // node is the left child of and return that node as the
+ // next element.
+ //
+
+ if (Parent->LeftChild == Next) {
+ return Parent;
+ }
+
+ Next = Parent;
+
+ }
+
+ return (PMMADDRESS_NODE)NULL;
+ }
+
+ //
+ // A right child exists, locate the left most child of that right child.
+ //
+
+ Next = Next->RightChild;
+
+ while ((Left = Next->LeftChild) != (PMMADDRESS_NODE)NULL) {
+ Next = Left;
+ }
+ return Next;
+
+}
+
+PMMADDRESS_NODE
+FASTCALL
+MiGetPreviousNode (
+ IN PMMADDRESS_NODE Node
+ )
+
+/*++
+
+Routine Description:
+
+ This function locates the virtual address descriptor which contains
+ the address range which logically precedes the specified virtual
+ address descriptor.
+
+Arguments:
+
+ Node - Supplies a pointer to a virtual address descriptor.
+
+Return Value:
+
+ Returns a pointer to the virtual address descriptor containing the
+ next address range, NULL if none.
+
+--*/
+
+{
+ PMMADDRESS_NODE Previous;
+
+ Previous = Node;
+
+ if (Previous->LeftChild == (PMMADDRESS_NODE)NULL) {
+
+
+ while (Previous->Parent != (PMMADDRESS_NODE)NULL) {
+
+ //
+ // Locate the first ancestor of this node of which this
+ // node is the right child of and return that node as the
+ // Previous element.
+ //
+
+ if (Previous->Parent->RightChild == Previous) {
+ return Previous->Parent;
+ }
+
+ Previous = Previous->Parent;
+
+ }
+ return (PMMADDRESS_NODE)NULL;
+ }
+
+ //
+ // A left child exists, locate the right most child of that left child.
+ //
+
+ Previous = Previous->LeftChild;
+ while (Previous->RightChild != (PMMADDRESS_NODE)NULL) {
+ Previous = Previous->RightChild;
+ }
+ return Previous;
+}
+
+PMMADDRESS_NODE
+FASTCALL
+MiGetFirstNode (
+ IN PMMADDRESS_NODE Root
+ )
+
+/*++
+
+Routine Description:
+
+ This function locates the virtual address descriptor which contains
+ the address range which logically is first within the address space.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns a pointer to the virtual address descriptor containing the
+ first address range, NULL if none.
+
+--*/
+
+{
+ PMMADDRESS_NODE First;
+
+ First = Root;
+
+ if (First == (PMMADDRESS_NODE)NULL) {
+ return (PMMADDRESS_NODE)NULL;
+ }
+
+ while (First->LeftChild != (PMMADDRESS_NODE)NULL) {
+ First = First->LeftChild;
+ }
+
+ return First;
+}
+
+VOID
+FASTCALL
+MiInsertNode (
+ IN PMMADDRESS_NODE Node,
+ IN OUT PMMADDRESS_NODE *Root
+ )
+
+/*++
+
+Routine Description:
+
+ This function inserts a virtual address descriptor into the tree and
+ reorders the splay tree as appropriate.
+
+Arguments:
+
+ Node - Supplies a pointer to a virtual address descriptor
+
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG Level = 0;
+ PMMADDRESS_NODE Parent;
+
+
+ //
+ // Initialize virtual address descriptor child links.
+ //
+
+ Node->LeftChild = (PMMADDRESS_NODE)NULL;
+ Node->RightChild = (PMMADDRESS_NODE)NULL;
+
+ //
+ // If the tree is empty, then establish this virtual address descriptor
+ // as the root of the tree.
+ // Otherwise descend the tree to find the correct place to
+ // insert the descriptor.
+ //
+
+ Parent = *Root;
+ if (!Parent) {
+ *Root = Node;
+ Node->Parent = (PMMADDRESS_NODE)NULL;
+ } else {
+ for (;;) {
+
+ Level += 1;
+ if (Level == 15) {
+ MiReorderTree(Parent, Root);
+ }
+
+ //
+ // If the starting address for this virtual address descriptor
+ // is less than the parent starting address, then
+ // follow the left child link. Else follow the right child link.
+ //
+
+ if (Node->StartingVa < Parent->StartingVa) {
+
+ //
+ // Starting address of the virtual address descriptor is less
+ // than the parent starting virtual address.
+ // Follow left child link if not null. Otherwise
+ // insert the descriptor as the left child of the parent and
+ // reorder the tree.
+ //
+
+ if (Parent->LeftChild) {
+ Parent = Parent->LeftChild;
+ } else {
+ Parent->LeftChild = Node;
+ Node->Parent = Parent;
+ // MiReorderTree(Node, Root);
+ break;
+ }
+ } else {
+
+ //
+ // Starting address of the virtual address descriptor is greater
+ // than the parent starting virtual address.
+ // Follow right child link if not null. Otherwise
+ // insert the descriptor as the right child of the parent and
+ // reorder the tree.
+ //
+
+ if (Parent->RightChild) {
+ Parent = Parent->RightChild;
+ } else {
+ Parent->RightChild = Node;
+ Node->Parent = Parent;
+ // MiReorderTree(Node, Root);
+ break;
+ }
+ }
+ }
+ }
+ return;
+}
+
+VOID
+FASTCALL
+MiRemoveNode (
+ IN PMMADDRESS_NODE Node,
+ IN OUT PMMADDRESS_NODE *Root
+ )
+
+/*++
+
+Routine Description:
+
+ This function removes a virtual address descriptor from the tree and
+ reorders the splay tree as appropriate.
+
+Arguments:
+
+ Node - Supplies a pointer to a virtual address descriptor.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PMMADDRESS_NODE LeftChild;
+ PMMADDRESS_NODE RightChild;
+ PMMADDRESS_NODE SplayNode;
+
+
+ LeftChild = Node->LeftChild;
+ RightChild = Node->RightChild;
+
+ //
+ // If the Node is the root of the tree, then establish new root. Else
+ // isolate splay case and perform splay tree transformation.
+ //
+
+ if (Node == *Root) {
+
+ //
+ // This Node is the root of the tree. There are four cases to
+ // handle:
+ //
+ // 1. the descriptor has no children
+ // 2. the descriptor has a left child but no right child
+ // 3. the descriptor has a right child but no left child
+ // 4. the descriptor has both a right child and a left child
+ //
+
+ if (LeftChild) {
+ if (RightChild) {
+
+ //
+ // The descriptor has both a left child and a right child.
+ //
+
+ if (LeftChild->RightChild) {
+
+ //
+ // The left child has a right child. Make the right most
+ // descendent of the right child of the left child the
+ // new root of the tree.
+ //
+ // Pictorially:
+ //
+ // R R
+ // | |
+ // X Z
+ // / \ / \
+ // A B -> A B
+ // \ \
+ // . .
+ // \
+ // Z
+ //
+
+ SplayNode = LeftChild->RightChild;
+ while (SplayNode->RightChild) {
+ SplayNode = SplayNode->RightChild;
+ }
+ *Root = SplayNode;
+ SplayNode->Parent->RightChild = SplayNode->LeftChild;
+ if (SplayNode->LeftChild) {
+ SplayNode->LeftChild->Parent = SplayNode->Parent;
+ }
+ SplayNode->Parent = (PMMADDRESS_NODE)NULL;
+ LeftChild->Parent = SplayNode;
+ RightChild->Parent = SplayNode;
+ SplayNode->LeftChild = LeftChild;
+ SplayNode->RightChild = RightChild;
+ } else if (RightChild->LeftChild) {
+
+ //
+ // The right child has a left child. Make the left most
+ // descendent of the left child of the right child the
+ // new root of the tree.
+ //
+ // Pictorially:
+ //
+ // R R
+ // | |
+ // X Z
+ // / \ / \
+ // A B -> A B
+ // / /
+ // . .
+ // /
+ // Z
+ //
+
+ SplayNode = RightChild->LeftChild;
+ while (SplayNode->LeftChild) {
+ SplayNode = SplayNode->LeftChild;
+ }
+ *Root = SplayNode;
+ SplayNode->Parent->LeftChild = SplayNode->RightChild;
+ if (SplayNode->RightChild) {
+ SplayNode->RightChild->Parent = SplayNode->Parent;
+ }
+ SplayNode->Parent = (PMMADDRESS_NODE)NULL;
+ LeftChild->Parent = SplayNode;
+ RightChild->Parent = SplayNode;
+ SplayNode->LeftChild = LeftChild;
+ SplayNode->RightChild = RightChild;
+ } else {
+
+ //
+ // The left child of the descriptor does not have a right child,
+ // and the right child of the descriptor does not have a left
+ // child. Make the left child of the descriptor the new root of
+ // the tree.
+ //
+ // Pictorially:
+ //
+ // R R
+ // | |
+ // X A
+ // / \ / \
+ // A B -> . B
+ // / /
+ // .
+ //
+
+ *Root = LeftChild;
+ LeftChild->Parent = (PMMADDRESS_NODE)NULL;
+ LeftChild->RightChild = RightChild;
+ LeftChild->RightChild->Parent = LeftChild;
+ }
+ } else {
+
+ //
+ // The descriptor has a left child, but does not have a right child.
+ // Make the left child the new root of the tree.
+ //
+ // Pictorially:
+ //
+ // R R
+ // | |
+ // X -> A
+ // /
+ // A
+ //
+
+ *Root = LeftChild;
+ LeftChild->Parent = (PMMADDRESS_NODE)NULL;
+ }
+ } else if (RightChild) {
+
+ //
+ // The descriptor has a right child, but does not have a left child.
+ // Make the right child the new root of the tree.
+ //
+ // Pictorially:
+ //
+ // R R
+ // | |
+ // X -> A
+ // \
+ // A
+ //
+
+ *Root = RightChild;
+ RightChild->Parent = (PMMADDRESS_NODE)NULL;
+ while (RightChild->LeftChild) {
+ RightChild = RightChild->LeftChild;
+ }
+ } else {
+
+ //
+ // The descriptor has neither a left child nor a right child. The
+ // tree will be empty after removing the descriptor.
+ //
+ // Pictorially:
+ //
+ // R R
+ // | ->
+ // X
+ //
+
+ *Root = NULL;
+ }
+ } else if (LeftChild) {
+ if (RightChild) {
+
+ //
+ // The descriptor has both a left child and a right child.
+ //
+
+ if (LeftChild->RightChild) {
+
+ //
+ // The left child has a right child. Make the right most
+ // descendent of the right child of the left child the new
+ // root of the subtree.
+ //
+ // Pictorially:
+ //
+ // P P
+ // / \
+ // X X
+ // / \ / \
+ // A B or A B
+ // \ \
+ // . .
+ // \ \
+ // Z Z
+ //
+ // |
+ // v
+ //
+ // P P
+ // / \
+ // Z Z
+ // / \ / \
+ // A B or A B
+ // \ \
+ // . .
+ //
+
+ SplayNode = LeftChild->RightChild;
+ while (SplayNode->RightChild) {
+ SplayNode = SplayNode->RightChild;
+ }
+ SplayNode->Parent->RightChild = SplayNode->LeftChild;
+ if (SplayNode->LeftChild) {
+ SplayNode->LeftChild->Parent = SplayNode->Parent;
+ }
+ SplayNode->Parent = Node->Parent;
+ if (Node == Node->Parent->LeftChild) {
+ Node->Parent->LeftChild = SplayNode;
+ } else {
+ Node->Parent->RightChild = SplayNode;
+ }
+ LeftChild->Parent = SplayNode;
+ RightChild->Parent = SplayNode;
+ SplayNode->LeftChild = LeftChild;
+ SplayNode->RightChild = RightChild;
+ } else if (RightChild->LeftChild) {
+
+ //
+ // The right child has a left child. Make the left most
+ // descendent of the left child of the right child the
+ // new root of the subtree.
+ //
+ // Pictorially:
+ //
+ // P P
+ // / \
+ // X X
+ // / \ / \
+ // A B or A B
+ // / /
+ // . .
+ // / /
+ // Z Z
+ //
+ // |
+ // v
+ //
+ // P P
+ // / \
+ // Z Z
+ // / \ / \
+ // A B or A B
+ // / /
+ // . .
+ //
+
+ SplayNode = RightChild->LeftChild;
+ while (SplayNode->LeftChild) {
+ SplayNode = SplayNode->LeftChild;
+ }
+ SplayNode->Parent->LeftChild = SplayNode->RightChild;
+ if (SplayNode->RightChild) {
+ SplayNode->RightChild->Parent = SplayNode->Parent;
+ }
+ SplayNode->Parent = Node->Parent;
+ if (Node == Node->Parent->LeftChild) {
+ Node->Parent->LeftChild = SplayNode;
+ } else {
+ Node->Parent->RightChild = SplayNode;
+ }
+ LeftChild->Parent = SplayNode;
+ RightChild->Parent = SplayNode;
+ SplayNode->LeftChild = LeftChild;
+ SplayNode->RightChild = RightChild;
+ } else {
+
+ //
+ // The left child of the descriptor does not have a right child,
+ // and the right child of the descriptor does node have a left
+ // child. Make the left child of the descriptor the new root of
+ // the subtree.
+ //
+ // Pictorially:
+ //
+ // P P
+ // / \
+ // X X
+ // / \ / \
+ // A B or A B
+ // / /
+ // . .
+ //
+ // |
+ // v
+ //
+ // P P
+ // / \
+ // A A
+ // / \ / \
+ // . B or . B
+ // / /
+ //
+
+ SplayNode = LeftChild;
+ SplayNode->Parent = Node->Parent;
+ if (Node == Node->Parent->LeftChild) {
+ Node->Parent->LeftChild = SplayNode;
+ } else {
+ Node->Parent->RightChild = SplayNode;
+ }
+ SplayNode->RightChild = RightChild;
+ RightChild->Parent = SplayNode;
+ }
+ } else {
+
+ //
+ // The descriptor has a left child, but does not have a right child.
+ // Make the left child the new root of the subtree.
+ //
+ // Pictorially:
+ //
+ // P P
+ // / \
+ // X or X
+ // / /
+ // A A
+ //
+ // |
+ // v
+ //
+ // P P
+ // / \
+ // A A
+ //
+
+ LeftChild->Parent = Node->Parent;
+ if (Node == Node->Parent->LeftChild) {
+ Node->Parent->LeftChild = LeftChild;
+ } else {
+ Node->Parent->RightChild = LeftChild;
+ }
+ }
+ } else if (RightChild) {
+
+ //
+ // descriptor has a right child, but does not have a left child. Make
+ // the right child the new root of the subtree.
+ //
+ // Pictorially:
+ //
+ // P P
+ // / \
+ // X or X
+ // \ \
+ // A A
+ //
+ // |
+ // v
+ //
+ // P P
+ // / \
+ // A A
+ //
+
+ RightChild->Parent = Node->Parent;
+ if (Node == Node->Parent->LeftChild) {
+ Node->Parent->LeftChild = RightChild;
+ } else {
+ Node->Parent->RightChild = RightChild;
+ }
+ } else {
+
+ //
+ // The descriptor has neither a left child nor a right child. Delete
+ // the descriptor from the tree and adjust its parent right or left
+ // link.
+ //
+ // Pictorially:
+ //
+ // P P
+ // / \
+ // X or X
+ //
+ // |
+ // v
+ //
+ // P P
+ //
+
+ if (Node == Node->Parent->LeftChild) {
+ Node->Parent->LeftChild = (PMMADDRESS_NODE)NULL;
+ } else {
+ Node->Parent->RightChild = (PMMADDRESS_NODE)NULL;
+ }
+ }
+ return;
+}
+
+PMMADDRESS_NODE
+FASTCALL
+MiLocateAddressInTree (
+ IN PVOID VirtualAddress,
+ IN PMMADDRESS_NODE *Root
+ )
+
+/*++
+
+Routine Description:
+
+ The function locates the virtual address descriptor which describes
+ a given address.
+
+Arguments:
+
+ VirtualAddress - Supplies the virtual address to locate a descriptor
+ for.
+
+Return Value:
+
+ Returns a pointer to the virtual address descriptor which contains
+ the supplied virtual address or NULL if none was located.
+
+--*/
+
+{
+
+ PMMADDRESS_NODE Parent;
+ ULONG Level = 0;
+
+ Parent = *Root;
+
+ for (;;) {
+
+ if (Parent == (PMMADDRESS_NODE)NULL) {
+ return (PMMADDRESS_NODE)NULL;
+ }
+
+ if (Level == 20) {
+
+ //
+ // There are 20 nodes above this point, reorder the
+ // tree with this node as the root.
+ //
+
+ MiReorderTree(Parent, Root);
+ }
+
+ if (VirtualAddress < Parent->StartingVa) {
+ Parent = Parent->LeftChild;
+ Level += 1;
+
+ } else if (VirtualAddress > Parent->EndingVa) {
+ Parent = Parent->RightChild;
+ Level += 1;
+
+ } else {
+
+ //
+ // The virtual address is within the start and end range.
+ //
+
+ return Parent;
+ }
+ }
+}
+
+PMMADDRESS_NODE
+MiCheckForConflictingNode (
+ IN PVOID StartingAddress,
+ IN PVOID EndingAddress,
+ IN PMMADDRESS_NODE Root
+ )
+
+/*++
+
+Routine Description:
+
+ The function determines if any addresses between a given starting and
+ ending address is contained within a virtual address descriptor.
+
+Arguments:
+
+ StartingAddress - Supplies the virtual address to locate a containing
+ descriptor.
+
+ EndingAddress - Supplies the virtual address to locate a containing
+ descriptor.
+
+Return Value:
+
+ Returns a pointer to the first conflicting virtual address descriptor
+ if one is found, othersize a NULL value is returned.
+
+--*/
+
+{
+
+ PMMADDRESS_NODE Node;
+
+ Node = Root;
+
+ for (;;) {
+
+ if (Node == (PMMADDRESS_NODE)NULL) {
+ return (PMMADDRESS_NODE)NULL;
+ }
+
+ if (StartingAddress > Node->EndingVa) {
+ Node = Node->RightChild;
+
+ } else if (EndingAddress < Node->StartingVa) {
+ Node = Node->LeftChild;
+
+ } else {
+
+ //
+ // The starting address is less than or equal to the end VA
+ // and the ending address is greater than or equal to the
+ // start va. Return this node.
+ //
+
+ return Node;
+ }
+ }
+}
+
+PVOID
+MiFindEmptyAddressRangeInTree (
+ IN ULONG SizeOfRange,
+ IN ULONG Alignment,
+ IN PMMADDRESS_NODE Root,
+ OUT PMMADDRESS_NODE *PreviousVad
+ )
+
+/*++
+
+Routine Description:
+
+ The function examines the virtual address descriptors to locate
+ an unused range of the specified size and returns the starting
+ address of the range.
+
+Arguments:
+
+ SizeOfRange - Supplies the size in bytes of the range to locate.
+
+ Alignment - Supplies the alignment for the address. Must be
+ a power of 2 and greater than the page_size.
+
+ Root - Supplies the root of the tree to search through.
+
+ PreviousVad - Supplies the Vad which is before this the found
+ address range.
+
+Return Value:
+
+ Returns the starting address of a suitable range.
+
+--*/
+
+{
+
+ PMMADDRESS_NODE Node;
+ PMMADDRESS_NODE NextNode;
+
+ //
+ // Locate the Node with the lowest starting address.
+ //
+
+ Node = Root;
+
+ if (Node == (PMMADDRESS_NODE)NULL) {
+ return MM_LOWEST_USER_ADDRESS;
+ }
+ while (Node->LeftChild != (PMMADDRESS_NODE)NULL) {
+ Node = Node->LeftChild;
+ }
+
+ //
+ // Check to see if a range exists between the lowest address VAD
+ // and lowest user address.
+ //
+
+ if (Node->StartingVa > MM_LOWEST_USER_ADDRESS) {
+ if ( SizeOfRange <
+ ((ULONG)Node->StartingVa - (ULONG)MM_LOWEST_USER_ADDRESS )) {
+
+ *PreviousVad = NULL;
+ return MM_LOWEST_USER_ADDRESS;
+ }
+ }
+
+ for (;;) {
+
+ NextNode = MiGetNextNode (Node);
+
+ if (NextNode != (PMMADDRESS_NODE)NULL) {
+ if (SizeOfRange <=
+ ((ULONG)NextNode->StartingVa -
+ (ULONG)MI_ROUND_TO_SIZE(Node->EndingVa, Alignment))) {
+
+ //
+ // Check to ensure that the ending address aligned upwards
+ // is not greater than the starting address.
+ //
+
+ if ((ULONG)NextNode->StartingVa >
+ (ULONG)MI_ROUND_TO_SIZE(Node->EndingVa,Alignment)) {
+
+ *PreviousVad = Node;
+ return (PMMADDRESS_NODE)MI_ROUND_TO_SIZE(Node->EndingVa,
+ Alignment);
+ }
+ }
+
+ } else {
+
+ //
+ // No more descriptors, check to see if this fits into the remainder
+ // of the address space.
+ //
+
+ if ((((ULONG)Node->EndingVa + X64K) <
+ (ULONG)MM_HIGHEST_VAD_ADDRESS)
+ &&
+ (SizeOfRange <=
+ ((ULONG)MM_HIGHEST_VAD_ADDRESS -
+ (ULONG)MI_ROUND_TO_SIZE(Node->EndingVa, Alignment)))) {
+
+ *PreviousVad = Node;
+ return (PMMADDRESS_NODE)MI_ROUND_TO_SIZE(Node->EndingVa,
+ Alignment);
+ } else {
+ ExRaiseStatus (STATUS_NO_MEMORY);
+ }
+ }
+ Node = NextNode;
+ }
+}
+
+PVOID
+MiFindEmptyAddressRangeDownTree (
+ IN ULONG SizeOfRange,
+ IN PVOID HighestAddressToEndAt,
+ IN ULONG Alignment,
+ IN PMMADDRESS_NODE Root
+ )
+
+/*++
+
+Routine Description:
+
+ The function examines the virtual address descriptors to locate
+ an unused range of the specified size and returns the starting
+ address of the range. The function examines from the high
+ addresses down and ensures that starting address is less than
+ the specified address.
+
+Arguments:
+
+ SizeOfRange - Supplies the size in bytes of the range to locate.
+
+ HighestAddressToEndAt - Supplies the virtual address that limits
+ the value of the ending address. The ending
+ address of the located range must be less
+ than this address.
+
+ Alignment - Supplies the alignment for the address. Must be
+ a power of 2 and greater than the page_size.
+
+ Root - Supplies the root of the tree to search through.
+
+Return Value:
+
+ Returns the starting address of a suitable range.
+
+--*/
+
+{
+ PMMADDRESS_NODE Node;
+ PMMADDRESS_NODE PreviousNode;
+ ULONG AlignedEndingVa;
+ PVOID OptimalStart;
+
+ ASSERT (HighestAddressToEndAt != NULL);
+ ASSERT (HighestAddressToEndAt <= (PVOID)((ULONG)MM_HIGHEST_VAD_ADDRESS + 1));
+
+ //
+ // Locate the Node with the highest starting address.
+ //
+
+ OptimalStart = (PVOID)(MI_ALIGN_TO_SIZE(
+ (((ULONG)HighestAddressToEndAt + 1) - SizeOfRange),
+ Alignment));
+ Node = Root;
+
+
+ if (Node == (PMMADDRESS_NODE)NULL) {
+
+ //
+ // The tree is empty, any range is okay.
+ //
+
+ return (PMMADDRESS_NODE)(OptimalStart);
+ }
+
+ //
+ // See if an empty slot exists to hold this range, locate the largest
+ // element in the tree.
+ //
+
+ while (Node->RightChild != (PMMADDRESS_NODE)NULL) {
+ Node = Node->RightChild;
+ }
+
+ //
+ // Check to see if a range exists between the highest address VAD
+ // and the highest address to end at.
+ //
+
+ AlignedEndingVa = (ULONG)MI_ROUND_TO_SIZE(Node->EndingVa, Alignment);
+
+ if (AlignedEndingVa < (ULONG)HighestAddressToEndAt) {
+
+ if ( SizeOfRange < ((ULONG)HighestAddressToEndAt - AlignedEndingVa)) {
+
+ return (PMMADDRESS_NODE)(MI_ALIGN_TO_SIZE(
+ ((ULONG)HighestAddressToEndAt - SizeOfRange),
+ Alignment));
+ }
+ }
+
+ //
+ // Walk the tree backwards looking for a fit.
+ //
+
+ for (;;) {
+
+ PreviousNode = MiGetPreviousNode (Node);
+
+ if (PreviousNode != (PMMADDRESS_NODE)NULL) {
+
+ //
+ // Is the ending Va below the top of the address to end at.
+ //
+
+ if (PreviousNode->EndingVa < OptimalStart) {
+ if (SizeOfRange <=
+ ((ULONG)Node->StartingVa -
+ (ULONG)MI_ROUND_TO_SIZE(PreviousNode->EndingVa,
+ Alignment))) {
+
+ //
+ // See if the optimal start will fit between these
+ // two VADs.
+ //
+
+ if ((OptimalStart > PreviousNode->EndingVa) &&
+ (HighestAddressToEndAt < Node->StartingVa)) {
+ return (PMMADDRESS_NODE)(OptimalStart);
+ }
+
+ //
+ // Check to ensure that the ending address aligned upwards
+ // is not greater than the starting address.
+ //
+
+ if ((ULONG)Node->StartingVa >
+ (ULONG)MI_ROUND_TO_SIZE(PreviousNode->EndingVa,
+ Alignment)) {
+
+ return (PMMADDRESS_NODE)MI_ALIGN_TO_SIZE(
+ (ULONG)Node->StartingVa - SizeOfRange,
+ Alignment);
+ }
+ }
+ }
+ } else {
+
+ //
+ // No more descriptors, check to see if this fits into the remainder
+ // of the address space.
+ //
+
+ if (Node->StartingVa > MM_LOWEST_USER_ADDRESS) {
+ if (SizeOfRange <=
+ ((ULONG)Node->StartingVa - (ULONG)MM_LOWEST_USER_ADDRESS)) {
+
+ //
+ // See if the optimal start will fit between these
+ // two VADs.
+ //
+
+ if (HighestAddressToEndAt < Node->StartingVa) {
+ return (PMMADDRESS_NODE)(OptimalStart);
+ }
+
+ return (PMMADDRESS_NODE)MI_ALIGN_TO_SIZE(
+ (ULONG)Node->StartingVa - SizeOfRange,
+ Alignment);
+ }
+ } else {
+ ExRaiseStatus (STATUS_NO_MEMORY);
+ }
+ }
+ Node = PreviousNode;
+ }
+}
+
+
+#if DBG
+
+VOID
+NodeTreeWalk (
+ PMMADDRESS_NODE Start
+ )
+
+{
+ if (Start == (PMMADDRESS_NODE)NULL) {
+ return;
+ }
+
+ NodeTreeWalk(Start->LeftChild);
+
+ DbgPrint("Node at 0x%lx start 0x%lx end 0x%lx \n",
+ (ULONG)Start, (ULONG)Start->StartingVa,
+ (ULONG)Start->EndingVa);
+
+
+ NodeTreeWalk(Start->RightChild);
+ return;
+}
+#endif //DBG