diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index bb7a4e4168b65..e3122f12da18c 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -91,6 +91,8 @@ BOOL bgc_heap_walk_for_etw_p = FALSE; #define UOH_ALLOCATION_RETRY_MAX_COUNT 2 +#define MAX_YP_SPIN_COUNT_UNIT 32768 + uint32_t yp_spin_count_unit = 0; uint32_t original_spin_count_unit = 0; size_t loh_size_threshold = LARGE_OBJECT_SIZE; @@ -2287,6 +2289,7 @@ double gc_heap::short_plugs_pad_ratio = 0; int gc_heap::generation_skip_ratio_threshold = 0; int gc_heap::conserve_mem_setting = 0; +bool gc_heap::spin_count_unit_config_p = false; uint64_t gc_heap::suspended_start_time = 0; uint64_t gc_heap::end_gc_time = 0; @@ -13744,6 +13747,14 @@ HRESULT gc_heap::initialize_gc (size_t soh_segment_size, yp_spin_count_unit = 32 * g_num_processors; #endif //MULTIPLE_HEAPS + // Check if the values are valid for the spin count if provided by the user + // and if they are, set them as the yp_spin_count_unit and then ignore any updates made in SetYieldProcessorScalingFactor. + uint32_t spin_count_unit_from_config = (uint32_t)GCConfig::GetGCSpinCountUnit(); + gc_heap::spin_count_unit_config_p = (spin_count_unit_from_config > 0) && (spin_count_unit_from_config <= MAX_YP_SPIN_COUNT_UNIT); + if (gc_heap::spin_count_unit_config_p) + { + yp_spin_count_unit = spin_count_unit_from_config; + } original_spin_count_unit = yp_spin_count_unit; #if defined(__linux__) @@ -45628,14 +45639,17 @@ size_t GCHeap::GetPromotedBytes(int heap_index) void GCHeap::SetYieldProcessorScalingFactor (float scalingFactor) { - assert (yp_spin_count_unit != 0); - uint32_t saved_yp_spin_count_unit = yp_spin_count_unit; - yp_spin_count_unit = (uint32_t)((float)original_spin_count_unit * scalingFactor / (float)9); - - // It's very suspicious if it becomes 0 and also, we don't want to spin too much. - if ((yp_spin_count_unit == 0) || (yp_spin_count_unit > 32768)) + if (!gc_heap::spin_count_unit_config_p) { - yp_spin_count_unit = saved_yp_spin_count_unit; + assert (yp_spin_count_unit != 0); + uint32_t saved_yp_spin_count_unit = yp_spin_count_unit; + yp_spin_count_unit = (uint32_t)((float)original_spin_count_unit * scalingFactor / (float)9); + + // It's very suspicious if it becomes 0 and also, we don't want to spin too much. + if ((yp_spin_count_unit == 0) || (yp_spin_count_unit > MAX_YP_SPIN_COUNT_UNIT)) + { + yp_spin_count_unit = saved_yp_spin_count_unit; + } } } diff --git a/src/coreclr/gc/gcconfig.h b/src/coreclr/gc/gcconfig.h index 2b5f87b41f4cc..c20febbb79dc6 100644 --- a/src/coreclr/gc/gcconfig.h +++ b/src/coreclr/gc/gcconfig.h @@ -136,7 +136,9 @@ class GCConfigStringHolder INT_CONFIG (GCEnabledInstructionSets, "GCEnabledInstructionSets", NULL, -1, "Specifies whether GC can use AVX2 or AVX512F - 0 for neither, 1 for AVX2, 3 for AVX512F")\ INT_CONFIG (GCConserveMem, "GCConserveMemory", "System.GC.ConserveMemory", 0, "Specifies how hard GC should try to conserve memory - values 0-9") \ INT_CONFIG (GCWriteBarrier, "GCWriteBarrier", NULL, 0, "Specifies whether GC should use more precise but slower write barrier") \ - STRING_CONFIG(GCName, "GCName", "System.GC.Name", "Specifies the path of the standalone GC implementation.") + STRING_CONFIG(GCName, "GCName", "System.GC.Name", "Specifies the path of the standalone GC implementation.") \ + INT_CONFIG (GCSpinCountUnit, "GCSpinCountUnit", NULL, 0, "Specifies the spin count unit used by the GC.") + // This class is responsible for retreiving configuration information // for how the GC should operate. class GCConfig diff --git a/src/coreclr/gc/gcpriv.h b/src/coreclr/gc/gcpriv.h index 5caa9c9dc338e..fde1cb3c36f2d 100644 --- a/src/coreclr/gc/gcpriv.h +++ b/src/coreclr/gc/gcpriv.h @@ -4859,6 +4859,9 @@ class gc_heap PER_HEAP_ISOLATED int conserve_mem_setting; + PER_HEAP_ISOLATED + bool spin_count_unit_config_p; + PER_HEAP BOOL gen0_bricks_cleared; PER_HEAP