@@ -2210,6 +2210,8 @@ uint64_t gc_heap::entry_available_physical_mem = 0;
22102210
22112211size_t gc_heap::heap_hard_limit = 0;
22122212
2213+ size_t gc_heap::heap_hard_limit_oh[total_oh_count - 1] = {0, 0, 0};
2214+
22132215bool affinity_config_specified_p = false;
22142216#ifdef BACKGROUND_GC
22152217GCEvent gc_heap::bgc_start_event;
@@ -3924,7 +3926,8 @@ struct initial_memory_details
39243926 {
39253927 ALLATONCE = 1,
39263928 EACH_GENERATION,
3927- EACH_BLOCK
3929+ EACH_BLOCK,
3930+ ALLATONCE_SEPARATED_POH
39283931 };
39293932
39303933 size_t allocation_pattern;
@@ -3970,7 +3973,7 @@ struct initial_memory_details
39703973
39713974initial_memory_details memory_details;
39723975
3973- BOOL gc_heap::reserve_initial_memory (size_t normal_size, size_t large_size, size_t pinned_size, int num_heaps, bool use_large_pages_p)
3976+ BOOL gc_heap::reserve_initial_memory (size_t normal_size, size_t large_size, size_t pinned_size, int num_heaps, bool use_large_pages_p, bool separated_poh_p )
39743977{
39753978 BOOL reserve_success = FALSE;
39763979
@@ -4014,23 +4017,52 @@ BOOL gc_heap::reserve_initial_memory (size_t normal_size, size_t large_size, siz
40144017 return FALSE;
40154018 }
40164019
4017- size_t requestedMemory = memory_details.block_count * (normal_size + large_size + pinned_size);
4020+ size_t temp_pinned_size = (separated_poh_p ? 0 : pinned_size);
4021+ size_t separate_pinned_size = memory_details.block_count * pinned_size;
4022+ size_t requestedMemory = memory_details.block_count * (normal_size + large_size + temp_pinned_size);
40184023
40194024 uint8_t* allatonce_block = (uint8_t*)virtual_alloc (requestedMemory, use_large_pages_p);
4025+ uint8_t* separated_poh_block = nullptr;
4026+ if (allatonce_block && separated_poh_p)
4027+ {
4028+ separated_poh_block = (uint8_t*)virtual_alloc (separate_pinned_size, false);
4029+ if (!separated_poh_block)
4030+ {
4031+ virtual_free (allatonce_block, requestedMemory);
4032+ allatonce_block = nullptr;
4033+ }
4034+ }
40204035 if (allatonce_block)
40214036 {
4022- g_gc_lowest_address = allatonce_block;
4023- g_gc_highest_address = allatonce_block + requestedMemory;
4024- memory_details.allocation_pattern = initial_memory_details::ALLATONCE;
4037+ if (separated_poh_p)
4038+ {
4039+ g_gc_lowest_address = min (allatonce_block, separated_poh_block);
4040+ g_gc_highest_address = max ((allatonce_block + requestedMemory), (separated_poh_block + separate_pinned_size));
4041+ memory_details.allocation_pattern = initial_memory_details::ALLATONCE_SEPARATED_POH;
4042+ }
4043+ else
4044+ {
4045+ g_gc_lowest_address = allatonce_block;
4046+ g_gc_highest_address = allatonce_block + requestedMemory;
4047+ memory_details.allocation_pattern = initial_memory_details::ALLATONCE;
4048+ }
40254049
40264050 for (int i = 0; i < memory_details.block_count; i++)
40274051 {
40284052 memory_details.initial_normal_heap[i].memory_base = allatonce_block +
40294053 (i * normal_size);
40304054 memory_details.initial_large_heap[i].memory_base = allatonce_block +
40314055 (memory_details.block_count * normal_size) + (i * large_size);
4032- memory_details.initial_pinned_heap[i].memory_base = allatonce_block +
4033- (memory_details.block_count * (normal_size + large_size)) + (i * pinned_size);
4056+ if (separated_poh_p)
4057+ {
4058+ memory_details.initial_pinned_heap[i].memory_base = separated_poh_block +
4059+ (i * pinned_size);
4060+ }
4061+ else
4062+ {
4063+ memory_details.initial_pinned_heap[i].memory_base = allatonce_block +
4064+ (memory_details.block_count * (normal_size + large_size)) + (i * pinned_size);
4065+ }
40344066
40354067 reserve_success = TRUE;
40364068 }
@@ -4040,7 +4072,7 @@ BOOL gc_heap::reserve_initial_memory (size_t normal_size, size_t large_size, siz
40404072 // try to allocate 3 blocks
40414073 uint8_t* b1 = (uint8_t*)virtual_alloc (memory_details.block_count * normal_size, use_large_pages_p);
40424074 uint8_t* b2 = (uint8_t*)virtual_alloc (memory_details.block_count * large_size, use_large_pages_p);
4043- uint8_t* b3 = (uint8_t*)virtual_alloc (memory_details.block_count * pinned_size, use_large_pages_p);
4075+ uint8_t* b3 = (uint8_t*)virtual_alloc (memory_details.block_count * pinned_size, use_large_pages_p && !separated_poh_p );
40444076
40454077 if (b1 && b2 && b3)
40464078 {
@@ -4114,10 +4146,18 @@ void gc_heap::destroy_initial_memory()
41144146 if (memory_details.initial_memory != NULL)
41154147 {
41164148 if (memory_details.allocation_pattern == initial_memory_details::ALLATONCE)
4149+ {
4150+ virtual_free(memory_details.initial_memory[0].memory_base,
4151+ memory_details.block_count*(memory_details.block_size_normal +
4152+ memory_details.block_size_large + memory_details.block_size_pinned));
4153+ }
4154+ else if (memory_details.allocation_pattern == initial_memory_details::ALLATONCE_SEPARATED_POH)
41174155 {
41184156 virtual_free(memory_details.initial_memory[0].memory_base,
41194157 memory_details.block_count*(memory_details.block_size_normal +
41204158 memory_details.block_size_large));
4159+ virtual_free(memory_details.initial_pinned_heap[0].memory_base,
4160+ memory_details.block_count*(memory_details.block_size_pinned));
41214161 }
41224162 else if (memory_details.allocation_pattern == initial_memory_details::EACH_GENERATION)
41234163 {
@@ -5566,10 +5606,16 @@ bool gc_heap::virtual_commit (void* address, size_t size, gc_oh_num oh, int h_nu
55665606 if (heap_hard_limit)
55675607 {
55685608 check_commit_cs.Enter();
5569- committed_by_oh[oh] += size;
55705609 bool exceeded_p = false;
55715610
5572- if ((current_total_committed + size) > heap_hard_limit)
5611+ if (heap_hard_limit_oh[0] != 0)
5612+ {
5613+ if ((committed_by_oh[oh] + size) > heap_hard_limit_oh[oh])
5614+ {
5615+ exceeded_p = true;
5616+ }
5617+ }
5618+ else if ((current_total_committed + size) > heap_hard_limit)
55735619 {
55745620 dprintf (1, ("%Id + %Id = %Id > limit %Id ",
55755621 current_total_committed, size,
@@ -5578,8 +5624,10 @@ bool gc_heap::virtual_commit (void* address, size_t size, gc_oh_num oh, int h_nu
55785624
55795625 exceeded_p = true;
55805626 }
5581- else
5627+
5628+ if (!exceeded_p)
55825629 {
5630+ committed_by_oh[oh] += size;
55835631 current_total_committed += size;
55845632 if (h_number < 0)
55855633 current_total_committed_bookkeeping += size;
@@ -9958,7 +10006,8 @@ HRESULT gc_heap::initialize_gc (size_t soh_segment_size,
995810006 check_commit_cs.Initialize();
995910007 }
996010008
9961- if (!reserve_initial_memory (soh_segment_size, loh_segment_size, poh_segment_size, number_of_heaps, use_large_pages_p))
10009+ bool separated_poh_p = use_large_pages_p && heap_hard_limit_oh[0] && (GCConfig::GetGCHeapHardLimitPOH() == 0) && (GCConfig::GetGCHeapHardLimitPOHPercent() == 0);
10010+ if (!reserve_initial_memory (soh_segment_size, loh_segment_size, poh_segment_size, number_of_heaps, use_large_pages_p, separated_poh_p))
996210011 return E_OUTOFMEMORY;
996310012
996410013#ifdef CARD_BUNDLE
@@ -12592,7 +12641,7 @@ allocation_state gc_heap::allocate_soh (int gen_number,
1259212641 }
1259312642 else
1259412643 {
12595- assert (commit_failed_p);
12644+ assert (commit_failed_p || heap_hard_limit );
1259612645 soh_alloc_state = a_state_cant_allocate;
1259712646 oom_r = oom_cant_commit;
1259812647 }
@@ -35103,6 +35152,64 @@ HRESULT GCHeap::Initialize()
3510335152
3510435153#ifdef HOST_64BIT
3510535154 gc_heap::heap_hard_limit = (size_t)GCConfig::GetGCHeapHardLimit();
35155+ gc_heap::heap_hard_limit_oh[0] = (size_t)GCConfig::GetGCHeapHardLimitSOH();
35156+ gc_heap::heap_hard_limit_oh[1] = (size_t)GCConfig::GetGCHeapHardLimitLOH();
35157+ gc_heap::heap_hard_limit_oh[2] = (size_t)GCConfig::GetGCHeapHardLimitPOH();
35158+
35159+ if (gc_heap::heap_hard_limit_oh[0] || gc_heap::heap_hard_limit_oh[1] || gc_heap::heap_hard_limit_oh[2])
35160+ {
35161+ if (!gc_heap::heap_hard_limit_oh[0])
35162+ {
35163+ return E_INVALIDARG;
35164+ }
35165+ if (!gc_heap::heap_hard_limit_oh[1])
35166+ {
35167+ return E_INVALIDARG;
35168+ }
35169+ if (gc_heap::heap_hard_limit_oh[2] < min_segment_size_hard_limit)
35170+ {
35171+ gc_heap::heap_hard_limit_oh[2] = min_segment_size_hard_limit;
35172+ }
35173+ // This tells the system there is a hard limit, but otherwise we will not compare against this value.
35174+ gc_heap::heap_hard_limit = 1;
35175+ }
35176+ else
35177+ {
35178+ uint32_t percent_of_mem_soh = (uint32_t)GCConfig::GetGCHeapHardLimitSOHPercent();
35179+ uint32_t percent_of_mem_loh = (uint32_t)GCConfig::GetGCHeapHardLimitLOHPercent();
35180+ uint32_t percent_of_mem_poh = (uint32_t)GCConfig::GetGCHeapHardLimitPOHPercent();
35181+ if (percent_of_mem_soh || percent_of_mem_loh || percent_of_mem_poh)
35182+ {
35183+ if ((percent_of_mem_soh <= 0) || (percent_of_mem_soh >= 100))
35184+ {
35185+ return E_INVALIDARG;
35186+ }
35187+ if ((percent_of_mem_loh <= 0) || (percent_of_mem_loh >= 100))
35188+ {
35189+ return E_INVALIDARG;
35190+ }
35191+ else if ((percent_of_mem_poh < 0) || (percent_of_mem_poh >= 100))
35192+ {
35193+ return E_INVALIDARG;
35194+ }
35195+ if ((percent_of_mem_soh + percent_of_mem_loh + percent_of_mem_poh) >= 100)
35196+ {
35197+ return E_INVALIDARG;
35198+ }
35199+ gc_heap::heap_hard_limit_oh[0] = (size_t)(gc_heap::total_physical_mem * (uint64_t)percent_of_mem_soh / (uint64_t)100);
35200+ gc_heap::heap_hard_limit_oh[1] = (size_t)(gc_heap::total_physical_mem * (uint64_t)percent_of_mem_loh / (uint64_t)100);
35201+ if (percent_of_mem_poh == 0)
35202+ {
35203+ gc_heap::heap_hard_limit_oh[2] = min_segment_size_hard_limit;
35204+ }
35205+ else
35206+ {
35207+ gc_heap::heap_hard_limit_oh[2] = (size_t)(gc_heap::total_physical_mem * (uint64_t)percent_of_mem_poh / (uint64_t)100);
35208+ }
35209+ // This tells the system there is a hard limit, but otherwise we will not compare against this value.
35210+ gc_heap::heap_hard_limit = 1;
35211+ }
35212+ }
3510635213
3510735214 if (!(gc_heap::heap_hard_limit))
3510835215 {
@@ -35189,14 +35296,63 @@ HRESULT GCHeap::Initialize()
3518935296
3519035297 size_t seg_size = 0;
3519135298 size_t large_seg_size = 0;
35299+ size_t pin_seg_size = 0;
3519235300
3519335301 if (gc_heap::heap_hard_limit)
3519435302 {
3519535303 gc_heap::use_large_pages_p = GCConfig::GetGCLargePages();
35196- seg_size = gc_heap::get_segment_size_hard_limit (&nhp, (nhp_from_config == 0));
35197- gc_heap::soh_segment_size = seg_size;
35198- large_seg_size = gc_heap::use_large_pages_p ? seg_size : seg_size * 2;
35304+ if (gc_heap::heap_hard_limit_oh[0])
35305+ {
35306+ #ifdef MULTIPLE_HEAPS
35307+ if (nhp_from_config == 0)
35308+ {
35309+ for (int i = 0; i < (total_oh_count - 1); i++)
35310+ {
35311+ uint32_t nhp_oh = (uint32_t)(gc_heap::heap_hard_limit_oh[i] / min_segment_size_hard_limit);
35312+ nhp = min (nhp, nhp_oh);
35313+ }
35314+ if (nhp == 0)
35315+ {
35316+ nhp = 1;
35317+ }
35318+ }
35319+ #endif
35320+ seg_size = gc_heap::heap_hard_limit_oh[0] / nhp;
35321+ large_seg_size = gc_heap::heap_hard_limit_oh[1] / nhp;
35322+ pin_seg_size = gc_heap::heap_hard_limit_oh[2] / nhp;
35323+
35324+ size_t aligned_seg_size = align_on_segment_hard_limit (seg_size);
35325+ size_t aligned_large_seg_size = align_on_segment_hard_limit (large_seg_size);
35326+ size_t aligned_pin_seg_size = align_on_segment_hard_limit (pin_seg_size);
35327+
35328+ if (!gc_heap::use_large_pages_p)
35329+ {
35330+ aligned_seg_size = round_up_power2 (aligned_seg_size);
35331+ aligned_large_seg_size = round_up_power2 (aligned_large_seg_size);
35332+ aligned_pin_seg_size = round_up_power2 (aligned_pin_seg_size);
35333+ }
35334+
35335+ size_t seg_size_from_config = (size_t)GCConfig::GetSegmentSize();
35336+ if (seg_size_from_config)
35337+ {
35338+ size_t aligned_seg_size_config = (gc_heap::use_large_pages_p ? align_on_segment_hard_limit (seg_size) : round_up_power2 (seg_size_from_config));
35339+ aligned_seg_size = max (aligned_seg_size, aligned_seg_size_config);
35340+ aligned_large_seg_size = max (aligned_large_seg_size, aligned_seg_size_config);
35341+ aligned_pin_seg_size = max (aligned_pin_seg_size, aligned_seg_size_config);
35342+ }
3519935343
35344+ seg_size = aligned_seg_size;
35345+ gc_heap::soh_segment_size = seg_size;
35346+ large_seg_size = aligned_large_seg_size;
35347+ pin_seg_size = aligned_pin_seg_size;
35348+ }
35349+ else
35350+ {
35351+ seg_size = gc_heap::get_segment_size_hard_limit (&nhp, (nhp_from_config == 0));
35352+ gc_heap::soh_segment_size = seg_size;
35353+ large_seg_size = gc_heap::use_large_pages_p ? seg_size : seg_size * 2;
35354+ pin_seg_size = large_seg_size;
35355+ }
3520035356 if (gc_heap::use_large_pages_p)
3520135357 gc_heap::min_segment_size = min_segment_size_hard_limit;
3520235358 }
@@ -35205,26 +35361,30 @@ HRESULT GCHeap::Initialize()
3520535361 seg_size = get_valid_segment_size();
3520635362 gc_heap::soh_segment_size = seg_size;
3520735363 large_seg_size = get_valid_segment_size (TRUE);
35364+ pin_seg_size = large_seg_size;
3520835365 }
35366+ assert (g_theGCHeap->IsValidSegmentSize (seg_size));
35367+ assert (g_theGCHeap->IsValidSegmentSize (large_seg_size));
35368+ assert (g_theGCHeap->IsValidSegmentSize (pin_seg_size));
3520935369
3521035370 dprintf (1, ("%d heaps, soh seg size: %Id mb, loh: %Id mb\n",
3521135371 nhp,
3521235372 (seg_size / (size_t)1024 / 1024),
3521335373 (large_seg_size / 1024 / 1024)));
3521435374
35215- gc_heap::min_uoh_segment_size = large_seg_size;
35375+ gc_heap::min_uoh_segment_size = min ( large_seg_size, pin_seg_size) ;
3521635376
3521735377 if (gc_heap::min_segment_size == 0)
3521835378 {
35219- gc_heap::min_segment_size = min (seg_size, large_seg_size );
35379+ gc_heap::min_segment_size = min (seg_size, gc_heap::min_uoh_segment_size );
3522035380 }
3522135381 gc_heap::min_segment_size_shr = index_of_highest_set_bit (gc_heap::min_segment_size);
3522235382
3522335383#ifdef MULTIPLE_HEAPS
3522435384 gc_heap::n_heaps = nhp;
35225- hr = gc_heap::initialize_gc (seg_size, large_seg_size /*loh_segment_size*/, large_seg_size /*poh_segment_size*/, nhp);
35385+ hr = gc_heap::initialize_gc (seg_size, large_seg_size /*loh_segment_size*/, pin_seg_size /*poh_segment_size*/, nhp);
3522635386#else
35227- hr = gc_heap::initialize_gc (seg_size, large_seg_size /*loh_segment_size*/, large_seg_size /*poh_segment_size*/);
35387+ hr = gc_heap::initialize_gc (seg_size, large_seg_size /*loh_segment_size*/, pin_seg_size /*poh_segment_size*/);
3522835388#endif //MULTIPLE_HEAPS
3522935389
3523035390 if (hr != S_OK)
0 commit comments