Exemplo n.º 1
0
        /***********************************************************************/
        /*  FUNCTION:  Treepredecessor  */
        /**/
        /*    INPUTS:  tree is the tree in question, and x is the node we want the */
        /*             the predecessor of. */
        /**/
        /*    OUTPUT:  This function returns the predecessor of x or NULL if no */
        /*             predecessor exists. */
        /**/
        /*    Modifies Input: none */
        /**/
        /*    Note:  uses the algorithm in _Introduction_To_Algorithms_ */
        /***********************************************************************/

        chunk_header *TreePredecessor(heap_header *tree, int tree_idx, chunk_header *x)
        {
            chunk_header *y;
            chunk_header *nil  = tree->nil;
            chunk_header *root = (tree_idx == 0) ? tree->root_free_chunk : tree->root_used_chunk;

            if (nil != (y = x->left))
            {     /* assignment to y is intentional */
                while (y->right != nil)
                { /* returns the maximum of the left subtree of x */
                    y = y->right;
                }
                return(y);
            }
            else
            {
                y = x->parent;
                while (x == y->left)
                {
                    if (y == root)
                    {
                        return(nil);
                    }
                    x = y;
                    y = y->parent;
                }
                return(y);
            }
        }
Exemplo n.º 2
0
        /***********************************************************************/
        /*  FUNCTION:  TreeSuccessor  */
        /**/
        /*    INPUTS:  tree is the tree in question, and x is the node we want the */
        /*             the successor of. */
        /**/
        /*    OUTPUT:  This function returns the successor of x or NULL if no */
        /*             successor exists. */
        /**/
        /*    Modifies Input: none */
        /**/
        /*    Note:  uses the algorithm in _Introduction_To_Algorithms_ */
        /***********************************************************************/

        chunk_header *TreeSuccessor(heap_header *tree, int tree_idx, chunk_header *x)
        {
            chunk_header *y;
            chunk_header *nil  = tree->nil;
            chunk_header *root = (tree_idx == 0) ? tree->root_free_chunk : tree->root_used_chunk;

            if (nil != (y = x->right))
            {     /* assignment to y is intentional */
                while (y->left != nil)
                { /* returns the minium of the right subtree of x */
                    y = y->left;
                }
                return(y);
            }
            else
            {
                y = x->parent;
                while (x == y->right)
                { /* sentinel used instead of checking for nil */
                    x = y;
                    y = y->parent;
                }
                if (y == root)
                {
                    return(nil);
                }
                return(y);
            }
        }
Exemplo n.º 3
0
        /***********************************************************************/
        /*  FUNCTION:  TreeInsertHelp  */
        /**/
        /*  INPUTS:  tree is the tree to insert into and z is the node to insert */
        /**/
        /*  OUTPUT:  none */
        /**/
        /*  Modifies Input:  tree, z */
        /**/
        /*  EFFECTS:  Inserts z into the tree as if it were a regular binary tree */
        /*            using the algorithm described in _Introduction_To_Algorithms_ */
        /*            by Cormen et al.  This funciton is only intended to be called */
        /*            by the RBTreeInsert function and not by the user */
        /***********************************************************************/

        void TreeInsertHelp(heap_header *tree, int tree_idx, chunk_header *z)
        {
            /*  This function should only be called by InsertRBTree (see above) */
            chunk_header *x;
            chunk_header *y;
            chunk_header *nil  = tree->nil;
            chunk_header *root = (tree_idx == 0) ? tree->root_free_chunk : tree->root_used_chunk;

#if DEBUG_TREE
            Formatter.Write("TreeInsertHelp: tree: ", Program.arch.DebugOutput);
            Formatter.Write((ulong)tree, "X", Program.arch.DebugOutput);
            Formatter.Write(", tree_idx: ", Program.arch.DebugOutput);
            Formatter.Write((ulong)tree_idx, "X", Program.arch.DebugOutput);
            Formatter.Write(", z: ", Program.arch.DebugOutput);
            Formatter.Write((ulong)z, "X", Program.arch.DebugOutput);
            Formatter.Write(", nil: ", Program.arch.DebugOutput);
            Formatter.Write((ulong)nil, "X", Program.arch.DebugOutput);
            Formatter.Write(", root: ", Program.arch.DebugOutput);
            Formatter.Write((ulong)root, "X", Program.arch.DebugOutput);
            Formatter.WriteLine(Program.arch.DebugOutput);
#endif

            z->left = z->right = nil;
            y       = root;
            x       = root->left;
            while (x != nil)
            {
#if DEBUG_TREE
                Formatter.Write("x: ", Program.arch.DebugOutput);
                Formatter.Write((ulong)x, "X", Program.arch.DebugOutput);
                Formatter.Write(", y: ", Program.arch.DebugOutput);
                Formatter.Write((ulong)y, "X", Program.arch.DebugOutput);
                Formatter.WriteLine(Program.arch.DebugOutput);
#endif

                y = x;
                if (1 == Compare(x, z, tree_idx))
                { /* x.key > z.key */
                    x = x->left;
                }
                else
                { /* x,key <= z.key */
                    x = x->right;
                }
            }
            z->parent = y;
            if ((y == root) ||
                (1 == Compare(y, z, tree_idx)))
            { /* y.key > z.key */
                y->left = z;
            }
            else
            {
                y->right = z;
            }
        }
