mirror of
https://github.com/reactos/reactos.git
synced 2025-07-24 14:23:41 +00:00
[RTL]
Add some temp AVL debugging code: In case an AVL table gets unbalanced, dump the table and a backtrace. svn path=/trunk/; revision=56249
This commit is contained in:
parent
6fcb5fd53c
commit
98a00b314d
1 changed files with 78 additions and 24 deletions
|
@ -140,7 +140,7 @@ RtlpRebalanceAvlTreeNode(IN PRTL_BALANCED_LINKS Node)
|
||||||
{
|
{
|
||||||
/* This performs the rotation described in Knuth A8-A10 for Case 1 */
|
/* This performs the rotation described in Knuth A8-A10 for Case 1 */
|
||||||
RtlPromoteAvlTreeNode(ChildNode);
|
RtlPromoteAvlTreeNode(ChildNode);
|
||||||
|
|
||||||
/* The nodes are now balanced */
|
/* The nodes are now balanced */
|
||||||
RtlSetBalance(ChildNode, RtlBalancedAvlTree);
|
RtlSetBalance(ChildNode, RtlBalancedAvlTree);
|
||||||
RtlSetBalance(Node, RtlBalancedAvlTree);
|
RtlSetBalance(Node, RtlBalancedAvlTree);
|
||||||
|
@ -189,20 +189,60 @@ RtlpRebalanceAvlTreeNode(IN PRTL_BALANCED_LINKS Node)
|
||||||
RtlSetBalance(SubChildNode, RtlBalancedAvlTree);
|
RtlSetBalance(SubChildNode, RtlBalancedAvlTree);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The case that remains is that the child was already balanced, so this is
|
* The case that remains is that the child was already balanced, so this is
|
||||||
* This is the rotation required for Case 3 in Knuth A8-A10
|
* This is the rotation required for Case 3 in Knuth A8-A10
|
||||||
*/
|
*/
|
||||||
RtlPromoteAvlTreeNode(ChildNode);
|
RtlPromoteAvlTreeNode(ChildNode);
|
||||||
|
|
||||||
/* Now the child has the opposite weight of the node */
|
/* Now the child has the opposite weight of the node */
|
||||||
RtlSetBalance(ChildNode, -Balance);
|
RtlSetBalance(ChildNode, -Balance);
|
||||||
|
|
||||||
/* This only happens on deletion, so we return TRUE to terminate the delete */
|
/* This only happens on deletion, so we return TRUE to terminate the delete */
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FORCEINLINE
|
||||||
|
Indent(ULONG Level)
|
||||||
|
{
|
||||||
|
while (Level--)
|
||||||
|
{
|
||||||
|
DbgPrint(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
FORCEINLINE
|
||||||
|
DbgDumpAvlNodes(
|
||||||
|
PRTL_BALANCED_LINKS Node,
|
||||||
|
ULONG Level)
|
||||||
|
{
|
||||||
|
#ifdef PRTL_BALANCED_LINKS
|
||||||
|
if (Level == 0)
|
||||||
|
{
|
||||||
|
DbgPrint("++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
|
||||||
|
DbgPrint("Root = %p\n", Node);
|
||||||
|
}
|
||||||
|
|
||||||
|
Indent(Level+1); DbgPrint("LetChid = %p", Node->LeftChild);
|
||||||
|
if (Node->LeftChild)
|
||||||
|
{
|
||||||
|
DbgPrint("(%lx, %lx)\n", Node->LeftChild->StartingVpn,Node->LeftChild->EndingVpn);
|
||||||
|
DbgDumpAvlNodes(Node->LeftChild, Level+1);
|
||||||
|
}
|
||||||
|
else DbgPrint("\n");
|
||||||
|
Indent(Level+1); DbgPrint("RightChild = %p\n", Node->RightChild);
|
||||||
|
if (Node->RightChild)
|
||||||
|
{
|
||||||
|
DbgPrint("(%lx, %lx)\n", Node->RightChild->StartingVpn,Node->RightChild->EndingVpn);
|
||||||
|
DbgDumpAvlNodes(Node->RightChild, Level+1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
FORCEINLINE
|
FORCEINLINE
|
||||||
RtlpInsertAvlTreeNode(IN PRTL_AVL_TABLE Table,
|
RtlpInsertAvlTreeNode(IN PRTL_AVL_TABLE Table,
|
||||||
|
@ -211,7 +251,7 @@ RtlpInsertAvlTreeNode(IN PRTL_AVL_TABLE Table,
|
||||||
IN OUT TABLE_SEARCH_RESULT SearchResult)
|
IN OUT TABLE_SEARCH_RESULT SearchResult)
|
||||||
{
|
{
|
||||||
CHAR Balance;
|
CHAR Balance;
|
||||||
|
|
||||||
/* Initialize the new inserted element */
|
/* Initialize the new inserted element */
|
||||||
MI_ASSERT(SearchResult != TableFoundNode);
|
MI_ASSERT(SearchResult != TableFoundNode);
|
||||||
NewNode->LeftChild = NewNode->RightChild = NULL;
|
NewNode->LeftChild = NewNode->RightChild = NULL;
|
||||||
|
@ -225,8 +265,15 @@ RtlpInsertAvlTreeNode(IN PRTL_AVL_TABLE Table,
|
||||||
/* This is the new root node */
|
/* This is the new root node */
|
||||||
RtlInsertAsRightChildAvl(&Table->BalancedRoot, NewNode);
|
RtlInsertAsRightChildAvl(&Table->BalancedRoot, NewNode);
|
||||||
//MI_ASSERT(RtlBalance(NewNode) == RtlBalancedAvlTree);
|
//MI_ASSERT(RtlBalance(NewNode) == RtlBalancedAvlTree);
|
||||||
if (RtlBalance(NewNode) != RtlBalancedAvlTree) DPRINT1("Warning: Root node unbalanced?\n");
|
if (RtlBalance(NewNode) != RtlBalancedAvlTree)
|
||||||
|
{
|
||||||
|
DPRINT1("Warning: Root node unbalanced?\n");
|
||||||
|
DbgDumpAvlNodes(&Table->BalancedRoot, 0);
|
||||||
|
#ifdef PRTL_BALANCED_LINKS
|
||||||
|
KeRosDumpStackFrames(NULL, 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/* On AVL trees, we also update the depth */
|
/* On AVL trees, we also update the depth */
|
||||||
ASSERT(Table->DepthOfTree == 0);
|
ASSERT(Table->DepthOfTree == 0);
|
||||||
Table->DepthOfTree = 1;
|
Table->DepthOfTree = 1;
|
||||||
|
@ -245,7 +292,14 @@ RtlpInsertAvlTreeNode(IN PRTL_AVL_TABLE Table,
|
||||||
|
|
||||||
/* Little cheat to save on loop processing, taken from Timo */
|
/* Little cheat to save on loop processing, taken from Timo */
|
||||||
//MI_ASSERT(RtlBalance(NewNode) == RtlBalancedAvlTree);
|
//MI_ASSERT(RtlBalance(NewNode) == RtlBalancedAvlTree);
|
||||||
if (RtlBalance(NewNode) != RtlBalancedAvlTree) DPRINT1("Warning: Root node unbalanced?\n");
|
if (RtlBalance(NewNode) != RtlBalancedAvlTree)
|
||||||
|
{
|
||||||
|
DPRINT1("Warning: Root node unbalanced?\n");
|
||||||
|
DbgDumpAvlNodes(&Table->BalancedRoot, 0);
|
||||||
|
#ifdef PRTL_BALANCED_LINKS
|
||||||
|
KeRosDumpStackFrames(NULL, 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
RtlSetBalance(&Table->BalancedRoot, RtlLeftHeavyAvlTree);
|
RtlSetBalance(&Table->BalancedRoot, RtlLeftHeavyAvlTree);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -258,13 +312,13 @@ RtlpInsertAvlTreeNode(IN PRTL_AVL_TABLE Table,
|
||||||
{
|
{
|
||||||
/* Calculate which side to balance on */
|
/* Calculate which side to balance on */
|
||||||
Balance = RtlIsLeftChildAvl(NewNode) ? RtlLeftHeavyAvlTree : RtlRightHeavyAvlTree;
|
Balance = RtlIsLeftChildAvl(NewNode) ? RtlLeftHeavyAvlTree : RtlRightHeavyAvlTree;
|
||||||
|
|
||||||
/* Check if the parent node was balanced */
|
/* Check if the parent node was balanced */
|
||||||
if (RtlBalance(NodeOrParent) == RtlBalancedAvlTree)
|
if (RtlBalance(NodeOrParent) == RtlBalancedAvlTree)
|
||||||
{
|
{
|
||||||
/* It's not balanced anymore (heavy on one side) */
|
/* It's not balanced anymore (heavy on one side) */
|
||||||
RtlSetBalance(NodeOrParent, Balance);
|
RtlSetBalance(NodeOrParent, Balance);
|
||||||
|
|
||||||
/* Move up */
|
/* Move up */
|
||||||
NewNode = NodeOrParent;
|
NewNode = NodeOrParent;
|
||||||
NodeOrParent = RtlParentAvl(NodeOrParent);
|
NodeOrParent = RtlParentAvl(NodeOrParent);
|
||||||
|
@ -273,14 +327,14 @@ RtlpInsertAvlTreeNode(IN PRTL_AVL_TABLE Table,
|
||||||
{
|
{
|
||||||
/* The parent's balance is opposite, so the tree is balanced now */
|
/* The parent's balance is opposite, so the tree is balanced now */
|
||||||
RtlSetBalance(NodeOrParent, RtlBalancedAvlTree);
|
RtlSetBalance(NodeOrParent, RtlBalancedAvlTree);
|
||||||
|
|
||||||
/* Check if this is the root (the cheat applied earlier gets us here) */
|
/* Check if this is the root (the cheat applied earlier gets us here) */
|
||||||
if (RtlBalance(&Table->BalancedRoot) == RtlBalancedAvlTree)
|
if (RtlBalance(&Table->BalancedRoot) == RtlBalancedAvlTree)
|
||||||
{
|
{
|
||||||
/* The depth has thus increased */
|
/* The depth has thus increased */
|
||||||
Table->DepthOfTree++;
|
Table->DepthOfTree++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We reached the root or a balanced node, so we're done */
|
/* We reached the root or a balanced node, so we're done */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -301,10 +355,10 @@ RtlpDeleteAvlTreeNode(IN PRTL_AVL_TABLE Table,
|
||||||
PRTL_BALANCED_LINKS DeleteNode = NULL, ParentNode;
|
PRTL_BALANCED_LINKS DeleteNode = NULL, ParentNode;
|
||||||
PRTL_BALANCED_LINKS *Node1, *Node2;
|
PRTL_BALANCED_LINKS *Node1, *Node2;
|
||||||
CHAR Balance;
|
CHAR Balance;
|
||||||
|
|
||||||
/* Take one of the children if possible */
|
/* Take one of the children if possible */
|
||||||
if (!(RtlLeftChildAvl(Node)) || !(RtlRightChildAvl(Node))) DeleteNode = Node;
|
if (!(RtlLeftChildAvl(Node)) || !(RtlRightChildAvl(Node))) DeleteNode = Node;
|
||||||
|
|
||||||
/* Otherwise, check if one side is longer */
|
/* Otherwise, check if one side is longer */
|
||||||
if (!(DeleteNode) && (RtlBalance(Node) >= RtlBalancedAvlTree))
|
if (!(DeleteNode) && (RtlBalance(Node) >= RtlBalancedAvlTree))
|
||||||
{
|
{
|
||||||
|
@ -316,34 +370,34 @@ RtlpDeleteAvlTreeNode(IN PRTL_AVL_TABLE Table,
|
||||||
{
|
{
|
||||||
/* Pick the predecessor which will be the longest side in this case */
|
/* Pick the predecessor which will be the longest side in this case */
|
||||||
DeleteNode = RtlLeftChildAvl(Node);
|
DeleteNode = RtlLeftChildAvl(Node);
|
||||||
while (RtlRightChildAvl(DeleteNode)) DeleteNode = RtlRightChildAvl(DeleteNode);
|
while (RtlRightChildAvl(DeleteNode)) DeleteNode = RtlRightChildAvl(DeleteNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the parent node */
|
/* Get the parent node */
|
||||||
ParentNode = RtlParentAvl(DeleteNode);
|
ParentNode = RtlParentAvl(DeleteNode);
|
||||||
DPRINT("Parent: %p\n", ParentNode);
|
DPRINT("Parent: %p\n", ParentNode);
|
||||||
|
|
||||||
/* Pick which now to use based on whether or not we have a left child */
|
/* Pick which now to use based on whether or not we have a left child */
|
||||||
Node1 = RtlLeftChildAvl(DeleteNode) ? &DeleteNode->LeftChild : &DeleteNode->RightChild;
|
Node1 = RtlLeftChildAvl(DeleteNode) ? &DeleteNode->LeftChild : &DeleteNode->RightChild;
|
||||||
DPRINT("Node 1: %p %p\n", Node1, *Node1);
|
DPRINT("Node 1: %p %p\n", Node1, *Node1);
|
||||||
|
|
||||||
/* Pick which node to swap based on if we're already a left child or not */
|
/* Pick which node to swap based on if we're already a left child or not */
|
||||||
Node2 = RtlIsLeftChildAvl(DeleteNode) ? &ParentNode->LeftChild : &ParentNode->RightChild;
|
Node2 = RtlIsLeftChildAvl(DeleteNode) ? &ParentNode->LeftChild : &ParentNode->RightChild;
|
||||||
DPRINT("Node 2: %p %p\n", Node2, *Node2);
|
DPRINT("Node 2: %p %p\n", Node2, *Node2);
|
||||||
|
|
||||||
/* Pick the correct balance depending on which side will get heavier */
|
/* Pick the correct balance depending on which side will get heavier */
|
||||||
Balance = RtlIsLeftChildAvl(DeleteNode) ? RtlLeftHeavyAvlTree : RtlRightHeavyAvlTree;
|
Balance = RtlIsLeftChildAvl(DeleteNode) ? RtlLeftHeavyAvlTree : RtlRightHeavyAvlTree;
|
||||||
DPRINT("Balance: %lx\n", Balance);
|
DPRINT("Balance: %lx\n", Balance);
|
||||||
|
|
||||||
/* Swap the children nodes, making one side heavier */
|
/* Swap the children nodes, making one side heavier */
|
||||||
*Node2 = *Node1;
|
*Node2 = *Node1;
|
||||||
|
|
||||||
/* If the node has a child now, update its parent */
|
/* If the node has a child now, update its parent */
|
||||||
if (*Node1) RtlSetParent(*Node1, ParentNode);
|
if (*Node1) RtlSetParent(*Node1, ParentNode);
|
||||||
|
|
||||||
/* Assume balanced root for loop optimization */
|
/* Assume balanced root for loop optimization */
|
||||||
RtlSetBalance(&Table->BalancedRoot, RtlBalancedAvlTree);
|
RtlSetBalance(&Table->BalancedRoot, RtlBalancedAvlTree);
|
||||||
|
|
||||||
/* Loop up the tree by parents */
|
/* Loop up the tree by parents */
|
||||||
while (TRUE)
|
while (TRUE)
|
||||||
{
|
{
|
||||||
|
@ -374,7 +428,7 @@ RtlpDeleteAvlTreeNode(IN PRTL_AVL_TABLE Table,
|
||||||
/* Choose which balance factor to use based on which side we're on */
|
/* Choose which balance factor to use based on which side we're on */
|
||||||
Balance = RtlIsRightChild(ParentNode) ?
|
Balance = RtlIsRightChild(ParentNode) ?
|
||||||
RtlRightHeavyAvlTree : RtlLeftHeavyAvlTree;
|
RtlRightHeavyAvlTree : RtlLeftHeavyAvlTree;
|
||||||
|
|
||||||
/* Iterate up the tree */
|
/* Iterate up the tree */
|
||||||
ParentNode = RtlParentAvl(ParentNode);
|
ParentNode = RtlParentAvl(ParentNode);
|
||||||
}
|
}
|
||||||
|
@ -384,7 +438,7 @@ RtlpDeleteAvlTreeNode(IN PRTL_AVL_TABLE Table,
|
||||||
|
|
||||||
/* Copy the deleted node itself */
|
/* Copy the deleted node itself */
|
||||||
RtlpCopyAvlNodeData(DeleteNode, Node);
|
RtlpCopyAvlNodeData(DeleteNode, Node);
|
||||||
|
|
||||||
/* Pick the right node to unlink */
|
/* Pick the right node to unlink */
|
||||||
Node1 = RtlIsLeftChildAvl(Node) ?
|
Node1 = RtlIsLeftChildAvl(Node) ?
|
||||||
&(RtlParentAvl(DeleteNode))->LeftChild : &(RtlParentAvl(DeleteNode))->RightChild;
|
&(RtlParentAvl(DeleteNode))->LeftChild : &(RtlParentAvl(DeleteNode))->RightChild;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue