Skip to content

Commit

Permalink
ntdll: Implement Low Fragmentation Heap frontend.
Browse files Browse the repository at this point in the history
This implements the reduced fragmentation from the heap frontend, by
carving smaller blocks out of larger allocated blocks.

The super block and each sub-block are all flagged with BLOCK_FLAG_LFH.

The super-block (struct group) uses a standard struct block header, as
well as a list entry to be linked in free list, and a free bit map to
track free sub-blocks.

Sub-blocks reference their super block through the base_offset, instead
of the subheap, using the block size as radix.

(cherry picked from commit 27665f3)
  • Loading branch information
rbernon authored and ivyl committed Apr 17, 2023
1 parent 95497e8 commit f71b8c0
Show file tree
Hide file tree
Showing 2 changed files with 277 additions and 19 deletions.
20 changes: 8 additions & 12 deletions dlls/kernel32/tests/heap.c
Original file line number Diff line number Diff line change
Expand Up @@ -986,6 +986,7 @@ static void test_HeapCreate(void)
ok( entries[0].cbData <= 0x1000 /* sizeof(*heap) */, "got cbData %#lx\n", entries[0].cbData );
ok( entries[0].cbOverhead == 0, "got cbOverhead %#x\n", entries[0].cbOverhead );
ok( entries[0].iRegionIndex == 0, "got iRegionIndex %d\n", entries[0].iRegionIndex );
todo_wine /* Wine currently reports the LFH group as a single block here */
ok( entries[1].wFlags == 0, "got wFlags %#x\n", entries[1].wFlags );

for (i = 0; i < 0x12; i++)
Expand Down Expand Up @@ -1066,6 +1067,7 @@ static void test_HeapCreate(void)
for (i = 1; i < count - 2; i++)
{
if (entries[i].wFlags != PROCESS_HEAP_ENTRY_BUSY) continue;
todo_wine /* Wine currently reports the LFH group as a single block */
ok( entries[i].cbData == 0x18 + 2 * sizeof(void *), "got cbData %#lx\n", entries[i].cbData );
ok( entries[i].cbOverhead == 0x8, "got cbOverhead %#x\n", entries[i].cbOverhead );
}
Expand Down Expand Up @@ -1691,9 +1693,7 @@ static void test_GlobalAlloc(void)
ok( size == small_size, "GlobalSize returned %Iu\n", size );
SetLastError( 0xdeadbeef );
tmp_mem = GlobalReAlloc( mem, small_size, 0 );
todo_wine
ok( !tmp_mem, "GlobalReAlloc succeeded\n" );
todo_wine
ok( GetLastError() == ERROR_NOT_ENOUGH_MEMORY, "got error %lu\n", GetLastError() );
if (tmp_mem) mem = tmp_mem;
tmp_mem = GlobalReAlloc( mem, 1024 * 1024, GMEM_MODIFY );
Expand All @@ -1709,7 +1709,6 @@ static void test_GlobalAlloc(void)
ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
tmp_mem = GlobalReAlloc( mem, small_size + 1, GMEM_MOVEABLE );
ok( !!tmp_mem, "GlobalReAlloc failed, error %lu\n", GetLastError() );
todo_wine
ok( tmp_mem != mem, "GlobalReAlloc didn't relocate memory\n" );
ptr = GlobalLock( tmp_mem );
ok( !!ptr, "GlobalLock failed, error %lu\n", GetLastError() );
Expand Down Expand Up @@ -1856,8 +1855,8 @@ static void test_GlobalAlloc(void)
{
ok( !is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem );
if (flags == GMEM_MODIFY) ok( tmp_mem == mem, "GlobalReAlloc returned %p\n", tmp_mem );
else if (flags != GMEM_MOVEABLE) todo_wine_if(!flags) ok( !tmp_mem, "GlobalReAlloc succeeded\n" );
else todo_wine ok( tmp_mem != mem, "GlobalReAlloc returned %p\n", tmp_mem );
else if (flags != GMEM_MOVEABLE) ok( !tmp_mem, "GlobalReAlloc succeeded\n" );
else ok( tmp_mem != mem, "GlobalReAlloc returned %p\n", tmp_mem );
}
else
{
Expand All @@ -1871,7 +1870,7 @@ static void test_GlobalAlloc(void)

size = GlobalSize( mem );
if (flags == GMEM_MOVEABLE) ok( size == 0 || broken( size == 1 ) /* w7 */, "GlobalSize returned %Iu\n", size );
else todo_wine_if(!flags) ok( size == small_size, "GlobalSize returned %Iu\n", size );
else ok( size == small_size, "GlobalSize returned %Iu\n", size );

mem = GlobalFree( mem );
ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() );
Expand Down Expand Up @@ -2429,9 +2428,7 @@ static void test_LocalAlloc(void)
ok( size == small_size, "LocalSize returned %Iu\n", size );
SetLastError( 0xdeadbeef );
tmp_mem = LocalReAlloc( mem, small_size, 0 );
todo_wine
ok( !tmp_mem, "LocalReAlloc succeeded\n" );
todo_wine
ok( GetLastError() == ERROR_NOT_ENOUGH_MEMORY, "got error %lu\n", GetLastError() );
if (tmp_mem) mem = tmp_mem;
tmp_mem = LocalReAlloc( mem, 1024 * 1024, LMEM_MODIFY );
Expand All @@ -2447,7 +2444,6 @@ static void test_LocalAlloc(void)
ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() );
tmp_mem = LocalReAlloc( mem, small_size + 1, LMEM_MOVEABLE );
ok( !!tmp_mem, "LocalReAlloc failed, error %lu\n", GetLastError() );
todo_wine
ok( tmp_mem != mem, "LocalReAlloc didn't relocate memory\n" );
ptr = LocalLock( tmp_mem );
ok( !!ptr, "LocalLock failed, error %lu\n", GetLastError() );
Expand Down Expand Up @@ -2540,13 +2536,13 @@ static void test_LocalAlloc(void)
tmp_mem = LocalReAlloc( mem, 0, flags );
ok( !is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem );
if (flags & LMEM_MODIFY) ok( tmp_mem == mem, "LocalReAlloc returned %p\n", tmp_mem );
else if (flags != LMEM_MOVEABLE) todo_wine_if(!flags) ok( !tmp_mem, "LocalReAlloc succeeded\n" );
else todo_wine ok( tmp_mem != mem, "LocalReAlloc returned %p\n", tmp_mem );
else if (flags != LMEM_MOVEABLE) ok( !tmp_mem, "LocalReAlloc succeeded\n" );
else ok( tmp_mem != mem, "LocalReAlloc returned %p\n", tmp_mem );
if (tmp_mem) mem = tmp_mem;

size = LocalSize( mem );
if (flags == LMEM_MOVEABLE) ok( size == 0 || broken( size == 1 ) /* w7 */, "LocalSize returned %Iu\n", size );
else todo_wine_if(!flags) ok( size == small_size, "LocalSize returned %Iu\n", size );
else ok( size == small_size, "LocalSize returned %Iu\n", size );

mem = LocalFree( mem );
ok( !mem, "LocalFree failed, error %lu\n", GetLastError() );
Expand Down
Loading

0 comments on commit f71b8c0

Please sign in to comment.