Exemplo n.º 4
0
        /***********************************************************************/
        /*  FUNCTION:  LeftRotate */
        /**/
        /*  INPUTS:  This takes a tree so that it can access the appropriate */
        /*           root and nil pointers, and the node to rotate on. */
        /**/
        /*  OUTPUT:  None */
        /**/
        /*  Modifies Input: tree, x */
        /**/
        /*  EFFECTS:  Rotates as described in _Introduction_To_Algorithms by */
        /*            Cormen, Leiserson, Rivest (Chapter 14).  Basically this */
        /*            makes the parent of x be to the left of x, x the parent of */
        /*            its parent before the rotation and fixes other pointers */
        /*            accordingly. */
        /***********************************************************************/

        void LeftRotate(heap_header *tree, int tree_idx, chunk_header *x)
        {
            chunk_header *y;
            chunk_header *nil = tree->nil;

            /*  I originally wrote this function to use the sentinel for */
            /*  nil to avoid checking for nil.  However this introduces a */
            /*  very subtle bug because sometimes this function modifies */
            /*  the parent pointer of nil.  This can be a problem if a */
            /*  function which calls LeftRotate also uses the nil sentinel */
            /*  and expects the nil sentinel's parent pointer to be unchanged */
            /*  after calling this function.  For example, when RBDeleteFixUP */
            /*  calls LeftRotate it expects the parent pointer of nil to be */
            /*  unchanged. */

            y        = x->right;
            x->right = y->left;

            if (y->left != nil)
            {
                y->left->parent = x;                 /* used to use sentinel here */
            }
            /* and do an unconditional assignment instead of testing for nil */

            y->parent = x->parent;

            /* instead of checking if x->parent is the root as in the book, we */
            /* count on the root sentinel to implicitly take care of this case */
            if (x == x->parent->left)
            {
                x->parent->left = y;
            }
            else
            {
                x->parent->right = y;
            }
            y->left   = x;
            x->parent = y;
        }
