/* * PROJECT: ReactOS Kernel * LICENSE: BSD - See COPYING.ARM in the top level directory * FILE: ntoskrnl/mm/ARM3/miavl.h * PURPOSE: ARM Memory Manager VAD Node Algorithms * PROGRAMMERS: ReactOS Portable Systems Group */ #pragma once /* * This is the glue code for the Memory Manager version of AVL Trees that is used * to store the MM_AVL_TABLE for Virtual Address Descriptors (VAD) in the VadRoot * field in EPROCESS. * * In this version of the package, the balance and parent pointers are stored in * the same field as a union (since we know the parent will be at least 8-byte * aligned), saving some space, but requiring special logic to handle setting and * querying the parent and balance. * * The other difference is that the AVL package for Rtl has custom callbacks for * comparison purposes (which would access some internal, opaque, user data) while * the Mm package stores the user-data inline as StartingVpn and EndingVpn. So * when a compare is being made, RtlpAvlCompareRoutine is called, which will either * perform the Mm work, or call the user-specified callback in the Rtl case. */ #define PRTL_AVL_TABLE PMM_AVL_TABLE #define PRTL_BALANCED_LINKS PMMADDRESS_NODE #define MI_ASSERT(x) ASSERT(x) /* We need to rename the functions to prevent conflicts when not inlined! */ #define RtlpFindAvlTableNodeOrParent MiFindAvlTableNodeOrParent #define RtlpPromoteAvlTreeNode MiPromoteAvlTreeNode #define RtlpRebalanceAvlTreeNode MiRebalanceAvlTreeNode #define RtlpInsertAvlTreeNode MiInsertAvlTreeNode #define RtlpDeleteAvlTreeNode MiDeleteAvlTreeNode /* These are implementation specific */ #define RtlpCopyAvlNodeData MiCopyAvlNodeData #define RtlpAvlCompareRoutine MiAvlCompareRoutine #define RtlSetParent MiSetParent #define RtlSetBalance MiSetBalance #define RtlBalance MiBalance #define RtlParentAvl MiParentAvl #define RtlRightChildAvl MiRightChildAvl #define RtlLeftChildAvl MiLeftChildAvl #define RtlIsLeftChildAvl MiIsLeftChildAvl #define RtlIsRightChildAvl MiIsRightChildAvl #define RtlInsertAsLeftChildAvl MiInsertAsLeftChildAvl #define RtlInsertAsRightChildAvl MiInsertAsRightChildAvl FORCEINLINE VOID MiCopyAvlNodeData(IN PRTL_BALANCED_LINKS Node1, IN PRTL_BALANCED_LINKS Node2) { Node1->u1.Parent = Node2->u1.Parent; Node1->LeftChild = Node2->LeftChild; Node1->RightChild = Node2->RightChild; } FORCEINLINE RTL_GENERIC_COMPARE_RESULTS MiAvlCompareRoutine(IN PRTL_AVL_TABLE Table, IN PVOID Buffer, IN PVOID UserData) { PRTL_BALANCED_LINKS CurrentNode = (PVOID)((ULONG_PTR)UserData - sizeof(RTL_BALANCED_LINKS)); ULONG_PTR StartingVpn = (ULONG_PTR)Buffer; if (StartingVpn < CurrentNode->StartingVpn) { return GenericLessThan; } else if (StartingVpn <= CurrentNode->EndingVpn) { return GenericEqual; } else { return GenericGreaterThan; } } FORCEINLINE VOID MiSetParent(IN PRTL_BALANCED_LINKS Node, IN PRTL_BALANCED_LINKS Parent) { Node->u1.Parent = (PRTL_BALANCED_LINKS)((ULONG_PTR)Parent | (Node->u1.Balance & 0x3)); } FORCEINLINE VOID MiSetBalance(IN PRTL_BALANCED_LINKS Node, IN SCHAR Balance) { Node->u1.Balance = Balance; } FORCEINLINE SCHAR MiBalance(IN PRTL_BALANCED_LINKS Node) { return (SCHAR)Node->u1.Balance; } FORCEINLINE PRTL_BALANCED_LINKS MiParentAvl(IN PRTL_BALANCED_LINKS Node) { return (PRTL_BALANCED_LINKS)((ULONG_PTR)Node->u1.Parent & ~3); } FORCEINLINE PRTL_BALANCED_LINKS MiRightChildAvl(IN PRTL_BALANCED_LINKS Node) { return Node->RightChild; } FORCEINLINE PRTL_BALANCED_LINKS MiLeftChildAvl(IN PRTL_BALANCED_LINKS Node) { return Node->LeftChild; } FORCEINLINE BOOLEAN MiIsLeftChildAvl(IN PRTL_BALANCED_LINKS Node) { return (RtlLeftChildAvl(RtlParentAvl(Node)) == Node); } FORCEINLINE BOOLEAN MiIsRightChildAvl(IN PRTL_BALANCED_LINKS Node) { return (RtlRightChildAvl(RtlParentAvl(Node)) == Node); } FORCEINLINE VOID MiInsertAsLeftChildAvl(IN PRTL_BALANCED_LINKS Parent, IN PRTL_BALANCED_LINKS Node) { Parent->LeftChild = Node; RtlSetParent(Node, Parent); } FORCEINLINE VOID MiInsertAsRightChildAvl(IN PRTL_BALANCED_LINKS Parent, IN PRTL_BALANCED_LINKS Node) { Parent->RightChild = Node; RtlSetParent(Node, Parent); } /* EOF */