Esempio n. 1
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);
        }
Esempio n. 2
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);
            }
        }