Example #1
0
        int Compare(chunk_header *a, chunk_header *b, int tree_idx)
        {
            /* Compare(a, b) should return 1 if a > b, -1 if a < b, 0 if equal */

            if (tree_idx == 0)
            {
                /* free tree, sorted by length */
                if (a->length > b->length)
                {
                    return(1);
                }
                if (a->length < b->length)
                {
                    return(-1);
                }
                return(0);
            }
            else
            {
                /* used tree, sorted by address */
                if (a > b)
                {
                    return(1);
                }
                if (a < b)
                {
                    return(-1);
                }
                else
                {
                    return(0);
                }
            }
        }
Example #2
0
        private void allocate_root_block()
        {
            /* Default each root block to store 1024 root definitions
             * Each definition is a start and end pointer, thus size of block
             * is sizeof(root_header) + 2 * 1024 * sizeof(byte *)
             */

            chunk_header *chk = allocate_chunk(sizeof(root_header) + 2048 * sizeof(byte *));

            if (chk == null)
            {
                Formatter.WriteLine("gengc: add_root_block: allocate_chunk() returned null",
                                    Program.arch.DebugOutput);
                libsupcs.OtherOperations.Halt();
            }
            chk->flags &= ~(1 << 4);        // not large block
            chk->flags |= 1 << 5;           // is root block

            root_header *r = (root_header *)((byte *)chk + sizeof(chunk_header));

            r->next     = hdr->roots;
            r->capacity = 1024;
            r->size     = 0;

            hdr->roots = r;
        }
Example #3
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);
            }
        }
Example #4
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);
            }
        }
Example #5
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;
            }
        }
Example #6
0
        /** <summary>Get the colour of a particular object</summary> */
        int GetColour(void *obj)
        {
            /* This is the same algorithm as used in gery_object
             *
             * First, get the chunk that contains the object */

            chunk_header *chk = search(hdr, 1, 1, (byte *)obj);

            if (chk == null)
            {
                return(-1);
            }

            byte *chk_start = (byte *)chk + sizeof(chunk_header);
            byte *chk_end   = chk_start + (int)chk->length;

            if (obj >= chk_start && obj < chk_end)
            {
                /* obj points into this chunk - check if its a large object,
                 * small object or something else (e.g. root pointer) */
                if ((chk->flags & 0x30) == 0x10)
                {
                    /* large object  */
                    return(chk->flags & 0x3);
                }
                else if ((chk->flags & 0x30) == 0x0)
                {
                    /* small object - we need to identify its index in the array */
                    sma_header *smhdr      = (sma_header *)((byte *)chk + sizeof(chunk_header));
                    byte *      data_start = (byte *)smhdr + sizeof(sma_header) +
                                             smhdr->total_count * 4;

                    if (obj >= data_start)
                    {
                        /* valid small object (i.e. not a pointer to within the small
                         * object block itself)
                         */

                        int idx      = (int)(((byte *)obj - data_start) / smhdr->obj_length);
                        int uint_idx = idx / 8;
                        int bit_idx  = idx % 8;

                        uint *uint_ptr = (uint *)((byte *)smhdr + sizeof(sma_header) +
                                                  uint_idx * 4);

                        return((int)(((*uint_ptr) >> (bit_idx * 4)) & 0x3));
                    }
                }
            }

            return(-1);
        }
Example #7
0
        private unsafe void *allocate_sma_header(sma_header **sma_ptr, int sm_index)
        {
            sma_header *old_entry  = *sma_ptr;
            int         obj_length = sm_sizes[sm_index];
            int         obj_count  = sm_total_counts[sm_index];

            chunk_header *c = allocate_chunk(sizeof(sma_header) + obj_count * 4 +
                                             obj_count * obj_length);

            if (c == null)
            {
                return(null);
            }

            /* Set as small object */
            c->flags &= ~(1 << 4);

            /* Fill in the header */
            sma_header *h = (sma_header *)((byte *)c + sizeof(chunk_header));

            h->obj_length        = obj_length;
            h->free_count        = obj_count;
            h->total_count       = obj_count;
            h->next              = old_entry;
            h->global_free_count = get_sm_free_ptr(sm_index);

            /* Add our free blocks to the total free count */
            *get_sm_free_ptr(sm_index) += obj_count;

            /* Set all memory as free */
            for (int i = 0; i < obj_count; i += 8)
            {
                /* Each 32-bit test uint covers 8 entries of 4 bits */
                uint *test = (uint *)((byte *)h + sizeof(sma_header) +
                                      i * 4);
                *test = 0;
            }

            // TODO: ?zero the returned memory block

            *sma_ptr = h;

            return(h);
        }
Example #8
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;
        }