Exemplo n.º 5
0
        chunk_header *search(heap_header *tree, int tree_idx, int pattern, byte *x)
        {
            /* Return the chunk that matches the given pattern value:
             *
             * 0) smallest value larger than or equal to (in-order successor of x)
             * 1) largest value smaller than or equal to (in-order predecessor of x)
             */

            /* First we do an 'pseudo-insert' on the new value and determine its would-be
             * parent and whether it would be the left or right child of that parent */

            chunk_header *parent    = null;
            int           child_idx = 0; /* 0 = left child, 1 = right child */

            chunk_header *root = (tree_idx == 0) ? tree->root_free_chunk : tree->root_used_chunk;
            chunk_header *nil  = tree->nil;

            root = root->left;
            chunk_header *src = root;

            while (src != nil)
            {
                /*Formatter.Write("gengc: search: src: ", Program.arch.DebugOutput);
                 * Formatter.Write((ulong)src, "X", Program.arch.DebugOutput);
                 * Formatter.Write(", parent: ", Program.arch.DebugOutput);
                 * Formatter.Write((ulong)src->parent, "X", Program.arch.DebugOutput);
                 * Formatter.Write(", left: ", Program.arch.DebugOutput);
                 * Formatter.Write((ulong)src->left, "X", Program.arch.DebugOutput);
                 * Formatter.Write(", right: ", Program.arch.DebugOutput);
                 * Formatter.Write((ulong)src->right, "X", Program.arch.DebugOutput);
                 * Formatter.WriteLine(Program.arch.DebugOutput);*/

                if (src == null)
                {
                    Formatter.WriteLine("gengc: search: error: src is null", Program.arch.DebugOutput);
                    Formatter.Write("gengc: tree_idx: ", Program.arch.DebugOutput);
                    Formatter.Write((ulong)tree_idx, Program.arch.DebugOutput);
                    Formatter.Write(", pattern: ", Program.arch.DebugOutput);
                    Formatter.Write((ulong)pattern, Program.arch.DebugOutput);
                    Formatter.Write(", root: ", Program.arch.DebugOutput);
                    Formatter.Write((ulong)root, "X", Program.arch.DebugOutput);
                    Formatter.Write(", nil: ", Program.arch.DebugOutput);
                    Formatter.Write((ulong)nil, "X", Program.arch.DebugOutput);
                    Formatter.WriteLine(Program.arch.DebugOutput);
                    while (true)
                    {
                        ;
                    }
                }
                byte *node_val;
                if (tree_idx == 0)
                {
                    /* free tree, sorted by length */
                    node_val = src->length;
                }
                else
                {
                    /* used tree, sorted by address */
                    node_val = (byte *)src;
                }

                if (node_val == x)
                {
                    /* We've found an exact match - return it */
                    return(src);
                }
                if (x > node_val)
                {
                    /* search to the right */
                    parent    = src;
                    child_idx = 1;
                    src       = src->right;
                }
                else
                {
                    /* search to the left */
                    parent    = src;
                    child_idx = 0;
                    src       = src->left;
                }
            }

            /* Now we have a leaf node, and know which child of its parent it is
             *
             * Look for either the in-order predecessor or successor depending on the
             * value of 'pattern'
             *
             * To do this, for successor we travel up until we find a node that is a
             * left child, then take its parent.
             *
             * For predecessor, we travel up until we find a node that is the right child
             * of its parent, then take its parent
             */

            while (pattern != child_idx)
            {
                /* go up the tree */
                chunk_header *cur_node = parent;
                parent = parent->parent;

                if (parent == nil)
                {
                    /* Couldn't find a block of the appropriate size */
                    return(null);
                }

                /* determine whether cur_node is the left or right child of parent */
                if (cur_node == parent->left)
                {
                    child_idx = 0;
                }
                else
                {
                    child_idx = 1;
                }
            }

            return(parent);
        }
Exemplo n.º 6
0
        public void Init(void *start, void *end)
        {
            sm_sizes = new int[] { 8, 16, 24, 32, 48, 64, 80, 96, 128, 192, 256, 384, 512,
                                   1024, 2048 };
            /* sm_total_counts must be a multiple of 8 */
            sm_total_counts = new int[] { 512, 256, 160, 128, 80, 64, 48, 40, 32, 16, 8, 8, 8,
                                          8, 8 };

            /* Check we have enough space for our structures */
            if (((byte *)end - (byte *)start) < 0x100000)
            {
                throw new Exception("Not enough heap space provided");
            }

            /* Sanity check */
            if (sm_sizes.Length != sm_total_counts.Length)
            {
                throw new Exception("sm_sizes and sm_total_counts are not of the same length");
            }

            heap_start = start;
            heap_end   = end;

            /* Allocate the header structure */
            hdr = (heap_header *)start;
            hdr->used_chunks = 0;
            hdr->free_chunks = 0;

            Formatter.Write("gengc: hdr = ", Program.arch.DebugOutput);
            Formatter.Write((ulong)hdr, "X", Program.arch.DebugOutput);
            Formatter.WriteLine(Program.arch.DebugOutput);

            /* Start chunks 1 page in */
            byte *cur_ptr = (byte *)start + 0x1000;

            /* Allocate the nil chunk */
            chunk_header *nil = (chunk_header *)cur_ptr;

            cur_ptr    += sizeof(chunk_header);
            nil->parent = nil;
            nil->left   = nil;
            nil->right  = nil;
            nil->red    = 0;
            nil->flags  = 0;
            nil->length = (byte *)0;
            hdr->nil    = nil;

            /* Allocate the used tree root chunk */
            chunk_header *root_u = (chunk_header *)(cur_ptr);

            cur_ptr             += sizeof(chunk_header);
            root_u->parent       = nil;
            root_u->left         = nil;
            root_u->right        = nil;
            root_u->red          = 0;
            root_u->length       = (byte *)0;
            root_u->flags        = 0;
            hdr->root_used_chunk = root_u;

            /* Allocate the free tree root chunk */
            chunk_header *root_f = (chunk_header *)(cur_ptr);

            cur_ptr             += sizeof(chunk_header);
            root_f->parent       = nil;
            root_f->left         = nil;
            root_f->right        = nil;
            root_f->red          = 0;
            root_f->length       = (byte *)0;
            root_f->flags        = 0;
            hdr->root_free_chunk = root_f;

            /* Allocate the first chunk */
            chunk_header *c = (chunk_header *)(cur_ptr);

            c->length      = (byte *)((byte *)end - (byte *)c - sizeof(chunk_header));
            c->flags       = 1 << 4; // large object
            c->lock_object = 0;

            /* Add the first chunk to the tree */
            RBTreeInsert(hdr, 0, c);


            hdr->lo_size = sm_sizes[sm_sizes.Length - 1];

            /* Allocate an array for the array of next free sm arrays */
            for (int i = 0; i < sm_sizes.Length; i++)
            {
                *get_sma_ptr(i) = null;
                *get_sm_free_ptr(i) = 0;
            }

            ready = 1;
        }
