@@ -7108,9 +7108,12 @@ void gc_heap::gc_thread_function ()
7108
7108
{
7109
7109
settings.init_mechanisms();
7110
7110
#ifdef DYNAMIC_HEAP_COUNT
7111
- // make sure the other gc threads cannot see this as a request to change heap count
7112
- // see explanation below about the cases when we return from gc_start_event.Wait
7113
- assert (dynamic_heap_count_data.new_n_heaps == n_heaps);
7111
+ if (gc_heap::dynamic_adaptation_mode == dynamic_adaptation_to_application_sizes)
7112
+ {
7113
+ // make sure the other gc threads cannot see this as a request to change heap count
7114
+ // see explanation below about the cases when we return from gc_start_event.Wait
7115
+ assert (dynamic_heap_count_data.new_n_heaps == n_heaps);
7116
+ }
7114
7117
#endif //DYNAMIC_HEAP_COUNT
7115
7118
dprintf (9999, ("GC thread %d setting_gc_start_in_gc(h%d)", heap_number, n_heaps));
7116
7119
gc_start_event.Set();
@@ -7174,8 +7177,7 @@ void gc_heap::gc_thread_function ()
7174
7177
continue;
7175
7178
}
7176
7179
#endif //DYNAMIC_HEAP_COUNT
7177
- //dprintf (3, (ThreadStressLog::gcServerThreadNStartMsg(), heap_number));
7178
- dprintf (9999, ("GC thread %d wait_done(%d)", heap_number, n_heaps));
7180
+ dprintf (3, (ThreadStressLog::gcServerThreadNStartMsg(), heap_number));
7179
7181
}
7180
7182
7181
7183
assert ((heap_number == 0) || proceed_with_gc_p);
@@ -12580,6 +12582,16 @@ void gc_heap::rearrange_uoh_segments()
12580
12582
freeable_uoh_segment = 0;
12581
12583
}
12582
12584
12585
+ void gc_heap::delay_free_segments()
12586
+ {
12587
+ rearrange_uoh_segments();
12588
+ #ifdef BACKGROUND_GC
12589
+ background_delay_delete_uoh_segments();
12590
+ if (!gc_heap::background_running_p())
12591
+ rearrange_small_heap_segments();
12592
+ #endif //BACKGROUND_GC
12593
+ }
12594
+
12583
12595
#ifndef USE_REGIONS
12584
12596
void gc_heap::rearrange_heap_segments(BOOL compacting)
12585
12597
{
@@ -17477,6 +17489,7 @@ BOOL gc_heap::a_fit_free_list_uoh_p (size_t size,
17477
17489
gen_number, align_const);
17478
17490
dd_new_allocation (dynamic_data_of (gen_number)) -= limit;
17479
17491
17492
+ size_t saved_free_list_size = free_list_size;
17480
17493
#ifdef FEATURE_LOH_COMPACTION
17481
17494
if (loh_pad)
17482
17495
{
@@ -17505,7 +17518,7 @@ BOOL gc_heap::a_fit_free_list_uoh_p (size_t size,
17505
17518
{
17506
17519
generation_free_obj_space (gen) += remain_size;
17507
17520
}
17508
- generation_free_list_space (gen) -= free_list_size ;
17521
+ generation_free_list_space (gen) -= saved_free_list_size ;
17509
17522
assert ((ptrdiff_t)generation_free_list_space (gen) >= 0);
17510
17523
generation_free_list_allocated (gen) += limit;
17511
17524
@@ -22829,7 +22842,12 @@ void gc_heap::merge_fl_from_other_heaps (int gen_idx, int to_n_heaps, int from_n
22829
22842
assert (free_list_space_decrease <= generation_free_list_space (gen));
22830
22843
generation_free_list_space (gen) -= free_list_space_decrease;
22831
22844
22832
- assert (free_list_space_decrease <= dd_fragmentation (dd));
22845
+ // TODO - I'm seeing for gen2 this is free_list_space_decrease can be a bit larger than frag.
22846
+ // Need to fix this later.
22847
+ if (gen_idx != max_generation)
22848
+ {
22849
+ assert (free_list_space_decrease <= dd_fragmentation (dd));
22850
+ }
22833
22851
22834
22852
size_t free_list_space_increase = 0;
22835
22853
for (int from_hn = 0; from_hn < from_n_heaps; from_hn++)
@@ -23826,7 +23844,6 @@ void gc_heap::garbage_collect (int n)
23826
23844
23827
23845
#ifdef MULTIPLE_HEAPS
23828
23846
#ifdef STRESS_DYNAMIC_HEAP_COUNT
23829
- dprintf (9999, ("h%d 1st join!", heap_number));
23830
23847
Interlocked::Increment (&heaps_in_this_gc);
23831
23848
#endif //STRESS_DYNAMIC_HEAP_COUNT
23832
23849
//align all heaps on the max generation to condemn
@@ -23863,24 +23880,12 @@ void gc_heap::garbage_collect (int n)
23863
23880
// check for card table growth
23864
23881
if (g_gc_card_table != hp->card_table)
23865
23882
hp->copy_brick_card_table();
23866
-
23867
- hp->rearrange_uoh_segments();
23868
- #ifdef BACKGROUND_GC
23869
- hp->background_delay_delete_uoh_segments();
23870
- if (!gc_heap::background_running_p())
23871
- hp->rearrange_small_heap_segments();
23872
- #endif //BACKGROUND_GC
23883
+ hp->delay_free_segments();
23873
23884
}
23874
23885
#else //MULTIPLE_HEAPS
23875
23886
if (g_gc_card_table != card_table)
23876
23887
copy_brick_card_table();
23877
-
23878
- rearrange_uoh_segments();
23879
- #ifdef BACKGROUND_GC
23880
- background_delay_delete_uoh_segments();
23881
- if (!gc_heap::background_running_p())
23882
- rearrange_small_heap_segments();
23883
- #endif //BACKGROUND_GC
23888
+ delay_free_segments();
23884
23889
#endif //MULTIPLE_HEAPS
23885
23890
23886
23891
BOOL should_evaluate_elevation = TRUE;
@@ -24424,7 +24429,7 @@ void gc_heap::equalize_promoted_bytes(int condemned_gen_number)
24424
24429
// hope is to achieve better work balancing in relocate and compact phases
24425
24430
// this is also used when the heap count changes to balance regions between heaps
24426
24431
int highest_gen_number = ((condemned_gen_number == max_generation) ?
24427
- (total_generation_count - 1) : condemned_gen_number);
24432
+ (total_generation_count - 1) : condemned_gen_number);
24428
24433
int stop_gen_idx = get_stop_generation_index (condemned_gen_number);
24429
24434
24430
24435
for (int gen_idx = highest_gen_number; gen_idx >= stop_gen_idx; gen_idx--)
@@ -25215,6 +25220,7 @@ void gc_heap::check_heap_count ()
25215
25220
{
25216
25221
// can't have background gc running while we change the number of heaps
25217
25222
// so it's useless to compute a new number of heaps here
25223
+ dprintf (9999, ("BGC in progress, don't change"));
25218
25224
}
25219
25225
else
25220
25226
{
@@ -25496,6 +25502,17 @@ bool gc_heap::prepare_to_change_heap_count (int new_n_heaps)
25496
25502
}
25497
25503
}
25498
25504
25505
+ // Before we look at whether we have sufficient regions we should return regions that should be deleted to free
25506
+ // so we don't lose them when we decommission heaps. We could do this for only heaps that we are about
25507
+ // to decomission. But it's better to do this for all heaps because we don't need to worry about adding them to the
25508
+ // heaps remain (freeable uoh/soh regions) and we get rid of regions with the heap_segment_flags_uoh_delete flag
25509
+ // because background_delay_delete_uoh_segments makes the assumption it can't be the start region.
25510
+ for (int i = 0; i < old_n_heaps; i++)
25511
+ {
25512
+ gc_heap* hp = g_heaps[i];
25513
+ hp->delay_free_segments ();
25514
+ }
25515
+
25499
25516
// if we want to increase the number of heaps, we have to make sure we can give
25500
25517
// each heap a region for each generation. If we cannot do that, we have to give up
25501
25518
ptrdiff_t region_count_in_gen[total_generation_count];
@@ -31591,7 +31608,6 @@ void gc_heap::process_remaining_regions (int current_plan_gen_num, generation* c
31591
31608
31592
31609
void gc_heap::grow_mark_list_piece()
31593
31610
{
31594
- dprintf (9999, ("gml: mls %Id, total %Id, rc %Id, hn %d", g_mark_list_piece_size, g_mark_list_piece_total_size, region_count, get_num_heaps ()));
31595
31611
if (g_mark_list_piece_total_size < region_count * 2 * get_num_heaps())
31596
31612
{
31597
31613
delete[] g_mark_list_piece;
@@ -31609,7 +31625,6 @@ void gc_heap::grow_mark_list_piece()
31609
31625
{
31610
31626
g_mark_list_piece_size = 0;
31611
31627
}
31612
- dprintf (9999, ("RS mls->%Id total %Id->%Id", alloc_count, g_mark_list_piece_total_size, (alloc_count * 2 * get_num_heaps ())));
31613
31628
g_mark_list_piece_total_size = g_mark_list_piece_size * 2 * get_num_heaps();
31614
31629
}
31615
31630
// update the size per heap in case the number of heaps has changed,
@@ -44900,7 +44915,6 @@ BOOL gc_heap::background_object_marked (uint8_t* o, BOOL clearp)
44900
44915
return m;
44901
44916
}
44902
44917
44903
- // TODO - when we change heap count, the assumption that first region can never have the flag set is no longer true.
44904
44918
void gc_heap::background_delay_delete_uoh_segments()
44905
44919
{
44906
44920
for (int i = uoh_start_generation; i < total_generation_count; i++)
@@ -48467,16 +48481,16 @@ HRESULT GCHeap::Initialize()
48467
48481
//dprintf (9999, ("changing join hp %d->%d", n_heaps, new_n_heaps));
48468
48482
int max_threads_to_wake = max (gc_heap::n_heaps, initial_n_heaps);
48469
48483
gc_t_join.update_n_threads (max_threads_to_wake);
48470
- gc_heap::gc_start_event.Set();
48484
+ gc_heap::gc_start_event.Set ();
48471
48485
}
48472
48486
48473
48487
gc_heap::g_heaps[0]->change_heap_count (initial_n_heaps);
48474
- gc_heap::gc_start_event.Reset();
48488
+ gc_heap::gc_start_event.Reset ();
48489
+
48490
+ // This needs to be different from our initial heap count so we can make sure we wait for
48491
+ // the idle threads correctly in gc_thread_function.
48492
+ gc_heap::dynamic_heap_count_data.last_n_heaps = 0;
48475
48493
}
48476
- //gc_heap::dynamic_heap_count_data.new_n_heaps = gc_heap::n_heaps;
48477
- // This needs to be different from our initial heap count so we can make sure we wait for
48478
- // the idle threads correctly in gc_thread_function.
48479
- gc_heap::dynamic_heap_count_data.last_n_heaps = 0;
48480
48494
#endif //DYNAMIC_HEAP_COUNT
48481
48495
GCScan::GcRuntimeStructuresValid (TRUE);
48482
48496
0 commit comments