modified rbtree code to not need the local key value; also set compiler to treat all warnings as errors

This commit is contained in:
Eric J. Bowersox 2013-06-07 21:31:32 -06:00
parent 0a31211d96
commit 3f4e807025
6 changed files with 195 additions and 80 deletions

View File

@ -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.

View File

@ -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;

View File

@ -57,48 +57,56 @@ typedef INT32 (*PFNTREECOMPARE)(TREEKEY, TREEKEY);
/* The basic tree node. */ /* The basic tree node. */
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)
#define rbtSetNodeRight(ptn, ptnR) \ #define rbtSetNodeRight(ptn, ptnR) \
do { (ptn)->ptnRightColor = (((UINT_PTR)(ptnR)) & ~1) | ((ptn)->ptnRightColor & 1); } while (0) do { (ptn)->ptnRightColor = (((UINT_PTR)(ptnR)) & ~1) | ((ptn)->ptnRightColor & 1); } while (0)
#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 */
PRBTREENODE ptnRoot; /* pointer to root of tree */ 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 */
} 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);

View File

@ -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;

View File

@ -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);
} }

View File

@ -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 */
} }