Exemplo n.º 7
0
        /***********************************************************************/
        /*  FUNCTION:  RBDelete */
        /**/
        /*    INPUTS:  tree is the tree to delete node z from */
        /**/
        /*    OUTPUT:  none */
        /**/
        /*    EFFECT:  Deletes z from tree and frees the key and info of z */
        /*             using DestoryKey and DestoryInfo.  Then calls */
        /*             RBDeleteFixUp to restore red-black properties */
        /**/
        /*    Modifies Input: tree, z */
        /**/
        /*    The algorithm from this function is from _Introduction_To_Algorithms_ */
        /***********************************************************************/

        void RBDelete(heap_header *tree, int tree_idx, chunk_header *z)
        {
            chunk_header *y;
            chunk_header *x;
            chunk_header *nil  = tree->nil;
            chunk_header *root = (tree_idx == 0) ? tree->root_free_chunk : tree->root_used_chunk;

            /* Remove from the count */
            if (tree_idx == 0)
            {
                tree->free_chunks--;
            }
            else
            {
                tree->used_chunks--;
            }

            y = ((z->left == nil) || (z->right == nil)) ? z : TreeSuccessor(tree, tree_idx, z);
            x = (y->left == nil) ? y->right : y->left;
            if (root == (x->parent = y->parent))
            { /* assignment of y->p to x->p is intentional */
                root->left = x;
            }
            else
            {
                if (y == y->parent->left)
                {
                    y->parent->left = x;
                }
                else
                {
                    y->parent->right = x;
                }
            }
            if (y != z)
            { /* y should not be nil in this case */
              /* y is the node to splice out and x is its child */

                if (y->red == 0)
                {
                    RBDeleteFixUp(tree, tree_idx, x);
                }

                //tree->DestroyKey(z->key);
                //tree->DestroyInfo(z->info);
                y->left         = z->left;
                y->right        = z->right;
                y->parent       = z->parent;
                y->red          = z->red;
                z->left->parent = z->right->parent = y;
                if (z == z->parent->left)
                {
                    z->parent->left = y;
                }
                else
                {
                    z->parent->right = y;
                }
                //free(z);
            }
            else
            {
                //tree->DestroyKey(y->key);
                //tree->DestroyInfo(y->info);
                if (y->red == 0)
                {
                    RBDeleteFixUp(tree, tree_idx, x);
                }
                //free(y);
            }
        }
