@@ -2210,6 +2210,8 @@ uint64_t gc_heap::entry_available_physical_mem = 0;
2210
2210
2211
2211
size_t gc_heap::heap_hard_limit = 0;
2212
2212
2213
+ size_t gc_heap::heap_hard_limit_oh[total_oh_count - 1] = {0, 0, 0};
2214
+
2213
2215
bool affinity_config_specified_p = false;
2214
2216
#ifdef BACKGROUND_GC
2215
2217
GCEvent gc_heap::bgc_start_event;
@@ -3924,7 +3926,8 @@ struct initial_memory_details
3924
3926
{
3925
3927
ALLATONCE = 1,
3926
3928
EACH_GENERATION,
3927
- EACH_BLOCK
3929
+ EACH_BLOCK,
3930
+ ALLATONCE_SEPARATED_POH
3928
3931
};
3929
3932
3930
3933
size_t allocation_pattern;
@@ -3970,7 +3973,7 @@ struct initial_memory_details
3970
3973
3971
3974
initial_memory_details memory_details;
3972
3975
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 )
3974
3977
{
3975
3978
BOOL reserve_success = FALSE;
3976
3979
@@ -4014,23 +4017,52 @@ BOOL gc_heap::reserve_initial_memory (size_t normal_size, size_t large_size, siz
4014
4017
return FALSE;
4015
4018
}
4016
4019
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);
4018
4023
4019
4024
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
+ }
4020
4035
if (allatonce_block)
4021
4036
{
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
+ }
4025
4049
4026
4050
for (int i = 0; i < memory_details.block_count; i++)
4027
4051
{
4028
4052
memory_details.initial_normal_heap[i].memory_base = allatonce_block +
4029
4053
(i * normal_size);
4030
4054
memory_details.initial_large_heap[i].memory_base = allatonce_block +
4031
4055
(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
+ }
4034
4066
4035
4067
reserve_success = TRUE;
4036
4068
}
@@ -4040,7 +4072,7 @@ BOOL gc_heap::reserve_initial_memory (size_t normal_size, size_t large_size, siz
4040
4072
// try to allocate 3 blocks
4041
4073
uint8_t* b1 = (uint8_t*)virtual_alloc (memory_details.block_count * normal_size, use_large_pages_p);
4042
4074
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 );
4044
4076
4045
4077
if (b1 && b2 && b3)
4046
4078
{
@@ -4114,10 +4146,18 @@ void gc_heap::destroy_initial_memory()
4114
4146
if (memory_details.initial_memory != NULL)
4115
4147
{
4116
4148
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)
4117
4155
{
4118
4156
virtual_free(memory_details.initial_memory[0].memory_base,
4119
4157
memory_details.block_count*(memory_details.block_size_normal +
4120
4158
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));
4121
4161
}
4122
4162
else if (memory_details.allocation_pattern == initial_memory_details::EACH_GENERATION)
4123
4163
{
@@ -5566,10 +5606,16 @@ bool gc_heap::virtual_commit (void* address, size_t size, gc_oh_num oh, int h_nu
5566
5606
if (heap_hard_limit)
5567
5607
{
5568
5608
check_commit_cs.Enter();
5569
- committed_by_oh[oh] += size;
5570
5609
bool exceeded_p = false;
5571
5610
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)
5573
5619
{
5574
5620
dprintf (1, ("%Id + %Id = %Id > limit %Id ",
5575
5621
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
5578
5624
5579
5625
exceeded_p = true;
5580
5626
}
5581
- else
5627
+
5628
+ if (!exceeded_p)
5582
5629
{
5630
+ committed_by_oh[oh] += size;
5583
5631
current_total_committed += size;
5584
5632
if (h_number < 0)
5585
5633
current_total_committed_bookkeeping += size;
@@ -9958,7 +10006,8 @@ HRESULT gc_heap::initialize_gc (size_t soh_segment_size,
9958
10006
check_commit_cs.Initialize();
9959
10007
}
9960
10008
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))
9962
10011
return E_OUTOFMEMORY;
9963
10012
9964
10013
#ifdef CARD_BUNDLE
@@ -12592,7 +12641,7 @@ allocation_state gc_heap::allocate_soh (int gen_number,
12592
12641
}
12593
12642
else
12594
12643
{
12595
- assert (commit_failed_p);
12644
+ assert (commit_failed_p || heap_hard_limit );
12596
12645
soh_alloc_state = a_state_cant_allocate;
12597
12646
oom_r = oom_cant_commit;
12598
12647
}
@@ -35103,6 +35152,64 @@ HRESULT GCHeap::Initialize()
35103
35152
35104
35153
#ifdef HOST_64BIT
35105
35154
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
+ }
35106
35213
35107
35214
if (!(gc_heap::heap_hard_limit))
35108
35215
{
@@ -35189,14 +35296,63 @@ HRESULT GCHeap::Initialize()
35189
35296
35190
35297
size_t seg_size = 0;
35191
35298
size_t large_seg_size = 0;
35299
+ size_t pin_seg_size = 0;
35192
35300
35193
35301
if (gc_heap::heap_hard_limit)
35194
35302
{
35195
35303
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
+ }
35199
35343
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
+ }
35200
35356
if (gc_heap::use_large_pages_p)
35201
35357
gc_heap::min_segment_size = min_segment_size_hard_limit;
35202
35358
}
@@ -35205,26 +35361,30 @@ HRESULT GCHeap::Initialize()
35205
35361
seg_size = get_valid_segment_size();
35206
35362
gc_heap::soh_segment_size = seg_size;
35207
35363
large_seg_size = get_valid_segment_size (TRUE);
35364
+ pin_seg_size = large_seg_size;
35208
35365
}
35366
+ assert (g_theGCHeap->IsValidSegmentSize (seg_size));
35367
+ assert (g_theGCHeap->IsValidSegmentSize (large_seg_size));
35368
+ assert (g_theGCHeap->IsValidSegmentSize (pin_seg_size));
35209
35369
35210
35370
dprintf (1, ("%d heaps, soh seg size: %Id mb, loh: %Id mb\n",
35211
35371
nhp,
35212
35372
(seg_size / (size_t)1024 / 1024),
35213
35373
(large_seg_size / 1024 / 1024)));
35214
35374
35215
- gc_heap::min_uoh_segment_size = large_seg_size;
35375
+ gc_heap::min_uoh_segment_size = min ( large_seg_size, pin_seg_size) ;
35216
35376
35217
35377
if (gc_heap::min_segment_size == 0)
35218
35378
{
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 );
35220
35380
}
35221
35381
gc_heap::min_segment_size_shr = index_of_highest_set_bit (gc_heap::min_segment_size);
35222
35382
35223
35383
#ifdef MULTIPLE_HEAPS
35224
35384
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);
35226
35386
#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*/);
35228
35388
#endif //MULTIPLE_HEAPS
35229
35389
35230
35390
if (hr != S_OK)
0 commit comments