diff options
-rw-r--r-- | lib/system/alloc.nim | 28 | ||||
-rw-r--r-- | tests/fragmentation/tfragment_alloc.nim | 4 |
2 files changed, 30 insertions, 2 deletions
diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim index 33e7b3898..4291013a2 100644 --- a/lib/system/alloc.nim +++ b/lib/system/alloc.nim @@ -29,6 +29,8 @@ const FliOffset = 6 RealFli = MaxFli - FliOffset + HugeChunkSize = int high(int32) - 1 # 2 GB, depends on TLSF's impl + type PTrunk = ptr Trunk Trunk = object @@ -593,6 +595,26 @@ proc getBigChunk(a: var MemRegion, size: int): PBigChunk = incl(a, a.chunkStarts, pageIndex(result)) dec(a.freeMem, size) +proc getHugeChunk(a: var MemRegion; size: int): PBigChunk = + result = cast[PBigChunk](osAllocPages(size)) + incCurrMem(a, size) + # XXX add this to the heap links. But also remove it from it later. + when false: a.addHeapLink(result, size) + sysAssert((cast[ByteAddress](result) and PageMask) == 0, "getHugeChunk") + result.next = nil + result.prev = nil + result.size = size + # set 'used' to to true: + result.prevSize = 1 + incl(a, a.chunkStarts, pageIndex(result)) + +proc freeHugeChunk(a: var MemRegion; c: PBigChunk) = + let size = c.size + sysAssert(size >= HugeChunkSize, "freeHugeChunk: invalid size") + excl(a.chunkStarts, pageIndex(c)) + decCurrMem(a, size) + osDeallocPages(c, size) + proc getSmallChunk(a: var MemRegion): PSmallChunk = var res = getBigChunk(a, PageSize) sysAssert res.prev == nil, "getSmallChunk 1" @@ -759,7 +781,8 @@ proc rawAlloc(a: var MemRegion, requestedSize: int): pointer = else: size = requestedSize + bigChunkOverhead() # roundup(requestedSize+bigChunkOverhead(), PageSize) # allocate a large block - var c = getBigChunk(a, size) + var c = if size >= HugeChunkSize: getHugeChunk(a, size) + else: getBigChunk(a, size) sysAssert c.prev == nil, "rawAlloc 10" sysAssert c.next == nil, "rawAlloc 11" result = addr(c.data) @@ -823,7 +846,8 @@ proc rawDealloc(a: var MemRegion, p: pointer) = sysAssert a.occ >= 0, "rawDealloc: negative occupied memory (case B)" a.deleted = getBottom(a) del(a, a.root, cast[int](addr(c.data))) - freeBigChunk(a, c) + if c.size >= HugeChunkSize: freeHugeChunk(a, c) + else: freeBigChunk(a, c) sysAssert(allocInv(a), "rawDealloc: end") when logAlloc: cprintf("dealloc(pointer_%p)\n", p) diff --git a/tests/fragmentation/tfragment_alloc.nim b/tests/fragmentation/tfragment_alloc.nim index 031588d27..5a44b7434 100644 --- a/tests/fragmentation/tfragment_alloc.nim +++ b/tests/fragmentation/tfragment_alloc.nim @@ -15,6 +15,10 @@ proc main = quit "could not serve request!" dealloc p # c_fprintf(stdout, "iteration: %ld size: %ld\n", i, size) + when defined(cpu64): + # bug #7120 + var x = alloc(((1 shl 29) - 4) * 8) + dealloc x main() |