From b321111d45216349f5fdf234302a03a071d5d911 Mon Sep 17 00:00:00 2001 From: Sean Gillespie Date: Wed, 13 Jan 2016 18:09:44 -0800 Subject: Enable corerun to select server GC or concurrent GC on startup based on environment variables --- src/coreclr/hosts/corerun/corerun.cpp | 55 ++++++++++++++++++++-- .../hosts/unixcoreruncommon/coreruncommon.cpp | 32 ++++++++++++- 2 files changed, 80 insertions(+), 7 deletions(-) diff --git a/src/coreclr/hosts/corerun/corerun.cpp b/src/coreclr/hosts/corerun/corerun.cpp index 6505a36362..4ac1911c0a 100644 --- a/src/coreclr/hosts/corerun/corerun.cpp +++ b/src/coreclr/hosts/corerun/corerun.cpp @@ -14,6 +14,17 @@ #include #include "palclr.h" +// Utility macro for testing whether or not a flag is set. +#define HAS_FLAG(value, flag) (((value) & (flag)) == (flag)) + +// Environment variable for setting whether or not to use Server GC. +// Off by default. +static const wchar_t *serverGcVar = W("CORECLR_SERVER_GC"); + +// Environment variable for setting whether or not to use Concurrent GC. +// On by default. +static const wchar_t *concurrentGcVar = W("CORECLR_CONCURRENT_GC"); + // The name of the CoreCLR native runtime DLL. static const wchar_t *coreCLRDll = W("CoreCLR.dll"); @@ -375,6 +386,39 @@ public: }; +// Creates the startup flags for the runtime, starting with the default startup +// flags and adding or removing from them based on environment variables. Only +// two environment variables are respected right now: serverGcVar, controlling +// Server GC, and concurrentGcVar, controlling Concurrent GC. +STARTUP_FLAGS CreateStartupFlags() { + auto initialFlags = + static_cast( + STARTUP_FLAGS::STARTUP_LOADER_OPTIMIZATION_SINGLE_DOMAIN | + STARTUP_FLAGS::STARTUP_SINGLE_APPDOMAIN | + STARTUP_FLAGS::STARTUP_CONCURRENT_GC); + + // server GC is off by default, concurrent GC is on by default. + auto checkVariable = [&](STARTUP_FLAGS flag, const wchar_t *var) { + wchar_t result[25]; + size_t outsize; + if (_wgetenv_s(&outsize, result, 25, var) == 0 && outsize > 0) { + // set the flag if the var is present and set to 1, + // clear the flag if the var isp resent and set to 0. + // Otherwise, ignore it. + if (_wcsicmp(result, W("1")) == 0) { + initialFlags = static_cast(initialFlags | flag); + } else if (_wcsicmp(result, W("0")) == 0) { + initialFlags = static_cast(initialFlags & ~flag); + } + } + }; + + checkVariable(STARTUP_FLAGS::STARTUP_SERVER_GC, serverGcVar); + checkVariable(STARTUP_FLAGS::STARTUP_CONCURRENT_GC, concurrentGcVar); + + return initialFlags; +} + bool TryRun(const int argc, const wchar_t* argv[], Logger &log, const bool verbose, const bool waitForDebugger, DWORD &exitCode) { @@ -450,14 +494,15 @@ bool TryRun(const int argc, const wchar_t* argv[], Logger &log, const bool verbo } HRESULT hr; - + + + STARTUP_FLAGS flags = CreateStartupFlags(); log << W("Setting ICLRRuntimeHost2 startup flags") << Logger::endl; + log << W("Server GC enabled: ") << HAS_FLAG(flags, STARTUP_FLAGS::STARTUP_SERVER_GC) << Logger::endl; + log << W("Concurrent GC enabled: ") << HAS_FLAG(flags, STARTUP_FLAGS::STARTUP_CONCURRENT_GC) << Logger::endl; // Default startup flags - hr = host->SetStartupFlags((STARTUP_FLAGS) - (STARTUP_FLAGS::STARTUP_LOADER_OPTIMIZATION_SINGLE_DOMAIN | - STARTUP_FLAGS::STARTUP_SINGLE_APPDOMAIN | - STARTUP_FLAGS::STARTUP_CONCURRENT_GC)); + hr = host->SetStartupFlags(flags); if (FAILED(hr)) { log << W("Failed to set startup flags. ERRORCODE: ") << Logger::hresult << hr << Logger::endl; return false; diff --git a/src/coreclr/hosts/unixcoreruncommon/coreruncommon.cpp b/src/coreclr/hosts/unixcoreruncommon/coreruncommon.cpp index 71598320a2..ba7c62e312 100644 --- a/src/coreclr/hosts/unixcoreruncommon/coreruncommon.cpp +++ b/src/coreclr/hosts/unixcoreruncommon/coreruncommon.cpp @@ -20,6 +20,15 @@ #define SUCCEEDED(Status) ((Status) >= 0) +// Name of the environment variable controlling server GC. +// If set to 1, server GC is enabled on startup. If 0, server GC is +// disabled. Server GC is off by default. +static const char* serverGcVar = "CORECLR_SERVER_GC"; + +// Name of the environment variable controlling concurrent GC, +// used in the same way as serverGcVar. Concurrent GC is on by default. +static const char* concurrentGcVar = "CORECLR_CONCURRENT_GC"; + // Prototype of the coreclr_initialize function from the libcoreclr.so typedef int (*InitializeCoreCLRFunction)( const char* exePath, @@ -288,6 +297,19 @@ int ExecuteManagedAssembly( } else { + // check if we are enabling server GC or concurrent GC. + // Server GC is off by default, while concurrent GC is on by default. + // Actual checking of these string values is done in coreclr_initialize. + const char* useServerGc = std::getenv(serverGcVar); + if (useServerGc == nullptr) { + useServerGc = "0"; + } + + const char* useConcurrentGc = std::getenv(concurrentGcVar); + if (useConcurrentGc == nullptr) { + useConcurrentGc = "1"; + } + // Allowed property names: // APPBASE // - The base path of the application from which the exe and other assemblies will be loaded @@ -309,7 +331,9 @@ int ExecuteManagedAssembly( "APP_PATHS", "APP_NI_PATHS", "NATIVE_DLL_SEARCH_DIRECTORIES", - "AppDomainCompatSwitch" + "AppDomainCompatSwitch", + "SERVER_GC", + "CONCURRENT_GC" }; const char *propertyValues[] = { // TRUSTED_PLATFORM_ASSEMBLIES @@ -321,7 +345,11 @@ int ExecuteManagedAssembly( // NATIVE_DLL_SEARCH_DIRECTORIES nativeDllSearchDirs.c_str(), // AppDomainCompatSwitch - "UseLatestBehaviorWhenTFMNotSpecified" + "UseLatestBehaviorWhenTFMNotSpecified", + // SERVER_GC + useServerGc, + // CONCURRENT_GC + useConcurrentGc }; void* hostHandle; -- cgit v1.2.3