Skip to content

Commit 86e5612

Browse files
cshungcshung79
authored andcommitted
Fix segfault in GC standalone large pages emulation mode (segments path)
In the non-regions (segments) path used by standalone GC (clrgc.dll), GCLargePages=2 (emulation mode) sets use_large_pages_p=true but reserves memory with normal pages without committing. This causes two problems: 1. virtual_commit (memory.cpp:102) returns true without actually committing for large pages heap memory, so accessing the memory causes a segfault. Fix: commit all reserved blocks upfront in init.cpp for emulation mode, matching the regions path behavior (init.cpp lines 895-901). 2. make_heap_segment calls virtual_commit for accounting, which hits the hard limit check. With large pages, segment sizes fill the entire hard limit budget (soh+loh+poh = heap_hard_limit), leaving zero room for infrastructure commits (card tables, mark lists). The hard limit check rejects and initialization fails. Fix: in make_heap_segment for large pages + non-regions, bypass virtual_commit (memory is already committed) but manually update the committed bytes accounting so diagnostics verification stays consistent. Fixes #127668
1 parent f1ca590 commit 86e5612

2 files changed

Lines changed: 41 additions & 3 deletions

File tree

src/coreclr/gc/init.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -923,6 +923,22 @@ HRESULT gc_heap::initialize_gc (size_t soh_segment_size,
923923
if (!reserve_initial_memory (soh_segment_size, loh_segment_size, poh_segment_size, number_of_heaps,
924924
use_real_large_pages, separated_poh_p, heap_no_to_numa_node))
925925
return E_OUTOFMEMORY;
926+
if (large_pages_emulation_mode_p)
927+
{
928+
// In emulation mode, memory was reserved with normal pages (not real large pages).
929+
// Commit everything upfront to simulate the "always committed" property of real large pages,
930+
// matching the regions path behavior (init.cpp lines 895-901).
931+
imemory_data* current_block = memory_details.initial_memory;
932+
int total_blocks = number_of_heaps * (total_generation_count - ephemeral_generation_count);
933+
for (int i = 0; i < total_blocks; i++, current_block++)
934+
{
935+
size_t blk_size = memory_details.block_size (i);
936+
if (!GCToOSInterface::VirtualCommit (current_block->memory_base, blk_size))
937+
{
938+
return E_OUTOFMEMORY;
939+
}
940+
}
941+
}
926942
if (use_large_pages_p)
927943
{
928944
#ifndef HOST_64BIT

src/coreclr/gc/regions_segments.cpp

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1313,10 +1313,32 @@ heap_segment* gc_heap::make_heap_segment (uint8_t* new_pages, size_t size, gc_he
13131313
0;
13141314
#endif //MULTIPLE_HEAPS
13151315

1316-
if (!virtual_commit (new_pages, initial_commit, oh, h_number))
1316+
#ifndef USE_REGIONS
1317+
if (use_large_pages_p)
13171318
{
1318-
log_init_error_to_host ("Committing %zd bytes for a region failed", initial_commit);
1319-
return 0;
1319+
// For large pages (real or emulation mode), segment memory is already fully committed
1320+
// at reservation time (via VirtualReserveAndCommitLargePages or upfront VirtualCommit).
1321+
// Skip virtual_commit's hard limit check (which would reject since segments fill the
1322+
// entire budget) but still update accounting so diagnostics verification stays consistent.
1323+
check_commit_cs.Enter();
1324+
#if defined(MULTIPLE_HEAPS) && defined(_DEBUG)
1325+
if (h_number != -1)
1326+
{
1327+
g_heaps[h_number]->committed_by_oh_per_heap[oh] += initial_commit;
1328+
}
1329+
#endif // MULTIPLE_HEAPS && _DEBUG
1330+
committed_by_oh[oh] += initial_commit;
1331+
current_total_committed += initial_commit;
1332+
check_commit_cs.Leave();
1333+
}
1334+
else
1335+
#endif //!USE_REGIONS
1336+
{
1337+
if (!virtual_commit (new_pages, initial_commit, oh, h_number))
1338+
{
1339+
log_init_error_to_host ("Committing %zd bytes for a region failed", initial_commit);
1340+
return 0;
1341+
}
13201342
}
13211343

13221344
#ifdef USE_REGIONS

0 commit comments

Comments
 (0)