Exemplo n.º 8
0
        /***********************************************************************/
        /*  FUNCTION:  RBDeleteFixUp */
        /**/
        /*    INPUTS:  tree is the tree to fix and x is the child of the spliced */
        /*             out node in RBTreeDelete. */
        /**/
        /*    OUTPUT:  none */
        /**/
        /*    EFFECT:  Performs rotations and changes colors to restore red-black */
        /*             properties after a node is deleted */
        /**/
        /*    Modifies Input: tree, x */
        /**/
        /*    The algorithm from this function is from _Introduction_To_Algorithms_ */
        /***********************************************************************/

        void RBDeleteFixUp(heap_header *tree, int tree_idx, chunk_header *x)
        {
            chunk_header *root = (tree_idx == 0) ? tree->root_free_chunk : tree->root_used_chunk;

            root = root->left;
            chunk_header *w;

            while ((x->red == 0) && (root != x))
            {
                if (x == x->parent->left)
                {
                    w = x->parent->right;
                    if (w->red == 1)
                    {
                        w->red         = 0;
                        x->parent->red = 1;
                        LeftRotate(tree, tree_idx, x->parent);
                        w = x->parent->right;
                    }
                    if ((w->right->red == 0) && (w->left->red == 0))
                    {
                        w->red = 1;
                        x      = x->parent;
                    }
                    else
                    {
                        if (w->right->red == 0)
                        {
                            w->left->red = 0;
                            w->red       = 1;
                            RightRotate(tree, tree_idx, w);
                            w = x->parent->right;
                        }
                        w->red         = x->parent->red;
                        x->parent->red = 0;
                        w->right->red  = 0;
                        LeftRotate(tree, tree_idx, x->parent);
                        x = root; /* this is to exit while loop */
                    }
                }
                else
                { /* the code below is has left and right switched from above */
                    w = x->parent->left;
                    if (w->red == 1)
                    {
                        w->red         = 0;
                        x->parent->red = 1;
                        RightRotate(tree, tree_idx, x->parent);
                        w = x->parent->left;
                    }
                    if ((w->right->red == 0) && (w->left->red == 0))
                    {
                        w->red = 1;
                        x      = x->parent;
                    }
                    else
                    {
                        if (w->left->red == 0)
                        {
                            w->right->red = 0;
                            w->red        = 1;
                            LeftRotate(tree, tree_idx, w);
                            w = x->parent->left;
                        }
                        w->red         = x->parent->red;
                        x->parent->red = 0;
                        w->left->red   = 0;
                        RightRotate(tree, tree_idx, x->parent);
                        x = root; /* this is to exit while loop */
                    }
                }
            }
            x->red = 0;
        }
Exemplo n.º 9
0
        /*  Before calling Insert RBTree the node x should have its key set */

        /***********************************************************************/
        /*  FUNCTION:  RBTreeInsert */
        /**/
        /*  INPUTS:  tree is the red-black tree to insert a node which has a key */
        /*           pointed to by key and info pointed to by info.  */
        /**/
        /*  OUTPUT:  This function returns a pointer to the newly inserted node */
        /*           which is guarunteed to be valid until this node is deleted. */
        /*           What this means is if another data structure stores this */
        /*           pointer then the tree does not need to be searched when this */
        /*           is to be deleted. */
        /**/
        /*  Modifies Input: tree */
        /**/
        /*  EFFECTS:  Creates a node node which contains the appropriate key and */
        /*            info pointers and inserts it into the tree. */
        /***********************************************************************/

        chunk_header *RBTreeInsert(heap_header *tree, int tree_idx, chunk_header *val)
        {
            chunk_header *y;
            chunk_header *x = val;
            chunk_header *newNode;
            chunk_header *root = (tree_idx == 0) ? tree->root_free_chunk : tree->root_used_chunk;

            /* Add to the count */
            if (tree_idx == 0)
            {
                tree->free_chunks++;
            }
            else
            {
                tree->used_chunks++;
            }

            TreeInsertHelp(tree, tree_idx, x);
            newNode = x;
            x->red  = 1;
            while (x->parent->red == 1)
            { /* use sentinel instead of checking for root */
                if (x->parent == x->parent->parent->left)
                {
                    y = x->parent->parent->right;
                    if (y->red == 1)
                    {
                        x->parent->red         = 0;
                        y->red                 = 0;
                        x->parent->parent->red = 1;
                        x = x->parent->parent;
                    }
                    else
                    {
                        if (x == x->parent->right)
                        {
                            x = x->parent;
                            LeftRotate(tree, tree_idx, x);
                        }
                        x->parent->red         = 0;
                        x->parent->parent->red = 1;
                        RightRotate(tree, tree_idx, x->parent->parent);
                    }
                }
                else
                { /* case for x->parent == x->parent->parent->right */
                    y = x->parent->parent->left;
                    if (y->red == 1)
                    {
                        x->parent->red         = 0;
                        y->red                 = 0;
                        x->parent->parent->red = 1;
                        x = x->parent->parent;
                    }
                    else
                    {
                        if (x == x->parent->left)
                        {
                            x = x->parent;
                            RightRotate(tree, tree_idx, x);
                        }
                        x->parent->red         = 0;
                        x->parent->parent->red = 1;
                        LeftRotate(tree, tree_idx, x->parent->parent);
                    }
                }
            }
            root->left->red = 0;
            return(newNode);
        }