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