modified rbtree code to not need the local key value; also set compiler to treat all warnings as errors
This commit is contained in:
parent
0a31211d96
commit
3f4e807025
|
@ -44,9 +44,9 @@ OBJCOPY := $(ARMDIR)/$(ARMPREFIX)-objcopy
|
||||||
# Define the default flags for compilation.
|
# Define the default flags for compilation.
|
||||||
DEFS := -D__COMROGUE_INTERNALS__
|
DEFS := -D__COMROGUE_INTERNALS__
|
||||||
INCLUDES := -I$(CRBASEDIR)/include -I$(CRBASEDIR)/idl
|
INCLUDES := -I$(CRBASEDIR)/include -I$(CRBASEDIR)/idl
|
||||||
CFLAGS := $(INCLUDES) -mabi=aapcs -mfloat-abi=hard -mcpu=arm1176jzf-s -Wall -O2 \
|
CFLAGS := $(INCLUDES) -mabi=aapcs -mfloat-abi=hard -mcpu=arm1176jzf-s -Wall -Werror -O2 \
|
||||||
-nostdlib -nostartfiles -ffreestanding $(DEFS)
|
-nostdlib -nostartfiles -ffreestanding $(DEFS)
|
||||||
AFLAGS := -mcpu=arm1176jzf-s -mfloat-abi=hard
|
AFLAGS := -mcpu=arm1176jzf-s -mfloat-abi=hard --fatal-warnings
|
||||||
ASM_CPP_FLAGS := $(INCLUDES) $(DEFS) -D__ASM__
|
ASM_CPP_FLAGS := $(INCLUDES) $(DEFS) -D__ASM__
|
||||||
|
|
||||||
# Standard rule for pre-processing linker script files.
|
# Standard rule for pre-processing linker script files.
|
||||||
|
|
|
@ -49,7 +49,8 @@
|
||||||
|
|
||||||
/* Nodes in the page table tree. */
|
/* Nodes in the page table tree. */
|
||||||
typedef struct tagPAGENODE {
|
typedef struct tagPAGENODE {
|
||||||
RBTREENODE rbtn; /* RBT node containing physical address as key */
|
RBTREENODE rbtn; /* RBT node */
|
||||||
|
PHYSADDR paPageTable; /* physical address of page table */
|
||||||
PPAGETAB ppt; /* pointer to page table */
|
PPAGETAB ppt; /* pointer to page table */
|
||||||
} PAGENODE, *PPAGENODE;
|
} PAGENODE, *PPAGENODE;
|
||||||
|
|
||||||
|
|
|
@ -59,10 +59,9 @@ typedef INT32 (*PFNTREECOMPARE)(TREEKEY, TREEKEY);
|
||||||
typedef struct tagRBTREENODE {
|
typedef struct tagRBTREENODE {
|
||||||
struct tagRBTREENODE *ptnLeft; /* pointer to left child */
|
struct tagRBTREENODE *ptnLeft; /* pointer to left child */
|
||||||
UINT_PTR ptnRightColor; /* pointer to right child AND color stored in low-order bit */
|
UINT_PTR ptnRightColor; /* pointer to right child AND color stored in low-order bit */
|
||||||
TREEKEY treekey; /* key value */
|
|
||||||
} RBTREENODE, *PRBTREENODE;
|
} RBTREENODE, *PRBTREENODE;
|
||||||
|
|
||||||
/* Tree node macros, mostly to access either color or pointer or both from the ptnRightColor field */
|
/* Tree node macros, mostly to access either color or pointer or both from the pRightColor field */
|
||||||
#define rbtNodeRight(ptn) ((PRBTREENODE)((ptn)->ptnRightColor & ~1))
|
#define rbtNodeRight(ptn) ((PRBTREENODE)((ptn)->ptnRightColor & ~1))
|
||||||
#define rbtNodeColor(ptn) ((ptn)->ptnRightColor & 1)
|
#define rbtNodeColor(ptn) ((ptn)->ptnRightColor & 1)
|
||||||
#define rbtIsRed(ptn) ((ptn) ? rbtNodeColor(ptn) : FALSE)
|
#define rbtIsRed(ptn) ((ptn) ? rbtNodeColor(ptn) : FALSE)
|
||||||
|
@ -71,34 +70,43 @@ typedef struct tagRBTREENODE {
|
||||||
#define rbtSetNodeColor(ptn, clr) \
|
#define rbtSetNodeColor(ptn, clr) \
|
||||||
do { (ptn)->ptnRightColor = ((ptn)->ptnRightColor & ~1) | ((clr) ? 1 : 0); } while (0)
|
do { (ptn)->ptnRightColor = ((ptn)->ptnRightColor & ~1) | ((clr) ? 1 : 0); } while (0)
|
||||||
#define rbtToggleColor(ptn) do { if (ptn) (ptn)->ptnRightColor ^= 1; } while (0)
|
#define rbtToggleColor(ptn) do { if (ptn) (ptn)->ptnRightColor ^= 1; } while (0)
|
||||||
#define rbtInitNode(ptn, ptnL, ptnR, clr, key) \
|
#define rbtInitNode(ptn, ptnL, ptnR, clr) \
|
||||||
do { (ptn)->ptnLeft = (ptnL); (ptn)->ptnRightColor = (((UINT_PTR)(ptnR)) & ~1) | ((clr) ? 1 : 0); \
|
do { (ptn)->ptnLeft = (ptnL); (ptn)->ptnRightColor = (((UINT_PTR)(ptnR)) & ~1) | ((clr) ? 1 : 0); } while (0)
|
||||||
(ptn)->treekey = (TREEKEY)(key); } while (0)
|
#define rbtNewNode(ptn) rbtInitNode(ptn, NULL, NULL, RED)
|
||||||
#define rbtNewNode(ptn, key) rbtInitNode(ptn, NULL, NULL, RED, key)
|
|
||||||
|
/* Accessor functions common to tree instances. */
|
||||||
|
typedef TREEKEY (*PFNGETTREEKEY)(PVOID);
|
||||||
|
typedef PRBTREENODE (*PFNGETTREENODEPTR)(PVOID);
|
||||||
|
typedef PVOID (*PFNGETFROMTREENODEPTR)(PRBTREENODE);
|
||||||
|
|
||||||
/* The head-of-tree structure. */
|
/* The head-of-tree structure. */
|
||||||
typedef struct tagRBTREE {
|
typedef struct tagRBTREE {
|
||||||
PFNTREECOMPARE pfnTreeCompare; /* pointer to comparison function */
|
PFNTREECOMPARE pfnTreeCompare; /* pointer to comparison function */
|
||||||
|
PFNGETTREEKEY pfnGetTreeKey; /* pointer to key-retrieval function */
|
||||||
|
PFNGETTREENODEPTR pfnGetNodePtr; /* pointer to node-pointer retrieval function */
|
||||||
|
PFNGETFROMTREENODEPTR pfnGetFromNodePtr; /* pointer to func to get the tree node from node pointer */
|
||||||
PRBTREENODE ptnRoot; /* pointer to root of tree */
|
PRBTREENODE ptnRoot; /* pointer to root of tree */
|
||||||
} RBTREE, *PRBTREE;
|
} RBTREE, *PRBTREE;
|
||||||
|
|
||||||
/* Tree macros. */
|
/* Tree macros. */
|
||||||
#define rbtInitTree(ptree, pfnCompare) \
|
#define rbtInitTree(ptree, pfnCompare, pfnGetKey, pfnToNodePtr, pfnFromNodePtr) \
|
||||||
do { (ptree)->pfnTreeCompare = (pfnCompare); (ptree)->ptnRoot = NULL; } while (0)
|
do { (ptree)->pfnTreeCompare = (pfnCompare); (ptree)->pfnGetTreeKey = (pfnGetKey); \
|
||||||
|
(ptree)->pfnGetNodePtr = (pfnToNodePtr); (ptree)->pfnGetFromNodePtr = (pfnFromNodePtr); \
|
||||||
|
(ptree)->ptnRoot = NULL; } while (0)
|
||||||
#define rbtIsEmpty(ptree) MAKEBOOL(!((ptree)->ptnRoot))
|
#define rbtIsEmpty(ptree) MAKEBOOL(!((ptree)->ptnRoot))
|
||||||
|
|
||||||
/* Type of function used by RbtWalk. */
|
/* Type of function used by RbtWalk. */
|
||||||
typedef BOOL (*PFNRBTWALK)(PRBTREE, PRBTREENODE, PVOID);
|
typedef BOOL (*PFNRBTWALK)(PRBTREE, PVOID, PVOID);
|
||||||
|
|
||||||
/* Function prototypes. */
|
/* Function prototypes. */
|
||||||
CDECL_BEGIN
|
CDECL_BEGIN
|
||||||
|
|
||||||
extern INT32 RbtStdCompareByValue(TREEKEY k1, TREEKEY k2);
|
extern INT32 RbtStdCompareByValue(TREEKEY k1, TREEKEY k2);
|
||||||
extern void RbtInsert(PRBTREE ptree, PRBTREENODE ptnNew);
|
extern void RbtInsert(PRBTREE ptree, PVOID ptnNew);
|
||||||
extern PRBTREENODE RbtFind(PRBTREE ptree, TREEKEY key);
|
extern PVOID RbtFind(PRBTREE ptree, TREEKEY key);
|
||||||
extern PRBTREENODE RbtFindPredecessor(PRBTREE ptree, TREEKEY key);
|
extern PVOID RbtFindPredecessor(PRBTREE ptree, TREEKEY key);
|
||||||
extern PRBTREENODE RbtFindSuccessor(PRBTREE ptree, TREEKEY key);
|
extern PVOID RbtFindSuccessor(PRBTREE ptree, TREEKEY key);
|
||||||
extern PRBTREENODE RbtFindMin(PRBTREE ptree);
|
extern PVOID RbtFindMin(PRBTREE ptree);
|
||||||
extern void RbtDelete(PRBTREE ptree, TREEKEY key);
|
extern void RbtDelete(PRBTREE ptree, TREEKEY key);
|
||||||
extern BOOL RbtWalk(PRBTREE ptree, PFNRBTWALK pfnWalk, PVOID pData);
|
extern BOOL RbtWalk(PRBTREE ptree, PFNRBTWALK pfnWalk, PVOID pData);
|
||||||
|
|
||||||
|
|
|
@ -31,12 +31,6 @@
|
||||||
*/
|
*/
|
||||||
#include <comrogue/types.h>
|
#include <comrogue/types.h>
|
||||||
#include <comrogue/internals/rbtree.h>
|
#include <comrogue/internals/rbtree.h>
|
||||||
#include <comrogue/internals/trace.h>
|
|
||||||
|
|
||||||
#ifdef THIS_FILE
|
|
||||||
#undef THIS_FILE
|
|
||||||
DECLARE_THIS_FILE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------------------------------
|
/*------------------------------------------------------------------------------------------------------
|
||||||
* An implementation of left-leaning red-black 2-3 trees as detailed in "Left-leaning Red-Black Trees,"
|
* An implementation of left-leaning red-black 2-3 trees as detailed in "Left-leaning Red-Black Trees,"
|
||||||
|
@ -155,8 +149,9 @@ static PRBTREENODE fix_up(PRBTREENODE ptn)
|
||||||
* - ptree = Pointer to the tree head structure, containing the compare function.
|
* - ptree = Pointer to the tree head structure, containing the compare function.
|
||||||
* - ptnCurrent = Pointer to the current subtree we're inserting into.
|
* - ptnCurrent = Pointer to the current subtree we're inserting into.
|
||||||
* - ptnNew = Pointer to the new tree node to be inserted. This node must have been initialized with
|
* - ptnNew = Pointer to the new tree node to be inserted. This node must have been initialized with
|
||||||
* the rbtInitNode macro to contain a key, NULL left and right pointers, and be red. It is
|
* the rbtInitNode macro to contain NULL left and right pointers and be red. It is
|
||||||
* assumed that the node's key does NOT already exist in the tree.
|
* assumed that the node's key does NOT already exist in the tree.
|
||||||
|
* - keyNew = Tree key for the new node.
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* The pointer to the new subtree after the insertion is performed.
|
* The pointer to the new subtree after the insertion is performed.
|
||||||
|
@ -165,18 +160,20 @@ static PRBTREENODE fix_up(PRBTREENODE ptn)
|
||||||
* This function is recursive; however, the nature of the tree guarantees that the stack space consumed
|
* This function is recursive; however, the nature of the tree guarantees that the stack space consumed
|
||||||
* by its stack frames will be O(log n).
|
* by its stack frames will be O(log n).
|
||||||
*/
|
*/
|
||||||
static PRBTREENODE insert_under(PRBTREE ptree, PRBTREENODE ptnCurrent, PRBTREENODE ptnNew)
|
static PRBTREENODE insert_under(PRBTREE ptree, PRBTREENODE ptnCurrent, PRBTREENODE ptnNew, TREEKEY keyNew)
|
||||||
{
|
{
|
||||||
register int cmp; /* compare result */
|
register int cmp; /* compare result */
|
||||||
|
register TREEKEY keyCurrent;
|
||||||
|
|
||||||
if (!ptnCurrent)
|
if (!ptnCurrent)
|
||||||
return ptnNew; /* degenerate case */
|
return ptnNew; /* degenerate case */
|
||||||
cmp = (*(ptree->pfnTreeCompare))(ptnNew->treekey, ptnCurrent->treekey);
|
keyCurrent = (*(ptree->pfnGetTreeKey))((*(ptree->pfnGetFromNodePtr))(ptnCurrent));
|
||||||
|
cmp = (*(ptree->pfnTreeCompare))(keyNew, keyCurrent);
|
||||||
//ASSERT(cmp != 0);
|
//ASSERT(cmp != 0);
|
||||||
if (cmp < 0)
|
if (cmp < 0)
|
||||||
ptnCurrent->ptnLeft = insert_under(ptree, ptnCurrent->ptnLeft, ptnNew);
|
ptnCurrent->ptnLeft = insert_under(ptree, ptnCurrent->ptnLeft, ptnNew, keyNew);
|
||||||
else
|
else
|
||||||
rbtSetNodeRight(ptnCurrent, insert_under(ptree, rbtNodeRight(ptnCurrent), ptnNew));
|
rbtSetNodeRight(ptnCurrent, insert_under(ptree, rbtNodeRight(ptnCurrent), ptnNew, keyNew));
|
||||||
return fix_up(ptnCurrent);
|
return fix_up(ptnCurrent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,16 +182,17 @@ static PRBTREENODE insert_under(PRBTREE ptree, PRBTREENODE ptnCurrent, PRBTREENO
|
||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* - ptree = Pointer to the tree head structure.
|
* - ptree = Pointer to the tree head structure.
|
||||||
* - ptnNew = Pointer to the new tree node to be inserted. This node must have been initialized with
|
* - pNew = Pointer to the new tree node to be inserted. This node must have been initialized with
|
||||||
* the rbtInitNode macro to contain a key, NULL left and right pointers, and be red. It is
|
* the rbtInitNode macro to contain NULL left and right pointers, and be red. It is
|
||||||
* assumed that the node's key does NOT already exist in the tree.
|
* assumed that the node's key does NOT already exist in the tree.
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* Nothing.
|
* Nothing.
|
||||||
*/
|
*/
|
||||||
void RbtInsert(PRBTREE ptree, PRBTREENODE ptnNew)
|
void RbtInsert(PRBTREE ptree, PVOID pNew)
|
||||||
{
|
{
|
||||||
ptree->ptnRoot = insert_under(ptree, ptree->ptnRoot, ptnNew);
|
ptree->ptnRoot = insert_under(ptree, ptree->ptnRoot, (*(ptree->pfnGetNodePtr))(pNew),
|
||||||
|
(*(ptree->pfnGetTreeKey))(pNew));
|
||||||
rbtSetNodeColor(ptree->ptnRoot, BLACK);
|
rbtSetNodeColor(ptree->ptnRoot, BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,23 +206,25 @@ void RbtInsert(PRBTREE ptree, PRBTREENODE ptnNew)
|
||||||
* Returns:
|
* Returns:
|
||||||
* Pointer to the node where the key is found, or NULL if not found.
|
* Pointer to the node where the key is found, or NULL if not found.
|
||||||
*/
|
*/
|
||||||
PRBTREENODE RbtFind(PRBTREE ptree, TREEKEY key)
|
PVOID RbtFind(PRBTREE ptree, TREEKEY key)
|
||||||
{
|
{
|
||||||
|
register PVOID pCurrent; /* pointer to current node */
|
||||||
register PRBTREENODE ptn = ptree->ptnRoot; /* current node */
|
register PRBTREENODE ptn = ptree->ptnRoot; /* current node */
|
||||||
register int cmp; /* compare result */
|
register int cmp; /* compare result */
|
||||||
|
|
||||||
while (ptn)
|
while (ptn)
|
||||||
{
|
{
|
||||||
cmp = (*(ptree->pfnTreeCompare))(key, ptn->treekey);
|
pCurrent = (*(ptree->pfnGetFromNodePtr))(ptn);
|
||||||
|
cmp = (*(ptree->pfnTreeCompare))(key, (*(ptree->pfnGetTreeKey))(pCurrent));
|
||||||
if (cmp == 0)
|
if (cmp == 0)
|
||||||
break; /* found */
|
return pCurrent; /* found */
|
||||||
else if (cmp < 0)
|
else if (cmp < 0)
|
||||||
ptn = ptn->ptnLeft;
|
ptn = ptn->ptnLeft;
|
||||||
else
|
else
|
||||||
ptn = rbtNodeRight(ptn);
|
ptn = rbtNodeRight(ptn);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ptn;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -239,27 +239,29 @@ PRBTREENODE RbtFind(PRBTREE ptree, TREEKEY key)
|
||||||
* Pointer to the node where the key is found, or pointer to the predecessor node, or NULL if the key
|
* Pointer to the node where the key is found, or pointer to the predecessor node, or NULL if the key
|
||||||
* is less than every key in the tree and hence has no predecessor.
|
* is less than every key in the tree and hence has no predecessor.
|
||||||
*/
|
*/
|
||||||
PRBTREENODE RbtFindPredecessor(PRBTREE ptree, TREEKEY key)
|
PVOID RbtFindPredecessor(PRBTREE ptree, TREEKEY key)
|
||||||
{
|
{
|
||||||
|
register PVOID pCurrent; /* pointer to current node */
|
||||||
register PRBTREENODE ptn = ptree->ptnRoot; /* current node */
|
register PRBTREENODE ptn = ptree->ptnRoot; /* current node */
|
||||||
register int cmp; /* compare result */
|
register int cmp; /* compare result */
|
||||||
|
|
||||||
while (ptn)
|
while (ptn)
|
||||||
{
|
{
|
||||||
cmp = (*(ptree->pfnTreeCompare))(key, ptn->treekey);
|
pCurrent = (*(ptree->pfnGetFromNodePtr))(ptn);
|
||||||
|
cmp = (*(ptree->pfnTreeCompare))(key, (*(ptree->pfnGetTreeKey))(pCurrent));
|
||||||
if (cmp == 0)
|
if (cmp == 0)
|
||||||
break; /* found */
|
return pCurrent; /* found */
|
||||||
else if (cmp > 0)
|
else if (cmp > 0)
|
||||||
{
|
{
|
||||||
if (rbtNodeRight(ptn))
|
if (rbtNodeRight(ptn))
|
||||||
ptn = rbtNodeRight(ptn);
|
ptn = rbtNodeRight(ptn);
|
||||||
else
|
else
|
||||||
break; /* found predecessor */
|
return pCurrent; /* found predecessor */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ptn = ptn->ptnLeft;
|
ptn = ptn->ptnLeft;
|
||||||
}
|
}
|
||||||
return ptn;
|
return NULL; /* not found */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -274,27 +276,29 @@ PRBTREENODE RbtFindPredecessor(PRBTREE ptree, TREEKEY key)
|
||||||
* Pointer to the node where the key is found, or pointer to the successor node, or NULL if the key
|
* Pointer to the node where the key is found, or pointer to the successor node, or NULL if the key
|
||||||
* is greater than every key in the tree and hence has no successor.
|
* is greater than every key in the tree and hence has no successor.
|
||||||
*/
|
*/
|
||||||
PRBTREENODE RbtFindSuccessor(PRBTREE ptree, TREEKEY key)
|
PVOID RbtFindSuccessor(PRBTREE ptree, TREEKEY key)
|
||||||
{
|
{
|
||||||
|
register PVOID pCurrent; /* pointer to current node */
|
||||||
register PRBTREENODE ptn = ptree->ptnRoot; /* current node */
|
register PRBTREENODE ptn = ptree->ptnRoot; /* current node */
|
||||||
register int cmp; /* compare result */
|
register int cmp; /* compare result */
|
||||||
|
|
||||||
while (ptn)
|
while (ptn)
|
||||||
{
|
{
|
||||||
cmp = (*(ptree->pfnTreeCompare))(key, ptn->treekey);
|
pCurrent = (*(ptree->pfnGetFromNodePtr))(ptn);
|
||||||
|
cmp = (*(ptree->pfnTreeCompare))(key, (*(ptree->pfnGetTreeKey))(pCurrent));
|
||||||
if (cmp == 0)
|
if (cmp == 0)
|
||||||
break; /* found */
|
return pCurrent; /* found */
|
||||||
else if (cmp < 0)
|
else if (cmp < 0)
|
||||||
{
|
{
|
||||||
if (ptn->ptnLeft)
|
if (ptn->ptnLeft)
|
||||||
ptn = ptn->ptnLeft;
|
ptn = ptn->ptnLeft;
|
||||||
else
|
else
|
||||||
break; /* found successor */
|
return pCurrent; /* found successor */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ptn = rbtNodeRight(ptn);
|
ptn = rbtNodeRight(ptn);
|
||||||
}
|
}
|
||||||
return ptn;
|
return NULL; /* not found */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -322,9 +326,11 @@ static PRBTREENODE find_min(PRBTREENODE ptn)
|
||||||
* Returns:
|
* Returns:
|
||||||
* Pointer to the leftmost node in the tree. If the tree has no nodes, NULL is returned.
|
* Pointer to the leftmost node in the tree. If the tree has no nodes, NULL is returned.
|
||||||
*/
|
*/
|
||||||
PRBTREENODE RbtFindMin(PRBTREE ptree)
|
PVOID RbtFindMin(PRBTREE ptree)
|
||||||
{
|
{
|
||||||
return ptree->ptnRoot ? find_min(ptree->ptnRoot) : NULL;
|
if (ptree->ptnRoot)
|
||||||
|
return (*(ptree->pfnGetFromNodePtr))(find_min(ptree->ptnRoot));
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -412,7 +418,8 @@ static PRBTREENODE delete_min(PRBTREENODE ptn)
|
||||||
*/
|
*/
|
||||||
static PRBTREENODE delete_from_under(PRBTREE ptree, PRBTREENODE ptnCurrent, TREEKEY key)
|
static PRBTREENODE delete_from_under(PRBTREE ptree, PRBTREENODE ptnCurrent, TREEKEY key)
|
||||||
{
|
{
|
||||||
register int cmp = (*(ptree->pfnTreeCompare))(key, ptnCurrent->treekey);
|
register TREEKEY keyCurrent = (*(ptree->pfnGetTreeKey))((*(ptree->pfnGetFromNodePtr))(ptnCurrent));
|
||||||
|
register int cmp = (*(ptree->pfnTreeCompare))(key, keyCurrent);
|
||||||
if (cmp < 0)
|
if (cmp < 0)
|
||||||
{
|
{
|
||||||
/* hunt down the left subtree */
|
/* hunt down the left subtree */
|
||||||
|
@ -425,7 +432,8 @@ static PRBTREENODE delete_from_under(PRBTREE ptree, PRBTREENODE ptnCurrent, TREE
|
||||||
if (rbtIsRed(ptnCurrent->ptnLeft))
|
if (rbtIsRed(ptnCurrent->ptnLeft))
|
||||||
{
|
{
|
||||||
ptnCurrent = rotate_right(ptnCurrent);
|
ptnCurrent = rotate_right(ptnCurrent);
|
||||||
cmp = (*(ptree->pfnTreeCompare))(key, ptnCurrent->treekey);
|
keyCurrent = (*(ptree->pfnGetTreeKey))((*(ptree->pfnGetFromNodePtr))(ptnCurrent));
|
||||||
|
cmp = (*(ptree->pfnTreeCompare))(key, keyCurrent);
|
||||||
}
|
}
|
||||||
if ((cmp == 0) && !rbtNodeRight(ptnCurrent))
|
if ((cmp == 0) && !rbtNodeRight(ptnCurrent))
|
||||||
return ptnCurrent->ptnLeft; /* degenerate case */
|
return ptnCurrent->ptnLeft; /* degenerate case */
|
||||||
|
@ -433,7 +441,8 @@ static PRBTREENODE delete_from_under(PRBTREE ptree, PRBTREENODE ptnCurrent, TREE
|
||||||
&& (!rbtNodeRight(ptnCurrent) || !rbtIsRed(rbtNodeRight(ptnCurrent)->ptnLeft)))
|
&& (!rbtNodeRight(ptnCurrent) || !rbtIsRed(rbtNodeRight(ptnCurrent)->ptnLeft)))
|
||||||
{
|
{
|
||||||
ptnCurrent = move_red_right(ptnCurrent);
|
ptnCurrent = move_red_right(ptnCurrent);
|
||||||
cmp = (*(ptree->pfnTreeCompare))(key, ptnCurrent->treekey);
|
keyCurrent = (*(ptree->pfnGetTreeKey))((*(ptree->pfnGetFromNodePtr))(ptnCurrent));
|
||||||
|
cmp = (*(ptree->pfnTreeCompare))(key, keyCurrent);
|
||||||
}
|
}
|
||||||
if (cmp == 0)
|
if (cmp == 0)
|
||||||
{
|
{
|
||||||
|
@ -495,7 +504,7 @@ static BOOL do_walk(PRBTREE ptree, PRBTREENODE ptn, PFNRBTWALK pfnWalk, PVOID pD
|
||||||
if (ptn->ptnLeft)
|
if (ptn->ptnLeft)
|
||||||
rc = do_walk(ptree, ptn->ptnLeft, pfnWalk, pData);
|
rc = do_walk(ptree, ptn->ptnLeft, pfnWalk, pData);
|
||||||
if (rc)
|
if (rc)
|
||||||
rc = (*pfnWalk)(ptree, ptn, pData);
|
rc = (*pfnWalk)(ptree, (*(ptree->pfnGetFromNodePtr))(ptn), pData);
|
||||||
if (rc && rbtNodeRight(ptn))
|
if (rc && rbtNodeRight(ptn))
|
||||||
rc = do_walk(ptree, rbtNodeRight(ptn), pfnWalk, pData);
|
rc = do_walk(ptree, rbtNodeRight(ptn), pfnWalk, pData);
|
||||||
return rc;
|
return rc;
|
||||||
|
|
|
@ -176,6 +176,48 @@ typedef struct tagALLOC_STRUC {
|
||||||
static RBTREE g_rbtFreeAddrs; /* free address tree */
|
static RBTREE g_rbtFreeAddrs; /* free address tree */
|
||||||
static PMALLOC g_pMalloc = NULL; /* allocator we use */
|
static PMALLOC g_pMalloc = NULL; /* allocator we use */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given a pointer to an ADDRTREENODE, returns its key value (pointer to its interval).
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - patn = Pointer to the ADDRTREENODE.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* Pointer to its embedded address interval.
|
||||||
|
*/
|
||||||
|
static TREEKEY get_interval_from_addrtreenode(PVOID patn)
|
||||||
|
{
|
||||||
|
return (TREEKEY)(&(((PADDRTREENODE)patn)->ai));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given a pointer to an ADDRTREENODE, returns a pointer to its embedded RBTREENODE.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - patn = Pointer to the ADDRTREENODE.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* Pointer to the embedded RBTREENODE.
|
||||||
|
*/
|
||||||
|
static PRBTREENODE get_rbtreenode_from_addrtreenode(PVOID patn)
|
||||||
|
{
|
||||||
|
return &(((PADDRTREENODE)patn)->rbtn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given a pointer to a RBTREENODE, returns a pointer to the ADDRTREENODE containing it.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - ptn = Pointer to the RBTREENODE.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* Pointer to the containing ADDRTREENODE.
|
||||||
|
*/
|
||||||
|
static PVOID get_addrtreenode_from_rbtreenode(PRBTREENODE ptn)
|
||||||
|
{
|
||||||
|
return (PVOID)(((PCHAR)ptn) - OFFSETOF(ADDRTREENODE, rbtn));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Inserts a kernel address range into the tree.
|
* Inserts a kernel address range into the tree.
|
||||||
*
|
*
|
||||||
|
@ -193,8 +235,9 @@ static void insert_into_tree(KERNADDR kaFirst, KERNADDR kaLast)
|
||||||
{
|
{
|
||||||
PADDRTREENODE pnode = IMalloc_Alloc(g_pMalloc, sizeof(ADDRTREENODE));
|
PADDRTREENODE pnode = IMalloc_Alloc(g_pMalloc, sizeof(ADDRTREENODE));
|
||||||
ASSERT(pnode);
|
ASSERT(pnode);
|
||||||
rbtNewNode(&(pnode->rbtn), init_interval(&(pnode->ai), kaFirst, kaLast));
|
rbtNewNode(&(pnode->rbtn));
|
||||||
RbtInsert(&g_rbtFreeAddrs, (PRBTREENODE)pnode);
|
init_interval(&(pnode->ai), kaFirst, kaLast);
|
||||||
|
RbtInsert(&g_rbtFreeAddrs, pnode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -288,8 +331,8 @@ void _MmFreeKernelAddr(KERNADDR kaBase, UINT32 cpgToFree)
|
||||||
|
|
||||||
init_interval_pages(&aiFree, kaBase, cpgToFree);
|
init_interval_pages(&aiFree, kaBase, cpgToFree);
|
||||||
ASSERT(!RbtFind(&g_rbtFreeAddrs, (TREEKEY)(&aiFree)));
|
ASSERT(!RbtFind(&g_rbtFreeAddrs, (TREEKEY)(&aiFree)));
|
||||||
patnPred = (PADDRTREENODE)RbtFindPredecessor(&g_rbtFreeAddrs, (TREEKEY)(&aiFree));
|
patnPred = (PADDRTREENODE)RbtFindPredecessor(&g_rbtFreeAddrs, (&aiFree));
|
||||||
patnSucc = (PADDRTREENODE)RbtFindSuccessor(&g_rbtFreeAddrs, (TREEKEY)(&aiFree));
|
patnSucc = (PADDRTREENODE)RbtFindSuccessor(&g_rbtFreeAddrs, (&aiFree));
|
||||||
if (patnPred && intervals_adjacent(&(patnPred->ai), &aiFree))
|
if (patnPred && intervals_adjacent(&(patnPred->ai), &aiFree))
|
||||||
{
|
{
|
||||||
if (patnSucc && intervals_adjacent(&aiFree, &(patnSucc->ai)))
|
if (patnSucc && intervals_adjacent(&aiFree, &(patnSucc->ai)))
|
||||||
|
@ -321,7 +364,8 @@ SEG_INIT_CODE void _MmInitKernelSpace(PSTARTUP_INFO pstartup, PMALLOC pmInitHeap
|
||||||
{
|
{
|
||||||
g_pMalloc = pmInitHeap;
|
g_pMalloc = pmInitHeap;
|
||||||
IUnknown_AddRef(g_pMalloc);
|
IUnknown_AddRef(g_pMalloc);
|
||||||
rbtInitTree(&g_rbtFreeAddrs, (PFNTREECOMPARE)interval_compare);
|
rbtInitTree(&g_rbtFreeAddrs, (PFNTREECOMPARE)interval_compare, get_interval_from_addrtreenode,
|
||||||
|
get_rbtreenode_from_addrtreenode, get_addrtreenode_from_rbtreenode);
|
||||||
insert_into_tree(pstartup->vmaFirstFree, VMADDR_IO_BASE);
|
insert_into_tree(pstartup->vmaFirstFree, VMADDR_IO_BASE);
|
||||||
insert_into_tree(VMADDR_IO_BASE + (PAGE_COUNT_IO * SYS_PAGE_SIZE), VMADDR_KERNEL_NOMANS);
|
insert_into_tree(VMADDR_IO_BASE + (PAGE_COUNT_IO * SYS_PAGE_SIZE), VMADDR_KERNEL_NOMANS);
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,6 +62,53 @@ static VMCTXT g_vmctxtKernel = { /* kernel VM context */
|
||||||
static RBTREE g_rbtFreePageTables; /* tree containing free page tables */
|
static RBTREE g_rbtFreePageTables; /* tree containing free page tables */
|
||||||
static PFNSETPTEADDR g_pfnSetPTEAddr = NULL; /* hook function into page database */
|
static PFNSETPTEADDR g_pfnSetPTEAddr = NULL; /* hook function into page database */
|
||||||
|
|
||||||
|
/*-----------------------------------
|
||||||
|
* Red-black tree accessor functions
|
||||||
|
*-----------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given a pointer to a PAGENODE, returns its key (the physical address of the page table).
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - ppgn = Pointer to a PAGENODE.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* The PAGENODE's key value (the physical address of the page table).
|
||||||
|
*/
|
||||||
|
static TREEKEY get_key_from_pagenode(PVOID ppgn)
|
||||||
|
{
|
||||||
|
return (TREEKEY)(((PPAGENODE)ppgn)->paPageTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given a pointer to a PAGENODE, returns a pointer to the RBTREENODE contained within it.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - ppgn = Pointer to a PAGENODE.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* The PAGENODE's embedded RBTREENODE.
|
||||||
|
*/
|
||||||
|
static PRBTREENODE get_rbtreenode_from_pagenode(PVOID ppgn)
|
||||||
|
{
|
||||||
|
return &(((PPAGENODE)ppgn)->rbtn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given a pointer to a RBTREENODE, returns a pointer to the PAGENODE it's embedded in.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - ptn = Pointer to an RBTREENODE.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* The pointer to the PAGENODE the RBTREENODE is embedded in.
|
||||||
|
*/
|
||||||
|
static PVOID get_pagenode_from_rbtreenode(PRBTREENODE ptn)
|
||||||
|
{
|
||||||
|
return (PVOID)(((PCHAR)ptn) - OFFSETOF(PAGENODE, rbtn));
|
||||||
|
}
|
||||||
|
|
||||||
/*------------------------------
|
/*------------------------------
|
||||||
* Inline resolution operations
|
* Inline resolution operations
|
||||||
*------------------------------
|
*------------------------------
|
||||||
|
@ -194,8 +241,8 @@ static void free_page_table(PVMCTXT pvmctxt, PPAGETAB ppgt)
|
||||||
if (ppgn)
|
if (ppgn)
|
||||||
{
|
{
|
||||||
RbtDelete(&(pvmctxt->rbtPageTables), (TREEKEY)pa);
|
RbtDelete(&(pvmctxt->rbtPageTables), (TREEKEY)pa);
|
||||||
rbtNewNode(&(ppgn->rbtn), ppgn->rbtn.treekey);
|
rbtNewNode(&(ppgn->rbtn));
|
||||||
RbtInsert(&g_rbtFreePageTables, (PRBTREENODE)ppgn);
|
RbtInsert(&g_rbtFreePageTables, ppgn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -681,12 +728,14 @@ static HRESULT alloc_page_table(PVMCTXT pvmctxt, PTTB pttbEntry, PTTBAUX pttbAux
|
||||||
ppgn = IMalloc_Alloc(g_pMalloc, sizeof(PAGENODE));
|
ppgn = IMalloc_Alloc(g_pMalloc, sizeof(PAGENODE));
|
||||||
if (ppgnFree && ppgn)
|
if (ppgnFree && ppgn)
|
||||||
{ /* prepare the new nodes and insert them in their respective trees */
|
{ /* prepare the new nodes and insert them in their respective trees */
|
||||||
rbtNewNode(&(ppgnFree->rbtn), paNewPage + sizeof(PAGETAB));
|
rbtNewNode(&(ppgnFree->rbtn));
|
||||||
|
ppgnFree->paPageTable = paNewPage + sizeof(PAGETAB);
|
||||||
ppgnFree->ppt = ((PPAGETAB)kaNewPage) + 1;
|
ppgnFree->ppt = ((PPAGETAB)kaNewPage) + 1;
|
||||||
RbtInsert(&g_rbtFreePageTables, (PRBTREENODE)ppgnFree);
|
RbtInsert(&g_rbtFreePageTables, ppgnFree);
|
||||||
rbtNewNode(&(ppgn->rbtn), paNewPage);
|
rbtNewNode(&(ppgn->rbtn));
|
||||||
|
ppgn->paPageTable = paNewPage;
|
||||||
ppgn->ppt = (PPAGETAB)kaNewPage;
|
ppgn->ppt = (PPAGETAB)kaNewPage;
|
||||||
RbtInsert(&(pvmctxt->rbtPageTables), (PRBTREENODE)ppgn);
|
RbtInsert(&(pvmctxt->rbtPageTables), ppgn);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ /* could not allocate both, free one if was allocated */
|
{ /* could not allocate both, free one if was allocated */
|
||||||
|
@ -712,15 +761,15 @@ static HRESULT alloc_page_table(PVMCTXT pvmctxt, PTTB pttbEntry, PTTBAUX pttbAux
|
||||||
else
|
else
|
||||||
{ /* get the first item out of the free-pages tree and reinsert it into the current VM context */
|
{ /* get the first item out of the free-pages tree and reinsert it into the current VM context */
|
||||||
ppgn = (PPAGENODE)RbtFindMin(&g_rbtFreePageTables);
|
ppgn = (PPAGENODE)RbtFindMin(&g_rbtFreePageTables);
|
||||||
RbtDelete(&g_rbtFreePageTables, ppgn->rbtn.treekey);
|
RbtDelete(&g_rbtFreePageTables, (TREEKEY)(ppgn->paPageTable));
|
||||||
rbtNewNode(&(ppgn->rbtn), ppgn->rbtn.treekey);
|
rbtNewNode(&(ppgn->rbtn));
|
||||||
RbtInsert(&(pvmctxt->rbtPageTables), (PRBTREENODE)ppgn);
|
RbtInsert(&(pvmctxt->rbtPageTables), ppgn);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{ /* prepare new page table and insert it into the TTB */
|
{ /* prepare new page table and insert it into the TTB */
|
||||||
StrSetMem(ppgn->ppt, 0, sizeof(PAGETAB));
|
StrSetMem(ppgn->ppt, 0, sizeof(PAGETAB));
|
||||||
pttbEntry->data = (PHYSADDR)(ppgn->rbtn.treekey) | uiTableFlags; /* poke new entry */
|
pttbEntry->data = ppgn->paPageTable | uiTableFlags; /* poke new entry */
|
||||||
pttbAuxEntry->data = TTBAUXFLAGS_PAGETABLE;
|
pttbAuxEntry->data = TTBAUXFLAGS_PAGETABLE;
|
||||||
*pppt = ppgn->ppt;
|
*pppt = ppgn->ppt;
|
||||||
}
|
}
|
||||||
|
@ -1066,8 +1115,10 @@ SEG_INIT_CODE void _MmInitVMMap(PSTARTUP_INFO pstartup, PMALLOC pmInitHeap)
|
||||||
g_vmctxtKernel.pTTB = (PTTB)(pstartup->kaTTB);
|
g_vmctxtKernel.pTTB = (PTTB)(pstartup->kaTTB);
|
||||||
g_vmctxtKernel.pTTBAux = (PTTBAUX)(pstartup->kaTTBAux);
|
g_vmctxtKernel.pTTBAux = (PTTBAUX)(pstartup->kaTTBAux);
|
||||||
g_vmctxtKernel.paTTB = pstartup->paTTB;
|
g_vmctxtKernel.paTTB = pstartup->paTTB;
|
||||||
rbtInitTree(&(g_vmctxtKernel.rbtPageTables), RbtStdCompareByValue);
|
rbtInitTree(&(g_vmctxtKernel.rbtPageTables), RbtStdCompareByValue, get_key_from_pagenode,
|
||||||
rbtInitTree(&g_rbtFreePageTables, RbtStdCompareByValue);
|
get_rbtreenode_from_pagenode, get_pagenode_from_rbtreenode);
|
||||||
|
rbtInitTree(&g_rbtFreePageTables, RbtStdCompareByValue, get_key_from_pagenode, get_rbtreenode_from_pagenode,
|
||||||
|
get_pagenode_from_rbtreenode);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Load all the page tables we know about. They all get mapped in as part of the kernel context, except if
|
* Load all the page tables we know about. They all get mapped in as part of the kernel context, except if
|
||||||
|
@ -1084,19 +1135,21 @@ SEG_INIT_CODE void _MmInitVMMap(PSTARTUP_INFO pstartup, PMALLOC pmInitHeap)
|
||||||
/* allocate node for first page table on page */
|
/* allocate node for first page table on page */
|
||||||
ppgn = IMalloc_Alloc(g_pMalloc, sizeof(PAGENODE));
|
ppgn = IMalloc_Alloc(g_pMalloc, sizeof(PAGENODE));
|
||||||
ASSERT(ppgn);
|
ASSERT(ppgn);
|
||||||
rbtNewNode(&(ppgn->rbtn), paPageTable);
|
rbtNewNode(&(ppgn->rbtn));
|
||||||
|
ppgn->paPageTable = paPageTable;
|
||||||
ppgn->ppt = (PPAGETAB)kaPageTable;
|
ppgn->ppt = (PPAGETAB)kaPageTable;
|
||||||
RbtInsert(&(g_vmctxtKernel.rbtPageTables), (PRBTREENODE)ppgn);
|
RbtInsert(&(g_vmctxtKernel.rbtPageTables), ppgn);
|
||||||
|
|
||||||
/* allocate node for second page table on page */
|
/* allocate node for second page table on page */
|
||||||
ppgn = IMalloc_Alloc(g_pMalloc, sizeof(PAGENODE));
|
ppgn = IMalloc_Alloc(g_pMalloc, sizeof(PAGENODE));
|
||||||
ASSERT(ppgn);
|
ASSERT(ppgn);
|
||||||
rbtNewNode(&(ppgn->rbtn), paPageTable + sizeof(PAGETAB));
|
rbtNewNode(&(ppgn->rbtn));
|
||||||
|
ppgn->paPageTable = paPageTable + sizeof(PAGETAB);
|
||||||
ppgn->ppt = ((PPAGETAB)kaPageTable) + 1;
|
ppgn->ppt = ((PPAGETAB)kaPageTable) + 1;
|
||||||
if ((i == (pstartup->cpgPageTables - 1)) && pstartup->ctblFreeOnLastPage)
|
if ((i == (pstartup->cpgPageTables - 1)) && pstartup->ctblFreeOnLastPage)
|
||||||
RbtInsert(&g_rbtFreePageTables, (PRBTREENODE)ppgn);
|
RbtInsert(&g_rbtFreePageTables, ppgn);
|
||||||
else
|
else
|
||||||
RbtInsert(&(g_vmctxtKernel.rbtPageTables), (PRBTREENODE)ppgn);
|
RbtInsert(&(g_vmctxtKernel.rbtPageTables), ppgn);
|
||||||
|
|
||||||
paPageTable += SYS_PAGE_SIZE; /* advance to next page table page */
|
paPageTable += SYS_PAGE_SIZE; /* advance to next page table page */
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user