Beispiel #1
0
        //////////////////////////////////// Allocation and Free Routines.
        //
        // Allocation is optimized for the case where an allocation starts
        // with a relatively small amount of memory and grows over time.
        // This is exactly the behavior exhibited by stacks and GC heaps.
        //
        // The allocation strategy also works well for large initial
        // allocations.  The strategy would be very inefficient if a very
        // large number of small, completely independent allocations are
        // made.
        //
        // AllocateMemory(size) performs an initial allocation.
        // AllocateMemory(startAddr, size) performs growing allocations.
        //
        internal static unsafe UIntPtr AllocateMemory(UIntPtr size)
        {
            VTable.Assert(PageTable.PageAligned(size));
#if SINGULARITY_KERNEL
            UIntPtr addr = Sing_MemoryManager.KernelAllocate(
                Sing_MemoryManager.PagesFromBytes(size),
                Process.kernelProcess, 0, PageType.Unknown);
#elif SINGULARITY_PROCESS
            UIntPtr addr = PageTableService.Allocate(size);
#endif

#if SINGULARITY_KERNEL
            Kernel.Waypoint((int)size);
            Kernel.Waypoint(811);
#endif // SINGULARITY_KERNEL

            if (addr != UIntPtr.Zero)
            {
                Util.MemClear(addr, size);
            }
            return(addr);
        }
        internal unsafe HandleEntry *AllocateEntry()
        {
            HandleEntry *entry = AllocateExisting();

            if (entry != null)
            {
                return(entry);
            }

#if SINGULARITY_KERNEL
            Kernel.Waypoint(830);
#endif // SINGULARITY_KERNEL
            // Need to allocate a new page.
            HandlePage *page
                = (HandlePage *)MemoryManager.KernelAllocate(
                      1, process, 0, PageType.Shared);

#if SINGULARITY_KERNEL
            Kernel.Waypoint(831);
#endif // SINGULARITY_KERNEL

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

            // Get the bounds.
            HandleEntry *beg = ((HandleEntry *)(page + 1));
            HandleEntry *end = beg + handlesPerPage - 1;

            // Save off the first entry to return.
            entry = beg++;
            entry->Set(null);
            entry->next = null;

            // Initialize the free list in the rest of the entries.
            for (HandleEntry *step = beg; step < end; step++)
            {
                step->Set(null);
                step->next = step + 1;
            }
            end->Set(null);
            end->next = null;

            // Initialize the page header and insert into the page list.
            page->SetTable(this);
            page->next = null;
            HandlePage *last;
            do
            {
                last       = pages;
                page->next = last;

                // Interlocked.CompareExchange only updates pages if it hasn't
                // changed within this loop.
            } while (last != Interlocked.CompareExchange(ref pages, page, last));

            // Then insert into the free list.
            HandleEntry *next;
            do
            {
                next      = freeList;
                end->next = next;

                // Interlocked.CompareExchange only updates freeList if it hasn't
                // changed with this loop.
            } while (next != Interlocked.CompareExchange(ref freeList, beg, next));

            Interlocked.Increment(ref pageCount);

            return(entry);
        }