diff --git a/src/coreclr/nativeaot/Runtime/RhConfig.cpp b/src/coreclr/nativeaot/Runtime/RhConfig.cpp index af6d130bd7dde9..5be922613e6cb6 100644 --- a/src/coreclr/nativeaot/Runtime/RhConfig.cpp +++ b/src/coreclr/nativeaot/Runtime/RhConfig.cpp @@ -99,30 +99,74 @@ bool RhConfig::Environment::TryGetStringValue(const char* name, char** value) if (actualLen == 0) return false; + char* strValue = nullptr; + if (actualLen < bufferLen) { - *value = PalCopyTCharAsChar(buffer); + strValue = PalCopyTCharAsChar(buffer); + if (strValue == nullptr) + return false; + + *value = strValue; return true; } // Expand the buffer to get the value bufferLen = actualLen + 1; NewArrayHolder newBuffer {new (nothrow) TCHAR[bufferLen]}; + + if (newBuffer.IsNull()) + return false; + actualLen = PalGetEnvironmentVariable(variableName, newBuffer, bufferLen); if (actualLen >= bufferLen) return false; #ifdef TARGET_WINDOWS - *value = PalCopyTCharAsChar(newBuffer); + strValue = PalCopyTCharAsChar(newBuffer); + if (strValue == nullptr) + return false; #else - *value = newBuffer.Extract(); + strValue = newBuffer.Extract(); #endif + + *value = strValue; return true; } extern "C" RhConfig::Config g_compilerEmbeddedSettingsBlob; extern "C" RhConfig::Config g_compilerEmbeddedKnobsBlob; +bool RhConfig::ReadStringConfigValue(_In_z_ const char* name, const char** pValue) +{ + char *envValue = nullptr; + if (Environment::TryGetStringValue(name, &envValue)) + { + *pValue = envValue; + return true; + } + + const char *embeddedValue = nullptr; + if (GetEmbeddedVariable(&g_compilerEmbeddedSettingsBlob, name, true, &embeddedValue)) + { + char* strCopy = new (nothrow) char[strlen(embeddedValue) + 1]; + if (strCopy != nullptr) + { + strcpy(strCopy, embeddedValue); + *pValue = strCopy; + + return true; + } + } + + return false; +} + +void RhConfig::FreeStringConfigValue(const char* value) +{ + delete[] value; +} + bool RhConfig::ReadConfigValue(_In_z_ const char *name, uint64_t* pValue, bool decimal) { if (Environment::TryGetIntegerValue(name, pValue, decimal)) @@ -139,6 +183,24 @@ bool RhConfig::ReadConfigValue(_In_z_ const char *name, uint64_t* pValue, bool d return false; } +bool RhConfig::ReadKnobStringValue(_In_z_ const char *name, const char** pValue) +{ + const char *embeddedValue = nullptr; + if (GetEmbeddedVariable(&g_compilerEmbeddedKnobsBlob, name, false, &embeddedValue)) + { + char* strCopy = new (nothrow) char[strlen(embeddedValue) + 1]; + if (strCopy != nullptr) + { + strcpy(strCopy, embeddedValue); + *pValue = strCopy; + + return true; + } + } + + return false; +} + bool RhConfig::ReadKnobUInt64Value(_In_z_ const char *name, uint64_t* pValue) { const char *embeddedValue = nullptr; diff --git a/src/coreclr/nativeaot/Runtime/RhConfig.h b/src/coreclr/nativeaot/Runtime/RhConfig.h index b452d68af65c7e..2f72cf1a4e617c 100644 --- a/src/coreclr/nativeaot/Runtime/RhConfig.h +++ b/src/coreclr/nativeaot/Runtime/RhConfig.h @@ -45,8 +45,11 @@ class RhConfig }; bool ReadConfigValue(_In_z_ const char* wszName, uint64_t* pValue, bool decimal = false); + bool ReadStringConfigValue(_In_z_ const char* wszName, const char** pValue); bool ReadKnobUInt64Value(_In_z_ const char* wszName, uint64_t* pValue); + bool ReadKnobStringValue(_In_z_ const char* wszName, const char** pValue); bool ReadKnobBooleanValue(_In_z_ const char* wszName, bool* pValue); + void FreeStringConfigValue(const char* value); char** GetKnobNames(); char** GetKnobValues(); diff --git a/src/coreclr/nativeaot/Runtime/gcenv.ee.cpp b/src/coreclr/nativeaot/Runtime/gcenv.ee.cpp index e2c31db91e328b..6b118f4504a266 100644 --- a/src/coreclr/nativeaot/Runtime/gcenv.ee.cpp +++ b/src/coreclr/nativeaot/Runtime/gcenv.ee.cpp @@ -797,16 +797,22 @@ uint64_t GCToEEInterface::GetThreadOSThreadId(Thread* thread) bool GCToEEInterface::GetStringConfigValue(const char* privateKey, const char* publicKey, const char** value) { - UNREFERENCED_PARAMETER(privateKey); - UNREFERENCED_PARAMETER(publicKey); - UNREFERENCED_PARAMETER(value); + if (g_pRhConfig->ReadStringConfigValue(privateKey, value)) + { + return true; + } + + if (publicKey) + { + return g_pRhConfig->ReadKnobStringValue(publicKey, value); + } return false; } void GCToEEInterface::FreeStringConfigValue(const char* value) { - delete[] value; + g_pRhConfig->FreeStringConfigValue(value); } void GCToEEInterface::TriggerClientBridgeProcessing(MarkCrossReferencesArgs* args) diff --git a/src/coreclr/nativeaot/Runtime/unix/PalUnix.cpp b/src/coreclr/nativeaot/Runtime/unix/PalUnix.cpp index 14efb5a984e641..a99cbf4475794a 100644 --- a/src/coreclr/nativeaot/Runtime/unix/PalUnix.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/PalUnix.cpp @@ -859,6 +859,11 @@ void PalPrintFatalError(const char* message) char* PalCopyTCharAsChar(const TCHAR* toCopy) { NewArrayHolder copy {new (nothrow) char[strlen(toCopy) + 1]}; + if (copy.IsNull()) + { + return nullptr; + } + strcpy(copy, toCopy); return copy.Extract(); } diff --git a/src/coreclr/nativeaot/Runtime/windows/PalMinWin.cpp b/src/coreclr/nativeaot/Runtime/windows/PalMinWin.cpp index 7c4a9000913e56..2459f66e8180d2 100644 --- a/src/coreclr/nativeaot/Runtime/windows/PalMinWin.cpp +++ b/src/coreclr/nativeaot/Runtime/windows/PalMinWin.cpp @@ -950,8 +950,12 @@ char* PalCopyTCharAsChar(const TCHAR* toCopy) return nullptr; char* converted = new (nothrow) char[len]; - int written = ::WideCharToMultiByte(CP_UTF8, 0, toCopy, -1, converted, len, nullptr, nullptr); - assert(len == written); + + if (converted != nullptr) + { + int written = ::WideCharToMultiByte(CP_UTF8, 0, toCopy, -1, converted, len, nullptr, nullptr); + assert(len == written); + } return converted; } diff --git a/src/tests/GC/API/GC/GetConfigurationVariables.cs b/src/tests/GC/API/GC/GetConfigurationVariables.cs index 3761669837dee3..ee9ef97918bf11 100644 --- a/src/tests/GC/API/GC/GetConfigurationVariables.cs +++ b/src/tests/GC/API/GC/GetConfigurationVariables.cs @@ -14,11 +14,23 @@ public static void CollectAllVariables() var configurations = GC.GetConfigurationVariables(); Assert.True(configurations != null); Assert.True(configurations.Count >= 0); + bool foundGCHeapAffinitizeRanges = false; foreach(var kvp in configurations) { + Console.WriteLine($"{kvp.Key} set to {kvp.Value}"); Assert.True(kvp.Key != null, "The name of the configuration is null."); Assert.True(kvp.Value != null, $"The value of configuration: {kvp.Key} is null."); + if (kvp.Key == "GCHeapAffinitizeRanges") + { + Assert.True(kvp.Value.ToString() == "1", "The expected value of GCHeapAffinitizeRanges is 1"); + foundGCHeapAffinitizeRanges = true; + } + } + + if (!TestLibrary.Utilities.IsMonoRuntime) + { + Assert.True(foundGCHeapAffinitizeRanges, "The GCHeapAffinitizeRanges was not found"); } } } -} \ No newline at end of file +} diff --git a/src/tests/GC/API/GC/GetConfigurationVariables.csproj b/src/tests/GC/API/GC/GetConfigurationVariables.csproj index d51cb0b82cb0dd..66619f6e918725 100644 --- a/src/tests/GC/API/GC/GetConfigurationVariables.csproj +++ b/src/tests/GC/API/GC/GetConfigurationVariables.csproj @@ -3,8 +3,15 @@ true 0 + true + + + + + +