Example #9
0
        private unsafe void grey_object(byte *obj_start, byte *obj_end)
        {
#if GENGC_DEBUG
            Formatter.Write("gengc: greying object from ", Program.arch.DebugOutput);
            Formatter.Write((ulong)obj_start, "X", Program.arch.DebugOutput);
            Formatter.Write(" to ", Program.arch.DebugOutput);
            Formatter.Write((ulong)obj_end, "X", Program.arch.DebugOutput);
            Formatter.WriteLine(Program.arch.DebugOutput);
#endif

            byte **cur_ptr = (byte **)obj_start;
            while ((byte *)cur_ptr + sizeof(void *) <= obj_end)
            {
                byte *obj = *cur_ptr;

#if GENGC_DEBUG
                Formatter.Write("gengc: grey_object: member at: ", Program.arch.DebugOutput);
                Formatter.Write((ulong)cur_ptr, "X", Program.arch.DebugOutput);
                Formatter.Write(" is: ", Program.arch.DebugOutput);
                Formatter.Write((ulong)obj, "X", Program.arch.DebugOutput);
                Formatter.WriteLine(Program.arch.DebugOutput);
#endif

                /* First, check its at all valid (i.e. points within the heap) */
                if (obj >= heap_start && obj < heap_end)
                {
#if GENGC_DEBUG
                    Formatter.Write("gengc: grey_object: object has member ", Program.arch.DebugOutput);
                    Formatter.Write((ulong)obj, "X", Program.arch.DebugOutput);
                    Formatter.WriteLine(" which is potentially within the heap", Program.arch.DebugOutput);
#endif

                    /* Now get the chunk that contains it in the used tree */
                    chunk_header *chk = search(hdr, 1, 1, obj);

                    if (chk != null)
                    {
                        byte *chk_start = (byte *)chk + sizeof(chunk_header);
                        byte *chk_end   = chk_start + (int)chk->length; // cannot add byte* to byte*

                        if (obj >= chk_start && obj < chk_end)
                        {
                            /* obj points into this chunk - check if its a large object,
                             * small object or something else (e.g. root pointer) */
                            if ((chk->flags & 0x30) == 0x10)
                            {
                                /* large object - we grey it if it is white */
                                if ((chk->flags & 0x3) == 0x1)
                                {
                                    chk->flags |= 0x2;
                                }
                            }
                            else if ((chk->flags & 0x30) == 0x0)
                            {
                                /* small object - we need to identify its index in the array */
                                sma_header *smhdr      = (sma_header *)((byte *)chk + sizeof(chunk_header));
                                byte *      data_start = (byte *)smhdr + sizeof(sma_header) +
                                                         smhdr->total_count * 4;

                                if (data_start > obj)
                                {
#if GENGC_DEBUG
                                    Formatter.Write("gengc: grey_object: object reference points to within sma_header, ignoring (obj: ", Program.arch.DebugOutput);
                                    Formatter.Write((ulong)obj, "X", Program.arch.DebugOutput);
                                    Formatter.Write(", data_start: ", Program.arch.DebugOutput);
                                    Formatter.Write((ulong)data_start, "X", Program.arch.DebugOutput);
                                    Formatter.Write(", total_count: ", Program.arch.DebugOutput);
                                    Formatter.Write((ulong)smhdr->total_count, Program.arch.DebugOutput);
                                    Formatter.Write(", obj_length: ", Program.arch.DebugOutput);
                                    Formatter.Write((ulong)smhdr->obj_length, Program.arch.DebugOutput);
                                    Formatter.WriteLine(")", Program.arch.DebugOutput);
#endif
                                }
                                else
                                {
                                    int idx      = (int)((obj - data_start) / smhdr->obj_length);
                                    int uint_idx = idx / 8;
                                    int bit_idx  = idx % 8;

                                    uint *uint_ptr = (uint *)((byte *)smhdr + sizeof(sma_header) +
                                                              uint_idx * 4);

                                    uint flag_pattern  = 0x3U << (bit_idx * 4);
                                    uint white_pattern = 0x1U << (bit_idx * 4);
                                    uint grey_pattern  = 0x2U << (bit_idx * 4);

                                    if ((*uint_ptr & flag_pattern) == white_pattern)
                                    {
                                        *uint_ptr |= grey_pattern;
                                    }
                                }
                            }
                        }
                    }
                }

                //cur_ptr++;
                cur_ptr = (byte **)(((byte *)cur_ptr) + 4);
            }
        }
Example #10
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);
        }
