/* * @implemented */ PRTL_SPLAY_LINKS NTAPI RtlRealSuccessor(PRTL_SPLAY_LINKS Links) { PRTL_SPLAY_LINKS Child; /* Get the right child */ Child = RtlRightChild(Links); if (Child) { /* Get left-most child */ while (RtlLeftChild(Child)) Child = RtlLeftChild(Child); return Child; } /* We don't have a right child, keep looping until we find our parent */ Child = Links; while (RtlIsRightChild(Child)) Child = RtlParent(Child); /* The parent should be a left child, return the real successor */ if (RtlIsLeftChild(Child)) return RtlParent(Child); /* The parent isn't a right child, so no real successor for us */ return NULL; }
PRTL_SPLAY_LINKS RtlRealPredecessor ( IN PRTL_SPLAY_LINKS Links ) /*++ Routine Description: The RealPredecessor function takes as input a pointer to a splay link in a tree and returns a pointer to the predecessor of the input node within the entire tree. If there is not a predecessor, the return value is NULL. Arguments: Links - Supplies a pointer to a splay link in a tree. Return Value: PRTL_SPLAY_LINKS - returns a pointer to the predecessor in the entire tree --*/ { PRTL_SPLAY_LINKS Ptr; /* first check to see if there is a left subtree to the input link if there is then the real predecessor is the right most node in the left subtree. That is find and return P in the following diagram Links / . . . P / */ if ((Ptr = RtlLeftChild(Links)) != NULL) { while (RtlRightChild(Ptr) != NULL) { Ptr = RtlRightChild(Ptr); } return Ptr; } /* we do not have a left child so check to see if have a parent and if so find the first ancestor that we are a right descendent of. That is find and return P in the following diagram P \ . . . Links */ Ptr = Links; while (RtlIsLeftChild(Ptr)) { Ptr = RtlParent(Ptr); } if (RtlIsRightChild(Ptr)) { return RtlParent(Ptr); } // // otherwise we are do not have a real predecessor so we simply return // NULL // return NULL; }
PRTL_SPLAY_LINKS RtlSplay ( IN PRTL_SPLAY_LINKS Links ) /*++ Routine Description: The Splay function takes as input a pointer to a splay link in a tree and splays the tree. Its function return value is a pointer to the root of the splayed tree. Arguments: Links - Supplies a pointer to a splay link in a tree. Return Value: PRTL_SPLAY_LINKS - returns a pointer to the root of the splayed tree. --*/ { PRTL_SPLAY_LINKS L; PRTL_SPLAY_LINKS P; PRTL_SPLAY_LINKS G; // // while links is not the root we need to keep rotating it toward // the root // L = Links; while (!RtlIsRoot(L)) { P = RtlParent(L); G = RtlParent(P); if (RtlIsLeftChild(L)) { if (RtlIsRoot(P)) { /* we have the following case P L / \ / \ L c ==> a P / \ / \ a b b c */ // // Connect P & b // P->LeftChild = L->RightChild; if (P->LeftChild != NULL) {P->LeftChild->Parent = P;} // // Connect L & P // L->RightChild = P; P->Parent = L; // // Make L the root // L->Parent = L; } else if (RtlIsLeftChild(P)) { /* we have the following case | | G L / \ / \ P d ==> a P / \ / \ L c b G / \ / \ a b c d */ // // Connect P & b // P->LeftChild = L->RightChild; if (P->LeftChild != NULL) {P->LeftChild->Parent = P;} // // Connect G & c // G->LeftChild = P->RightChild; if (G->LeftChild != NULL) {G->LeftChild->Parent = G;} // // Connect L & Great GrandParent // if (RtlIsRoot(G)) { L->Parent = L; } else { L->Parent = G->Parent; *(ParentsChildPointerAddress(G)) = L; } // // Connect L & P // L->RightChild = P; P->Parent = L; // // Connect P & G // P->RightChild = G; G->Parent = P; } else { // RtlIsRightChild(Parent) /* we have the following case | | G L / \ / \ a P G P / \ / \ / \ L d ==> a b c d / \ b c */ // // Connect G & b // G->RightChild = L->LeftChild; if (G->RightChild != NULL) {G->RightChild->Parent = G;} // // Connect P & c // P->LeftChild = L->RightChild; if (P->LeftChild != NULL) {P->LeftChild->Parent = P;} // // Connect L & Great GrandParent // if (RtlIsRoot(G)) { L->Parent = L; } else { L->Parent = G->Parent; *(ParentsChildPointerAddress(G)) = L; } // // Connect L & G // L->LeftChild = G; G->Parent = L; // // Connect L & P // L->RightChild = P; P->Parent = L; } } else { // RtlIsRightChild(L) if (RtlIsRoot(P)) { /* we have the following case P L / \ / \ a L P c / \ / \ b c ==> a b */ // // Connect P & b // P->RightChild = L->LeftChild; if (P->RightChild != NULL) {P->RightChild->Parent = P;} // // Connect P & L // L->LeftChild = P; P->Parent = L; // // Make L the root // L->Parent = L; } else if (RtlIsRightChild(P)) { /* we have the following case | | G L / \ / \ a P P d / \ / \ b L G c / \ / \ c d ==> a b */ // // Connect G & b // G->RightChild = P->LeftChild; if (G->RightChild != NULL) {G->RightChild->Parent = G;} // // Connect P & c // P->RightChild = L->LeftChild; if (P->RightChild != NULL) {P->RightChild->Parent = P;} // // Connect L & Great GrandParent // if (RtlIsRoot(G)) { L->Parent = L; } else { L->Parent = G->Parent; *(ParentsChildPointerAddress(G)) = L; } // // Connect L & P // L->LeftChild = P; P->Parent = L; // // Connect P & G // P->LeftChild = G; G->Parent = P; } else { // RtlIsLeftChild(P) /* we have the following case | | G L / \ / \ P d P G / \ / \ / \ a L ==> a b c d / \ b c */ // // Connect P & b // P->RightChild = L->LeftChild; if (P->RightChild != NULL) {P->RightChild->Parent = P;} // // Connect G & c // G->LeftChild = L->RightChild; if (G->LeftChild != NULL) {G->LeftChild->Parent = G;} // // Connect L & Great GrandParent // if (RtlIsRoot(G)) { L->Parent = L; } else { L->Parent = G->Parent; *(ParentsChildPointerAddress(G)) = L; } // // Connect L & P // L->LeftChild = P; P->Parent = L; // // Connect L & G // L->RightChild = G; G->Parent = L; } } } return L; }
FORCEINLINE VOID RtlpDeleteAvlTreeNode(IN PRTL_AVL_TABLE Table, IN PRTL_BALANCED_LINKS Node) { 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)) { /* Pick the successor which will be the longest side in this case */ DeleteNode = RtlRightChildAvl(Node); while (RtlLeftChildAvl(DeleteNode)) DeleteNode = RtlLeftChildAvl(DeleteNode); } else if (!DeleteNode) { /* Pick the predecessor which will be the longest side in this case */ DeleteNode = RtlLeftChildAvl(Node); 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) { /* Check if the tree's balance increased */ if (RtlBalance(ParentNode) == Balance) { /* Now the tree is balanced */ RtlSetBalance(ParentNode, RtlBalancedAvlTree); } else if (RtlBalance(ParentNode) == RtlBalancedAvlTree) { /* The tree has now become less balanced, since it was balanced */ RtlSetBalance(ParentNode, -Balance); /* Deal with the loop optimization to detect loss of a tree level */ if (RtlBalance(&Table->BalancedRoot) != RtlBalancedAvlTree) Table->DepthOfTree--; break; } else { /* The tree has become unbalanced, so a rebalance is needed */ if (RtlpRebalanceAvlTreeNode(ParentNode)) break; /* Get the new parent after the balance */ ParentNode = RtlParentAvl(ParentNode); } /* 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); } /* Check if this isn't the node we ended up deleting directly */ if (Node == DeleteNode) return; /* Copy the deleted node itself */ RtlpCopyAvlNodeData(DeleteNode, Node); /* Pick the right node to unlink */ Node1 = RtlIsLeftChildAvl(Node) ? &(RtlParentAvl(DeleteNode))->LeftChild : &(RtlParentAvl(DeleteNode))->RightChild; *Node1 = DeleteNode; /* Reparent as appropriate */ if (RtlLeftChildAvl(DeleteNode)) RtlSetParent(RtlLeftChildAvl(DeleteNode), DeleteNode); if (RtlRightChildAvl(DeleteNode)) RtlSetParent(RtlRightChildAvl(DeleteNode), DeleteNode); }
VOID DumpTunnel ( PTUNNEL Tunnel ) { PRTL_SPLAY_LINKS SplayLinks, Ptr; PTUNNEL_NODE Node; PLIST_ENTRY Link; ULONG Indent = 1, i; ULONG EntryCount = 0; BOOLEAN CountOff = FALSE; DbgPrint("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"); DbgPrint("NumEntries = %d\n", Tunnel->NumEntries); DbgPrint("****** Cache Tree\n"); SplayLinks = Tunnel->Cache; if (SplayLinks == NULL) { goto end; } while (RtlLeftChild(SplayLinks) != NULL) { SplayLinks = RtlLeftChild(SplayLinks); Indent++; } while (SplayLinks) { Node = CONTAINING_RECORD( SplayLinks, TUNNEL_NODE, CacheLinks ); EntryCount++; DumpNode(Node, Indent); Ptr = SplayLinks; /* first check to see if there is a right subtree to the input link if there is then the real successor is the left most node in the right subtree. That is find and return P in the following diagram Links \ . . . / P \ */ if ((Ptr = RtlRightChild(SplayLinks)) != NULL) { Indent++; while (RtlLeftChild(Ptr) != NULL) { Indent++; Ptr = RtlLeftChild(Ptr); } SplayLinks = Ptr; } else { /* we do not have a right child so check to see if have a parent and if so find the first ancestor that we are a left decendent of. That is find and return P in the following diagram P / . . . Links */ Ptr = SplayLinks; while (RtlIsRightChild(Ptr)) { Indent--; Ptr = RtlParent(Ptr); } if (!RtlIsLeftChild(Ptr)) { // // we do not have a real successor so we simply return // NULL // SplayLinks = NULL; } else { Indent--; SplayLinks = RtlParent(Ptr); } } } end: if (CountOff = (EntryCount != Tunnel->NumEntries)) { DbgPrint("!!!!!!!!!! Splay Tree Count Mismatch (%d != %d)\n", EntryCount, Tunnel->NumEntries); } EntryCount = 0; DbgPrint("****** Timer Queue\n"); for (Link = Tunnel->TimerQueue.Flink; Link != &Tunnel->TimerQueue; Link = Link->Flink) { Node = CONTAINING_RECORD( Link, TUNNEL_NODE, ListLinks ); EntryCount++; DumpNode(Node, 1); } if (CountOff |= (EntryCount != Tunnel->NumEntries)) { DbgPrint("!!!!!!!!!! Timer Queue Count Mismatch (%d != %d)\n", EntryCount, Tunnel->NumEntries); } ASSERT(!CountOff); DbgPrint("------------------------------------------------------------------\n"); }
/* * @implemented */ PRTL_SPLAY_LINKS NTAPI RtlSplay(PRTL_SPLAY_LINKS Links) { /* * Implementation Notes (http://en.wikipedia.org/wiki/Splay_tree): * * To do a splay, we carry out a sequence of rotations, * each of which moves the target node N closer to the root. * * Each particular step depends on only two factors: * - Whether N is the left or right child of its parent node, P, * - Whether P is the left or right child of its parent, G (for grandparent node). * * Thus, there are four cases: * - Case 1: N is the left child of P and P is the left child of G. * In this case we perform a double right rotation, so that * P becomes N's right child, and G becomes P's right child. * * - Case 2: N is the right child of P and P is the right child of G. * In this case we perform a double left rotation, so that * P becomes N's left child, and G becomes P's left child. * * - Case 3: N is the left child of P and P is the right child of G. * In this case we perform a rotation so that * G becomes N's left child, and P becomes N's right child. * * - Case 4: N is the right child of P and P is the left child of G. * In this case we perform a rotation so that * P becomes N's left child, and G becomes N's right child. * * Finally, if N doesn't have a grandparent node, we simply perform a * left or right rotation to move it to the root. * * By performing a splay on the node of interest after every operation, * we keep recently accessed nodes near the root and keep the tree * roughly balanced, so that we achieve the desired amortized time bounds. */ PRTL_SPLAY_LINKS N, P, G; /* N is the item we'll be playing with */ N = Links; /* Let the algorithm run until N becomes the root entry */ while (!RtlIsRoot(N)) { /* Now get the parent and grand-parent */ P = RtlParent(N); G = RtlParent(P); /* Case 1 & 3: N is left child of P */ if (RtlIsLeftChild(N)) { /* Case 1: P is the left child of G */ if (RtlIsLeftChild(P)) { /* * N's right-child becomes P's left child and * P's right-child becomes G's left child. */ RtlLeftChild(P) = RtlRightChild(N); RtlLeftChild(G) = RtlRightChild(P); /* * If they exist, update their parent pointers too, * since they've changed trees. */ if (RtlLeftChild(P)) RtlParent(RtlLeftChild(P)) = P; if (RtlLeftChild(G)) RtlParent(RtlLeftChild(G)) = G; /* * Now we'll shove N all the way to the top. * Check if G is the root first. */ if (RtlIsRoot(G)) { /* G doesn't have a parent, so N will become the root! */ RtlParent(N) = N; } else { /* G has a parent, so inherit it since we take G's place */ RtlParent(N) = RtlParent(G); /* * Now find out who was referencing G and have it reference * N instead, since we're taking G's place. */ if (RtlIsLeftChild(G)) { /* * G was a left child, so change its parent's left * child link to point to N now. */ RtlLeftChild(RtlParent(G)) = N; } else { /* * G was a right child, so change its parent's right * child link to point to N now. */ RtlRightChild(RtlParent(G)) = N; } } /* Now N is on top, so P has become its child. */ RtlRightChild(N) = P; RtlParent(P) = N; /* N is on top, P is its child, so G is grandchild. */ RtlRightChild(P) = G; RtlParent(G) = P; } /* Case 3: P is the right child of G */ else if (RtlIsRightChild(P)) { /* * N's left-child becomes G's right child and * N's right-child becomes P's left child. */ RtlRightChild(G) = RtlLeftChild(N); RtlLeftChild(P) = RtlRightChild(N); /* * If they exist, update their parent pointers too, * since they've changed trees. */ if (RtlRightChild(G)) RtlParent(RtlRightChild(G)) = G; if (RtlLeftChild(P)) RtlParent(RtlLeftChild(P)) = P; /* * Now we'll shove N all the way to the top. * Check if G is the root first. */ if (RtlIsRoot(G)) { /* G doesn't have a parent, so N will become the root! */ RtlParent(N) = N; } else { /* G has a parent, so inherit it since we take G's place */ RtlParent(N) = RtlParent(G); /* * Now find out who was referencing G and have it reference * N instead, since we're taking G's place. */ if (RtlIsLeftChild(G)) { /* * G was a left child, so change its parent's left * child link to point to N now. */ RtlLeftChild(RtlParent(G)) = N; } else { /* * G was a right child, so change its parent's right * child link to point to N now. */ RtlRightChild(RtlParent(G)) = N; } } /* Now N is on top, so G has become its left child. */ RtlLeftChild(N) = G; RtlParent(G) = N; /* N is on top, G is its left child, so P is right child. */ RtlRightChild(N) = P; RtlParent(P) = N; } /* "Finally" case: N doesn't have a grandparent => P is root */ else { /* P's left-child becomes N's right child */ RtlLeftChild(P) = RtlRightChild(N); /* If it exists, update its parent pointer too */ if (RtlLeftChild(P)) RtlParent(RtlLeftChild(P)) = P; /* Now make N the root, no need to worry about references */ N->Parent = N; /* And make P its right child */ N->RightChild = P; P->Parent = N; } } /* Case 2 & 4: N is right child of P */ else { /* Case 2: P is the right child of G */ if (RtlIsRightChild(P)) { /* * P's left-child becomes G's right child and * N's left-child becomes P's right child. */ RtlRightChild(G) = RtlLeftChild(P); RtlRightChild(P) = RtlLeftChild(N); /* * If they exist, update their parent pointers too, * since they've changed trees. */ if (RtlRightChild(G)) RtlParent(RtlRightChild(G)) = G; if (RtlRightChild(P)) RtlParent(RtlRightChild(P)) = P; /* * Now we'll shove N all the way to the top. * Check if G is the root first. */ if (RtlIsRoot(G)) { /* G doesn't have a parent, so N will become the root! */ RtlParent(N) = N; } else { /* G has a parent, so inherit it since we take G's place */ RtlParent(N) = RtlParent(G); /* * Now find out who was referencing G and have it reference * N instead, since we're taking G's place. */ if (RtlIsLeftChild(G)) { /* * G was a left child, so change its parent's left * child link to point to N now. */ RtlLeftChild(RtlParent(G)) = N; } else { /* * G was a right child, so change its parent's right * child link to point to N now. */ RtlRightChild(RtlParent(G)) = N; } } /* Now N is on top, so P has become its child. */ RtlLeftChild(N) = P; RtlParent(P) = N; /* N is on top, P is its child, so G is grandchild. */ RtlLeftChild(P) = G; RtlParent(G) = P; } /* Case 4: P is the left child of G */ else if (RtlIsLeftChild(P)) { /* * N's left-child becomes G's right child and * N's right-child becomes P's left child. */ RtlRightChild(P) = RtlLeftChild(N); RtlLeftChild(G) = RtlRightChild(N); /* * If they exist, update their parent pointers too, * since they've changed trees. */ if (RtlRightChild(P)) RtlParent(RtlRightChild(P)) = P; if (RtlLeftChild(G)) RtlParent(RtlLeftChild(G)) = G; /* * Now we'll shove N all the way to the top. * Check if G is the root first. */ if (RtlIsRoot(G)) { /* G doesn't have a parent, so N will become the root! */ RtlParent(N) = N; } else { /* G has a parent, so inherit it since we take G's place */ RtlParent(N) = RtlParent(G); /* * Now find out who was referencing G and have it reference * N instead, since we're taking G's place. */ if (RtlIsLeftChild(G)) { /* * G was a left child, so change its parent's left * child link to point to N now. */ RtlLeftChild(RtlParent(G)) = N; } else { /* * G was a right child, so change its parent's right * child link to point to N now. */ RtlRightChild(RtlParent(G)) = N; } } /* Now N is on top, so P has become its left child. */ RtlLeftChild(N) = P; RtlParent(G) = N; /* N is on top, P is its left child, so G is right child. */ RtlRightChild(N) = G; RtlParent(P) = N; } /* "Finally" case: N doesn't have a grandparent => P is root */ else { /* P's right-child becomes N's left child */ RtlRightChild(P) = RtlLeftChild(N); /* If it exists, update its parent pointer too */ if (RtlRightChild(P)) RtlParent(RtlRightChild(P)) = P; /* Now make N the root, no need to worry about references */ N->Parent = N; /* And make P its left child */ N->LeftChild = P; P->Parent = N; } } } /* Return the root entry */ ASSERT(RtlIsRoot(N)); return N; }