diff options
-rw-r--r-- | lib/system/alloc.nim | 24 | ||||
-rw-r--r-- | tests/system/tdeepcopy.nim | 1 | ||||
-rw-r--r-- | tests/system/trealloc.nim | 21 |
3 files changed, 43 insertions, 3 deletions
diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim index 3a8e8a1b6..5b0955132 100644 --- a/lib/system/alloc.nim +++ b/lib/system/alloc.nim @@ -100,7 +100,8 @@ type freeChunksList: PBigChunk # XXX make this a datastructure with O(1) access chunkStarts: IntSet root, deleted, last, freeAvlNodes: PAvlNode - locked: bool # if locked, we cannot free pages. + locked, blockChunkSizeIncrease: bool # if locked, we cannot free pages. + nextChunkSize: int {.deprecated: [TLLChunk: LLChunk, TAvlNode: AvlNode, TMemRegion: MemRegion].} # shared: @@ -275,9 +276,25 @@ proc pageAddr(p: pointer): PChunk {.inline.} = #sysAssert(Contains(allocator.chunkStarts, pageIndex(result))) proc requestOsChunks(a: var MemRegion, size: int): PBigChunk = + if not a.blockChunkSizeIncrease: + a.nextChunkSize = + if a.currMem < 64 * 1024: PageSize*4 + else: a.nextChunkSize*2 + var size = size + + if size > a.nextChunkSize: + result = cast[PBigChunk](osAllocPages(size)) + else: + result = cast[PBigChunk](osTryAllocPages(a.nextChunkSize)) + if result == nil: + result = cast[PBigChunk](osAllocPages(size)) + a.blockChunkSizeIncrease = true + else: + size = a.nextChunkSize + incCurrMem(a, size) inc(a.freeMem, size) - result = cast[PBigChunk](osAllocPages(size)) + sysAssert((cast[ByteAddress](result) and PageMask) == 0, "requestOsChunks 1") #zeroMem(result, size) result.next = nil @@ -432,6 +449,9 @@ proc getBigChunk(a: var MemRegion, size: int): PBigChunk = splitChunk(a, result, size) else: result = requestOsChunks(a, size) + # if we over allocated split the chunk: + if result.size > size: + splitChunk(a, result, size) result.prevSize = 0 # XXX why is this needed? result.used = true incl(a, a.chunkStarts, pageIndex(result)) diff --git a/tests/system/tdeepcopy.nim b/tests/system/tdeepcopy.nim index 5a582425a..f7a6e87fa 100644 --- a/tests/system/tdeepcopy.nim +++ b/tests/system/tdeepcopy.nim @@ -1,6 +1,5 @@ discard """ output: "ok" - disabled: "true" """ import tables, lists diff --git a/tests/system/trealloc.nim b/tests/system/trealloc.nim new file mode 100644 index 000000000..dc5f712d6 --- /dev/null +++ b/tests/system/trealloc.nim @@ -0,0 +1,21 @@ +discard """ + output: '''success''' +""" + +# bug #4818 + +# Test that this completes without OOM. + +const BUFFER_SIZE = 5000 +var buffer = cast[ptr uint16](alloc(BUFFER_SIZE)) + +var total_size: int64 = 0 +for i in 0 .. 4000: + let size = BUFFER_SIZE * i + #echo "requesting ", size + total_size += size.int64 + buffer = cast[ptr uint16](realloc(buffer, size)) + #echo totalSize, " total: ", getTotalMem(), " occupied: ", getOccupiedMem(), " free: ", getFreeMem() + +dealloc(buffer) +echo "success" |