Author: tkreuzer
Date: Tue Mar 27 17:19:53 2012
New Revision: 56249
URL:
http://svn.reactos.org/svn/reactos?rev=56249&view=rev
Log:
[RTL]
Add some temp AVL debugging code: In case an AVL table gets unbalanced, dump the table and
a backtrace.
Modified:
trunk/reactos/lib/rtl/avlsupp.c
Modified: trunk/reactos/lib/rtl/avlsupp.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/avlsupp.c?rev=5624…
==============================================================================
--- trunk/reactos/lib/rtl/avlsupp.c [iso-8859-1] (original)
+++ trunk/reactos/lib/rtl/avlsupp.c [iso-8859-1] Tue Mar 27 17:19:53 2012
@@ -140,7 +140,7 @@
{
/* This performs the rotation described in Knuth A8-A10 for Case 1 */
RtlPromoteAvlTreeNode(ChildNode);
-
+
/* The nodes are now balanced */
RtlSetBalance(ChildNode, RtlBalancedAvlTree);
RtlSetBalance(Node, RtlBalancedAvlTree);
@@ -189,19 +189,59 @@
RtlSetBalance(SubChildNode, RtlBalancedAvlTree);
return FALSE;
}
-
+
/*
* 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
*/
RtlPromoteAvlTreeNode(ChildNode);
-
+
/* Now the child has the opposite weight of the node */
RtlSetBalance(ChildNode, -Balance);
-
+
/* This only happens on deletion, so we return TRUE to terminate the delete */
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
FORCEINLINE
@@ -211,7 +251,7 @@
IN OUT TABLE_SEARCH_RESULT SearchResult)
{
CHAR Balance;
-
+
/* Initialize the new inserted element */
MI_ASSERT(SearchResult != TableFoundNode);
NewNode->LeftChild = NewNode->RightChild = NULL;
@@ -225,8 +265,15 @@
/* This is the new root node */
RtlInsertAsRightChildAvl(&Table->BalancedRoot, NewNode);
//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 */
ASSERT(Table->DepthOfTree == 0);
Table->DepthOfTree = 1;
@@ -245,7 +292,14 @@
/* Little cheat to save on loop processing, taken from Timo */
//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);
/*
@@ -258,13 +312,13 @@
{
/* Calculate which side to balance on */
Balance = RtlIsLeftChildAvl(NewNode) ? RtlLeftHeavyAvlTree :
RtlRightHeavyAvlTree;
-
+
/* Check if the parent node was balanced */
if (RtlBalance(NodeOrParent) == RtlBalancedAvlTree)
{
/* It's not balanced anymore (heavy on one side) */
RtlSetBalance(NodeOrParent, Balance);
-
+
/* Move up */
NewNode = NodeOrParent;
NodeOrParent = RtlParentAvl(NodeOrParent);
@@ -273,14 +327,14 @@
{
/* The parent's balance is opposite, so the tree is balanced now */
RtlSetBalance(NodeOrParent, RtlBalancedAvlTree);
-
+
/* Check if this is the root (the cheat applied earlier gets us here) */
if (RtlBalance(&Table->BalancedRoot) == RtlBalancedAvlTree)
{
/* The depth has thus increased */
Table->DepthOfTree++;
}
-
+
/* We reached the root or a balanced node, so we're done */
break;
}
@@ -301,10 +355,10 @@
PRTL_BALANCED_LINKS DeleteNode = NULL, ParentNode;
PRTL_BALANCED_LINKS *Node1, *Node2;
CHAR Balance;
-
+
/* Take one of the children if possible */
if (!(RtlLeftChildAvl(Node)) || !(RtlRightChildAvl(Node))) DeleteNode = Node;
-
+
/* Otherwise, check if one side is longer */
if (!(DeleteNode) && (RtlBalance(Node) >= RtlBalancedAvlTree))
{
@@ -316,34 +370,34 @@
{
/* Pick the predecessor which will be the longest side in this case */
DeleteNode = RtlLeftChildAvl(Node);
- while (RtlRightChildAvl(DeleteNode)) DeleteNode = RtlRightChildAvl(DeleteNode);
- }
-
+ while (RtlRightChildAvl(DeleteNode)) DeleteNode = RtlRightChildAvl(DeleteNode);
+ }
+
/* Get the parent node */
ParentNode = RtlParentAvl(DeleteNode);
DPRINT("Parent: %p\n", ParentNode);
-
+
/* Pick which now to use based on whether or not we have a left child */
Node1 = RtlLeftChildAvl(DeleteNode) ? &DeleteNode->LeftChild :
&DeleteNode->RightChild;
DPRINT("Node 1: %p %p\n", Node1, *Node1);
-
+
/* Pick which node to swap based on if we're already a left child or not */
Node2 = RtlIsLeftChildAvl(DeleteNode) ? &ParentNode->LeftChild :
&ParentNode->RightChild;
DPRINT("Node 2: %p %p\n", Node2, *Node2);
-
+
/* Pick the correct balance depending on which side will get heavier */
Balance = RtlIsLeftChildAvl(DeleteNode) ? RtlLeftHeavyAvlTree :
RtlRightHeavyAvlTree;
DPRINT("Balance: %lx\n", Balance);
-
+
/* Swap the children nodes, making one side heavier */
*Node2 = *Node1;
-
+
/* If the node has a child now, update its parent */
if (*Node1) RtlSetParent(*Node1, ParentNode);
/* Assume balanced root for loop optimization */
RtlSetBalance(&Table->BalancedRoot, RtlBalancedAvlTree);
-
+
/* Loop up the tree by parents */
while (TRUE)
{
@@ -374,7 +428,7 @@
/* Choose which balance factor to use based on which side we're on */
Balance = RtlIsRightChild(ParentNode) ?
RtlRightHeavyAvlTree : RtlLeftHeavyAvlTree;
-
+
/* Iterate up the tree */
ParentNode = RtlParentAvl(ParentNode);
}
@@ -384,7 +438,7 @@
/* Copy the deleted node itself */
RtlpCopyAvlNodeData(DeleteNode, Node);
-
+
/* Pick the right node to unlink */
Node1 = RtlIsLeftChildAvl(Node) ?
&(RtlParentAvl(DeleteNode))->LeftChild :
&(RtlParentAvl(DeleteNode))->RightChild;