fixes #4818
This commit is contained in:
parent
4561d70632
commit
39ca8b8c8e
3 changed files with 43 additions and 3 deletions
|
|
@ -100,7 +100,8 @@ type
|
||||||
freeChunksList: PBigChunk # XXX make this a datastructure with O(1) access
|
freeChunksList: PBigChunk # XXX make this a datastructure with O(1) access
|
||||||
chunkStarts: IntSet
|
chunkStarts: IntSet
|
||||||
root, deleted, last, freeAvlNodes: PAvlNode
|
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].}
|
{.deprecated: [TLLChunk: LLChunk, TAvlNode: AvlNode, TMemRegion: MemRegion].}
|
||||||
|
|
||||||
# shared:
|
# shared:
|
||||||
|
|
@ -275,9 +276,25 @@ proc pageAddr(p: pointer): PChunk {.inline.} =
|
||||||
#sysAssert(Contains(allocator.chunkStarts, pageIndex(result)))
|
#sysAssert(Contains(allocator.chunkStarts, pageIndex(result)))
|
||||||
|
|
||||||
proc requestOsChunks(a: var MemRegion, size: int): PBigChunk =
|
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)
|
incCurrMem(a, size)
|
||||||
inc(a.freeMem, size)
|
inc(a.freeMem, size)
|
||||||
result = cast[PBigChunk](osAllocPages(size))
|
|
||||||
sysAssert((cast[ByteAddress](result) and PageMask) == 0, "requestOsChunks 1")
|
sysAssert((cast[ByteAddress](result) and PageMask) == 0, "requestOsChunks 1")
|
||||||
#zeroMem(result, size)
|
#zeroMem(result, size)
|
||||||
result.next = nil
|
result.next = nil
|
||||||
|
|
@ -432,6 +449,9 @@ proc getBigChunk(a: var MemRegion, size: int): PBigChunk =
|
||||||
splitChunk(a, result, size)
|
splitChunk(a, result, size)
|
||||||
else:
|
else:
|
||||||
result = requestOsChunks(a, size)
|
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.prevSize = 0 # XXX why is this needed?
|
||||||
result.used = true
|
result.used = true
|
||||||
incl(a, a.chunkStarts, pageIndex(result))
|
incl(a, a.chunkStarts, pageIndex(result))
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
discard """
|
discard """
|
||||||
output: "ok"
|
output: "ok"
|
||||||
disabled: "true"
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import tables, lists
|
import tables, lists
|
||||||
|
|
|
||||||
21
tests/system/trealloc.nim
Normal file
21
tests/system/trealloc.nim
Normal file
|
|
@ -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"
|
||||||
Loading…
Add table
Add a link
Reference in a new issue