Commit 676f1f2d authored by Tamar Christina's avatar Tamar Christina Committed by Ben Gamari

rts: fix Windows megablock allocator

The megablock allocator does not currently check that after aligning the
free region if it still has enough space to actually do the allocation.

This causes it to return a memory region which it didn't fully allocate
itself.  Even worse, it can cause it to return a block with a region
that will be present in two allocation pools.

This causes if you're lucky an error from the OS that you're committing
memory that has never been reserved, or causes random heap corruption.

This change makes it consider the alignment as well.

Test Plan: ./validate , testcase testmblockalloc

Reviewers: bgamari, erikd, simonmar

Reviewed By: simonmar

Subscribers: rwbarton, carter

Differential Revision: https://phabricator.haskell.org/D5363
parent 7cba71fc
......@@ -144,8 +144,11 @@ findFreeBlocks(uint32_t n) {
temp.next=free_blocks; temp.base=0; temp.size=0;
prev=&temp;
/* TODO: Don't just take first block, find smallest sufficient block */
for( ; it!=0 && it->size<required_size; prev=it, it=it->next ) {}
if(it!=0) {
for ( ; it; prev=it, it=it->next )
{
if (!it || it->size < required_size)
continue;
if( (((W_)it->base) & MBLOCK_MASK) == 0) { /* MBlock aligned */
ret = (void*)it->base;
if(it->size==required_size) {
......@@ -155,22 +158,28 @@ findFreeBlocks(uint32_t n) {
it->base += required_size;
it->size -=required_size;
}
break;
} else {
char* need_base;
block_rec* next;
int new_size;
need_base =
(char*)(((W_)it->base) & ((W_)~MBLOCK_MASK)) + MBLOCK_SIZE;
new_size = need_base - it->base;
/* Make sure that after alignment we have enough space. */
W_ total_size = new_size + required_size;
if (total_size > it->size)
continue;
next = (block_rec*)stgMallocBytes(
sizeof(block_rec)
, "getMBlocks: findFreeBlocks: splitting");
new_size = need_base - it->base;
next->base = need_base +required_size;
next->size = it->size - (new_size+required_size);
next->size = it->size - total_size;
it->size = new_size;
next->next = it->next;
it->next = next;
ret=(void*)need_base;
break;
}
}
free_blocks=temp.next;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment