Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions src/coreclr/gc/gc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44803,8 +44803,9 @@ HRESULT GCHeap::Initialize()
uint32_t nhp = 1;
uint32_t nhp_from_config = 0;

#ifdef MULTIPLE_HEAPS

#ifndef MULTIPLE_HEAPS
GCConfig::SetServerGC(false);
#else //!MULTIPLE_HEAPS
GCConfig::SetServerGC(true);
AffinitySet config_affinity_set;
GCConfigStringHolder cpu_index_ranges_holder(GCConfig::GetGCHeapAffinitizeRanges());
Expand Down Expand Up @@ -44861,7 +44862,7 @@ HRESULT GCHeap::Initialize()
nhp = min(nhp, num_affinitized_processors);
}
}
#endif //MULTIPLE_HEAPS
#endif //!MULTIPLE_HEAPS

size_t seg_size = 0;
size_t large_seg_size = 0;
Expand Down
17 changes: 11 additions & 6 deletions src/coreclr/gc/gcconfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,18 @@

#define BOOL_CONFIG(name, unused_private_key, unused_public_key, default, unused_doc) \
bool GCConfig::Get##name() { return s_##name; } \
bool GCConfig::Get##name(bool defaultValue) \
{ \
return s_##name##Provided ? s_##name : defaultValue; \
} \
void GCConfig::Set##name(bool value) { s_Updated##name = value; } \
bool GCConfig::s_##name = default; \
bool GCConfig::s_##name##Provided = false; \
bool GCConfig::s_Updated##name = default;

#define INT_CONFIG(name, unused_private_key, unused_public_key, default, unused_doc) \
int64_t GCConfig::Get##name() { return s_##name; } \
void GCConfig::Set##name(int64_t value) { s_Updated##name = value; } \
void GCConfig::Set##name(int64_t value) { s_Updated##name = value; } \
int64_t GCConfig::s_##name = default; \
int64_t GCConfig::s_Updated##name = default;

Expand All @@ -36,7 +41,7 @@ GC_CONFIGURATION_KEYS