Example #11
0
        private unsafe chunk_header *allocate_chunk(int length)
        {
            /* Find the smallest chunk larger than or equal to length
             *
             * Perform an insertion operation on a new node of length l,
             * - if during the insert we come across a chunk of the exact
             *      length, ues it
             * - else, then look for the in-order predecessor of the new node
             * (don't actually add the new node to the tree though)
             * Remove the identified chunk
             *
             * Then, split the chunk if required, add the used bit to the used
             * tree and the remaining bit to the free tree */

            int act_length = util.align(length, 32);

            chunk_header *chk = search(hdr, 0, 0, (byte *)act_length);

            if (chk == null)
            {
                Formatter.WriteLine("gengc: allocate_chunk(): search() returned null",
                                    Program.arch.DebugOutput);
                libsupcs.OtherOperations.Halt();
            }
            if (chk->length < (byte *)length)
            {
                Formatter.Write("gengc: allocate_chunk(): search() returned too small a chunk (",
                                Program.arch.DebugOutput);
                Formatter.Write((ulong)chk->length, Program.arch.DebugOutput);
                Formatter.Write(") when ", Program.arch.DebugOutput);
                Formatter.Write((ulong)length, Program.arch.DebugOutput);
                Formatter.WriteLine(" was requested", Program.arch.DebugOutput);
                libsupcs.OtherOperations.Halt();
            }

            /* Remove the chunk from the free tree */
            RBDelete(hdr, 0, chk);

            if (chk->length - act_length > (byte *)hdr->lo_size)
            {
                /* There is enough space to split our chunk - build a new free chunk */
                chunk_header *free_chk = (chunk_header *)((byte *)chk + sizeof(chunk_header)
                                                          + act_length);

                free_chk->parent      = hdr->nil;
                free_chk->left        = hdr->nil;
                free_chk->right       = hdr->nil;
                free_chk->flags       = 1 << 4;
                free_chk->lock_object = 0;
                free_chk->red         = 0;
                free_chk->length      = chk->length - act_length - sizeof(chunk_header);

                RBTreeInsert(hdr, 0, free_chk);
            }

            /* Build the chunk denoting a used block */
            chk->length      = (byte *)act_length;
            chk->parent      = hdr->nil;
            chk->left        = hdr->nil;
            chk->right       = hdr->nil;
            chk->lock_object = 0;
            chk->flags       = 1 << 4 | 1; // large block, white

            chk->red = 0;

            RBTreeInsert(hdr, 1, chk);

            return(chk);
        }
Example #12
0
        public void *Alloc(int length)
        {
            /* Wait for all other allocations and collections to complete */
            var state = libsupcs.OtherOperations.EnterUninterruptibleSection();

            bool can_continue = false;

            while (can_continue == false)
            {
                libsupcs.Monitor.Enter(collection_mutex);
                {
                    if (collection_in_progress == false && alloc_in_progress == false)
                    {
                        alloc_in_progress = true;
                        can_continue      = true;
                    }
                }
                libsupcs.Monitor.Exit(collection_mutex);
            }

            /* Increase the allocation counter */
            allocs++;

            /* Decide if we want a large or small object */
            if (length > hdr->lo_size)
            {
                chunk_header *c = allocate_chunk(length);
                alloc_in_progress = false;

                if (c == null)
                {
                    return(null);
                }
                var ret = (void *)((byte *)c + sizeof(chunk_header));
                libsupcs.OtherOperations.ExitUninterruptibleSection(state);
                return(ret);
            }
            else
            {
                /* Small object */
                int sm_index = get_size_index(length);
                if (sm_index < 0)
                {
                    alloc_in_progress = false;
                    return(null);
                }

                /* Get first sma_header */
                sma_header **sma_ptr     = get_sma_ptr(sm_index);
                int *        sm_free_ptr = get_sm_free_ptr(sm_index);

                /* Ensure there is free space of the appropriate size */
                if (*sm_free_ptr == 0)
                {
                    allocate_sma_header(sma_ptr, sm_index);
                }

                /* Allocate space */
                void *ret = allocate_small_object(*sma_ptr, sm_index);

                if (ret == null)
                {
                    Formatter.Write("gengc: allocate_small_object failed.  sm_free_ptr = ", Program.arch.DebugOutput);
                    Formatter.Write((ulong)*sm_free_ptr, Program.arch.DebugOutput);
                    Formatter.Write(".  Trying again... ", Program.arch.DebugOutput);

                    allocate_sma_header(sma_ptr, sm_index);
                    ret = allocate_small_object(*sma_ptr, sm_index);

                    if (ret == null)
                    {
                        Formatter.WriteLine("failed again", Program.arch.DebugOutput);
                    }
                    else
                    {
                        Formatter.WriteLine("succeeded", Program.arch.DebugOutput);
                    }
                }
                alloc_in_progress = false;
                libsupcs.OtherOperations.ExitUninterruptibleSection(state);
                return(ret);
            }
        }
Example #13
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;
        }
Example #14
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);
            }
        }
Example #15
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;
        }
Example #16
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);
        }