private StreamWriter _sw = new StreamWriter(new MemoryStream()); //@"d:\temp\gc-log.txt"); public AutoMemoryManager(AutoMemoryManagementContext autoMemoryManagementContext, IMemoryManager underlying) { _sw.BaseStream.SetLength(0); _autoMemoryManagementContext = autoMemoryManagementContext; _underlying = underlying; _poolSize = _initialPoolSize; _pool = underlying.Alloc(_initialPoolSize).value; _defaultLayout = autoMemoryManagementContext.RuntimeGlobalAccessor.GetDefaultLayoutInfo(); _markBitFieldInfo = _defaultLayout.Fields[autoMemoryManagementContext.MarkBitFieldNumber]; _realBlockSizeFieldInfo = _defaultLayout.Fields[autoMemoryManagementContext.RealBlockSizeFieldNumber]; MMFreeBlockHeader *item = (MMFreeBlockHeader *)_pool; item->next = MMFreeBlockHeader.ZeroPtr; item->size = _poolSize - sizeof(MMFreeBlockHeader); _freeBlocks = item; _stats.currentAllocatedBlocksCount = 0; _stats.currentAllocatedBytes = 0; _stats.currentAllBlocksCount = 1; _stats.currentAvailableBytes = _poolSize; _stats.totalBlocksCreated = 1; _stats.totalBlocksMerged = 0; _stats.totalBlocksAllocated = 0; _stats.totalBlocksFreed = 0; }
private void Sweep(IntPtr heapStart, IntPtr heapEnd) { var blocksToRecycle = new List <BlockPtr>(); MMFreeBlockHeader *freePtr = _freeBlocks; var ptr = new BlockPtr(heapStart); do { BlockPtr nextPtr; bool isFree = new IntPtr(freePtr) == ptr.value; if (_knownBlocks.Contains(ptr)) { Console.WriteLine("C"); } else if (!isFree) { Console.WriteLine("NC"); } if (isFree) { nextPtr = new BlockPtr(ptr.value + freePtr->size + sizeof(MMFreeBlockHeader)); freePtr = freePtr->next; } else { if (this.IsGarbage(ptr)) { blocksToRecycle.Add(ptr); } else { this.SetMark(ptr, false); } nextPtr = new BlockPtr(ptr.value + this.GetBlockSize(ptr.value)); } if (freePtr < nextPtr.value.ToPointer() && freePtr != (void *)0) { throw new InvalidOperationException(); } ptr = nextPtr; } while (ptr.value.ToPointer() < heapEnd.ToPointer()); blocksToRecycle.ForEach(p => this.Free(p)); }
private void Expand() { var newPool = _underlying.Alloc(_poolSize).value; if (newPool == IntPtr.Zero) { throw new OutOfMemoryException("Failed to expand memory pool"); } MMFreeBlockHeader *item = (MMFreeBlockHeader *)newPool; item->next = MMFreeBlockHeader.ZeroPtr; item->size = _poolSize - sizeof(MMFreeBlockHeader); this.InsertFreeBlockToList(item); }
bool TryMergeFreeBlocks(MMFreeBlockHeader *first, MMFreeBlockHeader *second) { if (((int)first) + first->size + sizeof(MMFreeBlockHeader) == (int)second) { first->size += sizeof(MMFreeBlockHeader) + second->size; _stats.currentAllBlocksCount--; _stats.currentAvailableBytes += sizeof(MMBusyBlockHeader); _stats.totalBlocksMerged++; return(true); } else { return(false); } }
private void Expand() { var poolSize = _poolSize; var poolHeaderOffset = poolSize.AlignTo(Alignment); var newPool = _underlyingMM.Alloc((poolHeaderOffset + sizeof(MMPool)).AlignTo(Alignment)).value; if (newPool == IntPtr.Zero) { throw new OutOfMemoryException("Failed to expand memory pool"); } MMFreeBlockHeader *item = (MMFreeBlockHeader *)newPool; item->next = MMFreeBlockHeader.ZeroPtr; item->size = poolSize - sizeof(MMFreeBlockHeader); this.InsertFreeBlockToList(item); MMPool *poolHeader = (MMPool *)(((int)newPool) + poolHeaderOffset); poolHeader->next = _pools; poolHeader->rangePtr = newPool; poolHeader->size = poolSize; _pools = poolHeader; }
void *InternalAlloc(int size) { MMFreeBlockHeader *pprev; MMFreeBlockHeader *p; MMFreeBlockHeader *next; MMBusyBlockHeader *ret; int retSize; // size += (MM_ALIGNMENT - ((size - 1) % MM_ALIGNMENT)) - 1; size = size.AlignTo(Alignment); pprev = MMFreeBlockHeader.ZeroPtr; p = _freeBlocks; while (p != MMFreeBlockHeader.ZeroPtr) { if (p->size + sizeof(MMFreeBlockHeader) - sizeof(MMBusyBlockHeader) >= size) { if (p->size + sizeof(MMFreeBlockHeader) - sizeof(MMBusyBlockHeader) - size > sizeof(MMFreeBlockHeader)) { MMFreeBlockHeader *newBlock = (MMFreeBlockHeader *)(((int)p) + (sizeof(MMBusyBlockHeader) + size)); newBlock->size = (p->size + sizeof(MMFreeBlockHeader)) - (sizeof(MMBusyBlockHeader) + size) - sizeof(MMFreeBlockHeader); newBlock->next = p->next; p->size = sizeof(MMBusyBlockHeader) + size - sizeof(MMFreeBlockHeader); p->next = newBlock; _stats.currentAllBlocksCount++; _stats.currentAvailableBytes -= sizeof(MMBusyBlockHeader); _stats.totalBlocksCreated++; } next = p->next; if (pprev == MMFreeBlockHeader.ZeroPtr && next == MMFreeBlockHeader.ZeroPtr) { _freeBlocks = MMFreeBlockHeader.ZeroPtr; } if (pprev == MMFreeBlockHeader.ZeroPtr) { _freeBlocks = next; } else if (next == MMFreeBlockHeader.ZeroPtr) { pprev->next = MMFreeBlockHeader.ZeroPtr; } else { pprev->next = next; } retSize = p->size + sizeof(MMFreeBlockHeader) - sizeof(MMBusyBlockHeader); ret = (MMBusyBlockHeader *)p; ret->size = retSize; _stats.currentAllocatedBytes += ret->size; _stats.currentAllocatedBlocksCount++; _stats.currentAvailableBytes -= ret->size; _stats.totalBlocksAllocated++; return((void *)(((int)ret) + sizeof(MMBusyBlockHeader))); } pprev = p; p = p->next; } return(MMFreeBlockHeader.ZeroPtr); }
void InsertFreeBlockToList(MMFreeBlockHeader *block) { if (_freeBlocks == MMFreeBlockHeader.ZeroPtr) { _freeBlocks = block; } else { MMFreeBlockHeader *p = _freeBlocks; MMFreeBlockHeader *pprev = MMFreeBlockHeader.ZeroPtr; while (p != MMFreeBlockHeader.ZeroPtr) { if (p > block) { break; } pprev = p; p = p->next; } // insert before p, after pprev if (pprev == MMFreeBlockHeader.ZeroPtr) // try merge [block, p] { if (TryMergeFreeBlocks(block, p)) { block->next = p->next; _freeBlocks = block; } else { block->next = p; _freeBlocks = block; } } else if (p == MMFreeBlockHeader.ZeroPtr) // try merge [pprev, block] { if (TryMergeFreeBlocks(pprev, block)) { // do nothing } else { pprev->next = block; block->next = MMFreeBlockHeader.ZeroPtr; } } else // try merge [pprev, block] and [block, p] { if (TryMergeFreeBlocks(pprev, block)) { if (TryMergeFreeBlocks(pprev, p)) { pprev->next = p->next; } } else { if (TryMergeFreeBlocks(block, p)) { pprev->next = block; block->next = p->next; } else { pprev->next = block; block->next = p; } } } } }
private IntPtr InternalAlloc(int size) { MMFreeBlockHeader *pprev; MMFreeBlockHeader *p; MMFreeBlockHeader *next; IntPtr ret; int retSize; size += (_alignment - ((size - 1) % _alignment)) - 1; pprev = MMFreeBlockHeader.ZeroPtr; p = _freeBlocks; while (p != MMFreeBlockHeader.ZeroPtr) { if (p->size + sizeof(MMFreeBlockHeader) >= size) { if (p->size + sizeof(MMFreeBlockHeader) - size > sizeof(MMFreeBlockHeader)) { MMFreeBlockHeader *newBlock = (MMFreeBlockHeader *)(((int)p) + size); newBlock->size = (p->size + sizeof(MMFreeBlockHeader)) - size - sizeof(MMFreeBlockHeader); newBlock->next = p->next; p->size = size - sizeof(MMFreeBlockHeader); p->next = newBlock; _stats.currentAllBlocksCount++; //_stats.currentAvailableBytes -= sizeof(MMBusyBlockHeader); _stats.totalBlocksCreated++; } next = p->next; if (pprev == MMFreeBlockHeader.ZeroPtr && next == MMFreeBlockHeader.ZeroPtr) { _freeBlocks = MMFreeBlockHeader.ZeroPtr; } if (pprev == MMFreeBlockHeader.ZeroPtr) { _freeBlocks = next; } else if (next == MMFreeBlockHeader.ZeroPtr) { pprev->next = MMFreeBlockHeader.ZeroPtr; } else { pprev->next = next; } retSize = p->size + sizeof(MMFreeBlockHeader); ret = new IntPtr(p); this.SetBlockSize(ret, retSize); _stats.currentAllocatedBytes += retSize; _stats.currentAllocatedBlocksCount++; _stats.currentAvailableBytes -= retSize; _stats.totalBlocksAllocated++; return(ret); } pprev = p; p = p->next; } return(IntPtr.Zero); }