void GCConfig::EnumerateConfigurationValues(void* context, ConfigurationValueFunc configurationValueFunc)
{
#define INT_CONFIG(name, unused_private_key, public_key, default, unused_doc) \
#define INT_CONFIG(name, unused_private_key, public_key, unused_default, unused_doc) \
configurationValueFunc(context, (void*)(#name), (void*)(public_key), GCConfigurationType::Int64, static_cast<int64_t>(s_Updated##name));

#define STRING_CONFIG(name, private_key, public_key, unused_doc) \
Expand All @@ -47,7 +52,7 @@ void GCConfig::EnumerateConfigurationValues(void* context, ConfigurationValueFun
configurationValueFunc(context, (void*)(#name), (void*)(public_key), GCConfigurationType::StringUtf8, reinterpret_cast<int64_t>(resultStr)); \
}

#define BOOL_CONFIG(name, unused_private_key, public_key, default, unused_doc) \
#define BOOL_CONFIG(name, unused_private_key, public_key, unused_default, unused_doc) \
configurationValueFunc(context, (void*)(#name), (void*)(public_key), GCConfigurationType::Boolean, static_cast<int64_t>(s_Updated##name));

GC_CONFIGURATION_KEYS
Expand All @@ -59,10 +64,10 @@ GC_CONFIGURATION_KEYS

void GCConfig::Initialize()
{
#define BOOL_CONFIG(name, private_key, public_key, default, unused_doc) \
GCToEEInterface::GetBooleanConfigValue(private_key, public_key, &s_##name);
#define BOOL_CONFIG(name, private_key, public_key, unused_default, unused_doc) \
s_##name##Provided = GCToEEInterface::GetBooleanConfigValue(private_key, public_key, &s_##name);

#define INT_CONFIG(name, private_key, public_key, default, unused_doc) \
#define INT_CONFIG(name, private_key, public_key, unused_default, unused_doc) \
GCToEEInterface::GetIntConfigValue(private_key, public_key, &s_##name);

#define STRING_CONFIG(unused_name, unused_private_key, unused_public_key, unused_doc)
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/gc/gcconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,10 @@ class GCConfig
{
#define BOOL_CONFIG(name, unused_private_key, unused_public_key, unused_default, unused_doc) \
public: static bool Get##name(); \
public: static bool Get##name(bool defaultValue); \
public: static void Set##name(bool value); \
private: static bool s_##name; \
private: static bool s_##name##Provided; \
private: static bool s_Updated##name;

#define INT_CONFIG(name, unused_private_key, unused_public_key, unused_default, unused_doc) \
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/gc/gcload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,11 @@ GC_Initialize(
assert(clrToGC == nullptr);
#endif

#ifndef FEATURE_NATIVEAOT // GCConfig and GCToOSInterface are initialized in PalInit
// Initialize GCConfig before anything else - initialization of our
// various components may want to query the current configuration.
GCConfig::Initialize();

#ifndef FEATURE_NATIVEAOT // GCToOSInterface is initialized directly
if (!GCToOSInterface::Initialize())
{
return E_FAIL;
Expand All @@ -92,7 +92,7 @@ GC_Initialize(
}

#ifdef FEATURE_SVR_GC
if (GCConfig::GetServerGC())
if (GCConfig::GetServerGC() && GCToEEInterface::GetCurrentProcessCpuCount() > 1)
{
#ifdef WRITE_BARRIER_CHECK
g_GCShadow = 0;
Expand Down
34 changes: 14 additions & 20 deletions src/coreclr/gc/windows/gcenv.windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ struct CPU_Group_Info
};

static bool g_fEnableGCCPUGroups;
static bool g_fHadSingleProcessorAtStartup;
static DWORD g_nGroups;
static DWORD g_nProcessors;
static CPU_Group_Info *g_CPUGroupInfoArray;
Expand Down Expand Up @@ -220,26 +219,26 @@ void InitCPUGroupInfo()
g_fEnableGCCPUGroups = false;

#if (defined(TARGET_AMD64) || defined(TARGET_ARM64))
if (!GCConfig::GetGCCpuGroup())
USHORT groupCount = 0;

// On Windows 11+ and Windows Server 2022+, a process is no longer restricted to a single processor group by default.
// If more than one processor group is available to the process (a non-affinitized process on Windows 11+),
// default to using multiple processor groups; otherwise, default to using a single processor group. This default
// behavior may be overridden by the configuration value below.
if (GetProcessGroupAffinity(GetCurrentProcess(), &groupCount, NULL) || GetLastError() != ERROR_INSUFFICIENT_BUFFER)
groupCount = 1;

bool enableGCCPUGroups = GCConfig::GetGCCpuGroup(/* defaultValue */ groupCount > 1);

if (!enableGCCPUGroups)
return;

if (!InitCPUGroupInfoArray())
return;

// only enable CPU groups if more than one group exists
// Enable processor groups only if more than one group exists
g_fEnableGCCPUGroups = g_nGroups > 1;
#endif // TARGET_AMD64 || TARGET_ARM64

// Determine if the process is affinitized to a single processor (or if the system has a single processor)
DWORD_PTR processAffinityMask, systemAffinityMask;
if (::GetProcessAffinityMask(::GetCurrentProcess(), &processAffinityMask, &systemAffinityMask))
{
if (processAffinityMask != 0 && // only one CPU group is involved
(processAffinityMask & (processAffinityMask - 1)) == 0) // only one bit is set
{
g_fHadSingleProcessorAtStartup = true;
}
}
}

void GetProcessMemoryLoad(LPMEMORYSTATUSEX pMSEX)
Expand Down Expand Up @@ -475,17 +474,12 @@ size_t GetLogicalProcessorCacheSizeFromOS()
return cache_size;
}

bool CanEnableGCCPUGroups()
{
return g_fEnableGCCPUGroups;
}

// Get the CPU group for the specified processor
void GetGroupForProcessor(uint16_t processor_number, uint16_t* group_number, uint16_t* group_processor_number)
{
assert(g_fEnableGCCPUGroups);

#if !defined(FEATURE_NATIVEAOT) && (defined(TARGET_AMD64) || defined(TARGET_ARM64))
#if defined(TARGET_AMD64) || defined(TARGET_ARM64)
WORD bTemp = 0;
WORD bDiff = processor_number - bTemp;

Expand Down
7 changes: 0 additions & 7 deletions src/coreclr/nativeaot/Runtime/gcrhenv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1307,13 +1307,6 @@ MethodTable* GCToEEInterface::GetFreeObjectMethodTable()

bool GCToEEInterface::GetBooleanConfigValue(const char* privateKey, const char* publicKey, bool* value)
{
// these configuration values are given to us via startup flags.
if (strcmp(privateKey, "gcServer") == 0)
{
*value = g_heap_type == GC_HEAP_SVR;
return true;
}

if (strcmp(privateKey, "gcConservative") == 0)
{
*value = true;
Expand Down
4 changes: 4 additions & 0 deletions src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
#include "UnixHandle.h"
#include <pthread.h>
#include "gcenv.h"
#include "gcenv.ee.h"
#include "gcconfig.h"
#include "holder.h"
#include "UnixSignals.h"
#include "UnixContext.h"
Expand Down Expand Up @@ -417,6 +419,8 @@ REDHAWK_PALEXPORT bool REDHAWK_PALAPI PalInit()

ConfigureSignals();

GCConfig::Initialize();

if (!GCToOSInterface::Initialize())
{
return false;
Expand Down
48 changes: 28 additions & 20 deletions src/coreclr/nativeaot/Runtime/windows/PalRedhawkMinWin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ uint32_t PalEventWrite(REGHANDLE arg1, const EVENT_DESCRIPTOR * arg2, uint32_t a
}

#include "gcenv.h"
#include "gcenv.ee.h"
#include "gcconfig.h"


#define REDHAWK_PALEXPORT extern "C"
Expand Down Expand Up @@ -71,29 +73,36 @@ void InitializeCurrentProcessCpuCount()
}
else
{
DWORD_PTR pmask, smask;

if (!GetProcessAffinityMask(GetCurrentProcess(), &pmask, &smask))
if (GCToOSInterface::CanEnableGCCPUGroups())
{
count = 1;
count = GCToOSInterface::GetTotalProcessorCount();
}
else
{
count = 0;
DWORD_PTR pmask, smask;

while (pmask)
if (!GetProcessAffinityMask(GetCurrentProcess(), &pmask, &smask))
{
pmask &= (pmask - 1);
count++;
count = 1;
}
else
{
count = 0;

while (pmask)
{
pmask &= (pmask - 1);
count++;
}

// GetProcessAffinityMask can return pmask=0 and smask=0 on systems with more
// than 64 processors, which would leave us with a count of 0. Since the GC
// expects there to be at least one processor to run on (and thus at least one
// heap), we'll return 64 here if count is 0, since there are likely a ton of
// processors available in that case.
if (count == 0)
count = 64;
}

// GetProcessAffinityMask can return pmask=0 and smask=0 on systems with more
// than 64 processors, which would leave us with a count of 0. Since the GC
// expects there to be at least one processor to run on (and thus at least one
// heap), we'll return 64 here if count is 0, since there are likely a ton of
// processors available in that case.
if (count == 0)
count = 64;
}

JOBOBJECT_CPU_RATE_CONTROL_INFORMATION cpuRateControl;
Expand All @@ -119,10 +128,7 @@ void InitializeCurrentProcessCpuCount()

if (0 < maxRate && maxRate < MAXIMUM_CPU_RATE)
{
SYSTEM_INFO systemInfo;
GetSystemInfo(&systemInfo);

DWORD cpuLimit = (maxRate * systemInfo.dwNumberOfProcessors + MAXIMUM_CPU_RATE - 1) / MAXIMUM_CPU_RATE;
DWORD cpuLimit = (maxRate * GCToOSInterface::GetTotalProcessorCount() + MAXIMUM_CPU_RATE - 1) / MAXIMUM_CPU_RATE;
if (cpuLimit < count)
count = cpuLimit;
}
Expand All @@ -145,6 +151,8 @@ REDHAWK_PALEXPORT bool REDHAWK_PALAPI PalInit()
return false;
}

GCConfig::Initialize();

if (!GCToOSInterface::Initialize())
{
return false;
Expand Down