From 41710cbef4faae344e2523de598c1e38de9fa810 Mon Sep 17 00:00:00 2001 From: Manish Godse <61718172+mangod9@users.noreply.github.com> Date: Wed, 12 Oct 2022 20:45:44 -0700 Subject: [PATCH 01/11] statically linking GC PAL The GC PAL will be used for both coreclr and standalone GC on linux --- .../dlls/mscoree/coreclr/CMakeLists.txt | 2 + src/coreclr/gc/CMakeLists.txt | 8 ++-- src/coreclr/gc/unix/cgroup.cpp | 15 +++--- src/coreclr/gc/unix/gcenv.unix.cpp | 48 +++++++++---------- src/coreclr/vm/CMakeLists.txt | 2 +- 5 files changed, 38 insertions(+), 37 deletions(-) diff --git a/src/coreclr/dlls/mscoree/coreclr/CMakeLists.txt b/src/coreclr/dlls/mscoree/coreclr/CMakeLists.txt index 688629d178ddc..6e22bd96f79dc 100644 --- a/src/coreclr/dlls/mscoree/coreclr/CMakeLists.txt +++ b/src/coreclr/dlls/mscoree/coreclr/CMakeLists.txt @@ -82,6 +82,7 @@ set_property(TARGET coreclr APPEND_STRING PROPERTY LINK_DEPENDS ${EXPORTS_FILE}) if (CLR_CMAKE_HOST_UNIX) set(LIB_UNWINDER unwinder_wks) + set(GC_PAL gc_unix) endif (CLR_CMAKE_HOST_UNIX) # IMPORTANT! Please do not rearrange the order of the libraries. The linker on Linux is @@ -108,6 +109,7 @@ set(CORECLR_LIBRARIES System.Globalization.Native-Static interop coreclrminipal + ${GC_PAL} ) if(CLR_CMAKE_TARGET_WIN32) diff --git a/src/coreclr/gc/CMakeLists.txt b/src/coreclr/gc/CMakeLists.txt index 9052c4a529f7e..4441c41df36f9 100644 --- a/src/coreclr/gc/CMakeLists.txt +++ b/src/coreclr/gc/CMakeLists.txt @@ -27,12 +27,10 @@ set(GC_SOURCES handletablecache.cpp) if(CLR_CMAKE_HOST_UNIX) + add_subdirectory(unix) include(unix/configure.cmake) set (GC_SOURCES - ${GC_SOURCES} - unix/gcenv.unix.cpp - unix/events.cpp - unix/cgroup.cpp) + ${GC_SOURCES}) else() set (GC_SOURCES ${GC_SOURCES} @@ -101,7 +99,7 @@ if(CLR_CMAKE_HOST_WIN32) kernel32.lib advapi32.lib) else() - set (GC_LINK_LIBRARIES) + set (GC_LINK_LIBRARIES gc_unix) endif(CLR_CMAKE_HOST_WIN32) list(APPEND GC_SOURCES ${GC_HEADERS}) diff --git a/src/coreclr/gc/unix/cgroup.cpp b/src/coreclr/gc/unix/cgroup.cpp index ad2a41284cbbe..99accf455f6e4 100644 --- a/src/coreclr/gc/unix/cgroup.cpp +++ b/src/coreclr/gc/unix/cgroup.cpp @@ -54,7 +54,8 @@ Module Name: extern bool ReadMemoryValueFromFile(const char* filename, uint64_t* val); -class CGroup + +class CGroup_GC { // the cgroup version number or 0 to indicate cgroups are not found or not enabled static int s_cgroup_version; @@ -454,24 +455,24 @@ class CGroup } }; -int CGroup::s_cgroup_version = 0; -char *CGroup::s_memory_cgroup_path = nullptr; +int CGroup_GC::s_cgroup_version = 0; +char *CGroup_GC::s_memory_cgroup_path = nullptr; void InitializeCGroup() { - CGroup::Initialize(); + CGroup_GC::Initialize(); } void CleanupCGroup() { - CGroup::Cleanup(); + CGroup_GC::Cleanup(); } size_t GetRestrictedPhysicalMemoryLimit() { uint64_t physical_memory_limit = 0; - if (!CGroup::GetPhysicalMemoryLimit(&physical_memory_limit)) + if (!CGroup_GC::GetPhysicalMemoryLimit(&physical_memory_limit)) return 0; // If there's no memory limit specified on the container this @@ -526,7 +527,7 @@ bool GetPhysicalMemoryUsed(size_t* val) return false; // Linux uses cgroup usage to trigger oom kills. - if (CGroup::GetPhysicalMemoryUsage(val)) + if (CGroup_GC::GetPhysicalMemoryUsage(val)) return true; // process resident set size. diff --git a/src/coreclr/gc/unix/gcenv.unix.cpp b/src/coreclr/gc/unix/gcenv.unix.cpp index 8037fa084b657..6d9fa1ae40810 100644 --- a/src/coreclr/gc/unix/gcenv.unix.cpp +++ b/src/coreclr/gc/unix/gcenv.unix.cpp @@ -152,16 +152,16 @@ typedef cpuset_t cpu_set_t; PER_FUNCTION_BLOCK(numa_node_of_cpu) // Declare pointers to all the used numa functions -#define PER_FUNCTION_BLOCK(fn) extern decltype(fn)* fn##_ptr; +#define PER_FUNCTION_BLOCK(fn) extern decltype(fn)* fn##_ptr_gc; FOR_ALL_NUMA_FUNCTIONS #undef PER_FUNCTION_BLOCK // Redefine all calls to numa functions as calls through pointers that are set // to the functions of libnuma in the initialization. -#define mbind(...) mbind_ptr(__VA_ARGS__) -#define numa_available() numa_available_ptr() -#define numa_max_node() numa_max_node_ptr() -#define numa_node_of_cpu(...) numa_node_of_cpu_ptr(__VA_ARGS__) +#define mbind(...) mbind_ptr_gc(__VA_ARGS__) +#define numa_available() numa_available_ptr_gc() +#define numa_max_node() numa_max_node_ptr_gc() +#define numa_node_of_cpu(...) numa_node_of_cpu_ptr_gc(__VA_ARGS__) #endif // HAVE_NUMA_H @@ -234,14 +234,14 @@ uint32_t g_pageSizeUnixInl = 0; AffinitySet g_processAffinitySet; // The highest NUMA node available -int g_highestNumaNode = 0; +int g_highestNumaNode_gc = 0; // Is numa available -bool g_numaAvailable = false; +bool g_numaAvailable_gc = false; void* g_numaHandle = nullptr; #if HAVE_NUMA_H -#define PER_FUNCTION_BLOCK(fn) decltype(fn)* fn##_ptr; +#define PER_FUNCTION_BLOCK(fn) decltype(fn)* fn##_ptr_gc; FOR_ALL_NUMA_FUNCTIONS #undef PER_FUNCTION_BLOCK @@ -297,8 +297,8 @@ void NUMASupportInitialize() #if HAVE_NUMA_H if (!ShouldOpenLibNuma()) { - g_numaAvailable = false; - g_highestNumaNode = 0; + g_numaAvailable_gc = false; + g_highestNumaNode_gc = 0; return; } @@ -314,8 +314,8 @@ void NUMASupportInitialize() if (g_numaHandle != 0) { #define PER_FUNCTION_BLOCK(fn) \ - fn##_ptr = (decltype(fn)*)dlsym(g_numaHandle, #fn); \ - if (fn##_ptr == NULL) { fprintf(stderr, "Cannot get symbol " #fn " from libnuma\n"); abort(); } + fn##_ptr_gc = (decltype(fn)*)dlsym(g_numaHandle, #fn); \ + if (fn##_ptr_gc == NULL) { fprintf(stderr, "Cannot get symbol " #fn " from libnuma\n"); abort(); } FOR_ALL_NUMA_FUNCTIONS #undef PER_FUNCTION_BLOCK @@ -325,15 +325,15 @@ FOR_ALL_NUMA_FUNCTIONS } else { - g_numaAvailable = true; - g_highestNumaNode = numa_max_node(); + g_numaAvailable_gc = true; + g_highestNumaNode_gc = numa_max_node(); } } #endif // HAVE_NUMA_H - if (!g_numaAvailable) + if (!g_numaAvailable_gc) { // No NUMA - g_highestNumaNode = 0; + g_highestNumaNode_gc = 0; } } @@ -341,7 +341,7 @@ FOR_ALL_NUMA_FUNCTIONS void NUMASupportCleanup() { #if HAVE_NUMA_H - if (g_numaAvailable) + if (g_numaAvailable_gc) { dlclose(g_numaHandle); } @@ -725,11 +725,11 @@ bool GCToOSInterface::VirtualCommit(void* address, size_t size, uint16_t node) bool success = mprotect(address, size, PROT_WRITE | PROT_READ) == 0; #if HAVE_NUMA_H - if (success && g_numaAvailable && (node != NUMA_NODE_UNDEFINED)) + if (success && g_numaAvailable_gc && (node != NUMA_NODE_UNDEFINED)) { - if ((int)node <= g_highestNumaNode) + if ((int)node <= g_highestNumaNode_gc) { - int usedNodeMaskBits = g_highestNumaNode + 1; + int usedNodeMaskBits = g_highestNumaNode_gc + 1; int nodeMaskLength = (usedNodeMaskBits + sizeof(unsigned long) - 1) / sizeof(unsigned long); unsigned long nodeMask[nodeMaskLength]; memset(nodeMask, 0, sizeof(nodeMask)); @@ -825,7 +825,7 @@ bool GCToOSInterface::GetWriteWatch(bool resetState, void* address, size_t size, return false; } -bool ReadMemoryValueFromFile(const char* filename, uint64_t* val) +bool _ReadMemoryValueFromFile(const char* filename, uint64_t* val) { bool result = false; char* line = nullptr; @@ -917,11 +917,11 @@ static size_t GetLogicalProcessorCacheSizeFromOS() { path_to_size_file[index] = (char)(48 + i); - if (ReadMemoryValueFromFile(path_to_size_file, &size)) + if (_ReadMemoryValueFromFile(path_to_size_file, &size)) { path_to_level_file[index] = (char)(48 + i); - if (ReadMemoryValueFromFile(path_to_level_file, &level)) + if (_ReadMemoryValueFromFile(path_to_level_file, &level)) { UPDATE_CACHE_SIZE_AND_LEVEL(size, level) } @@ -1494,7 +1494,7 @@ uint32_t GCToOSInterface::GetTotalProcessorCount() bool GCToOSInterface::CanEnableGCNumaAware() { - return g_numaAvailable; + return g_numaAvailable_gc; } bool GCToOSInterface::CanEnableGCCPUGroups() diff --git a/src/coreclr/vm/CMakeLists.txt b/src/coreclr/vm/CMakeLists.txt index 153fe06f44f4a..66ba446346926 100644 --- a/src/coreclr/vm/CMakeLists.txt +++ b/src/coreclr/vm/CMakeLists.txt @@ -324,7 +324,6 @@ set(VM_SOURCES_WKS gccover.cpp gcenv.ee.static.cpp gcenv.ee.common.cpp - gcenv.os.cpp gchelpers.cpp genanalysis.cpp genmeth.cpp @@ -492,6 +491,7 @@ set(GC_SOURCES_WKS if (CLR_CMAKE_TARGET_ARCH_AMD64 AND CLR_CMAKE_TARGET_WIN32) set ( GC_SOURCES_WKS ${GC_SOURCES_WKS} + gcenv.os.cpp ../gc/vxsort/isa_detection.cpp ../gc/vxsort/do_vxsort_avx2.cpp ../gc/vxsort/do_vxsort_avx512.cpp From 61426d707180fe521da57faa378b62f18f9c3d23 Mon Sep 17 00:00:00 2001 From: Manish Godse <61718172+mangod9@users.noreply.github.com> Date: Thu, 13 Oct 2022 00:32:43 -0700 Subject: [PATCH 02/11] fixing arm64 and nativeaot build breaks --- src/coreclr/gc/unix/cgroup.cpp | 7 +++---- src/coreclr/gc/unix/gcenv.unix.cpp | 6 +++--- src/coreclr/vm/CMakeLists.txt | 8 +++++++- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/coreclr/gc/unix/cgroup.cpp b/src/coreclr/gc/unix/cgroup.cpp index 99accf455f6e4..447e6ee336cc6 100644 --- a/src/coreclr/gc/unix/cgroup.cpp +++ b/src/coreclr/gc/unix/cgroup.cpp @@ -52,8 +52,7 @@ Module Name: #define CGROUP1_MEMORY_STAT_INACTIVE_FIELD "total_inactive_file " #define CGROUP2_MEMORY_STAT_INACTIVE_FIELD "inactive_file " -extern bool ReadMemoryValueFromFile(const char* filename, uint64_t* val); - +extern bool ReadMemoryValueFromFile_GC(const char* filename, uint64_t* val); class CGroup_GC { @@ -375,7 +374,7 @@ class CGroup_GC if (asprintf(&mem_limit_filename, "%s%s", s_memory_cgroup_path, filename) < 0) return false; - bool result = ReadMemoryValueFromFile(mem_limit_filename, val); + bool result = ReadMemoryValueFromFile_GC(mem_limit_filename, val); free(mem_limit_filename); return result; } @@ -394,7 +393,7 @@ class CGroup_GC size_t usage = 0; - bool result = ReadMemoryValueFromFile(mem_usage_filename, &temp); + bool result = ReadMemoryValueFromFile_GC(mem_usage_filename, &temp); if (result) { if (temp > std::numeric_limits::max()) diff --git a/src/coreclr/gc/unix/gcenv.unix.cpp b/src/coreclr/gc/unix/gcenv.unix.cpp index 6d9fa1ae40810..07078613fd1aa 100644 --- a/src/coreclr/gc/unix/gcenv.unix.cpp +++ b/src/coreclr/gc/unix/gcenv.unix.cpp @@ -825,7 +825,7 @@ bool GCToOSInterface::GetWriteWatch(bool resetState, void* address, size_t size, return false; } -bool _ReadMemoryValueFromFile(const char* filename, uint64_t* val) +bool ReadMemoryValueFromFile_GC(const char* filename, uint64_t* val) { bool result = false; char* line = nullptr; @@ -917,11 +917,11 @@ static size_t GetLogicalProcessorCacheSizeFromOS() { path_to_size_file[index] = (char)(48 + i); - if (_ReadMemoryValueFromFile(path_to_size_file, &size)) + if (ReadMemoryValueFromFile_GC(path_to_size_file, &size)) { path_to_level_file[index] = (char)(48 + i); - if (_ReadMemoryValueFromFile(path_to_level_file, &level)) + if (ReadMemoryValueFromFile_GC(path_to_level_file, &level)) { UPDATE_CACHE_SIZE_AND_LEVEL(size, level) } diff --git a/src/coreclr/vm/CMakeLists.txt b/src/coreclr/vm/CMakeLists.txt index 66ba446346926..8ac82802a9a41 100644 --- a/src/coreclr/vm/CMakeLists.txt +++ b/src/coreclr/vm/CMakeLists.txt @@ -491,7 +491,6 @@ set(GC_SOURCES_WKS if (CLR_CMAKE_TARGET_ARCH_AMD64 AND CLR_CMAKE_TARGET_WIN32) set ( GC_SOURCES_WKS ${GC_SOURCES_WKS} - gcenv.os.cpp ../gc/vxsort/isa_detection.cpp ../gc/vxsort/do_vxsort_avx2.cpp ../gc/vxsort/do_vxsort_avx512.cpp @@ -504,6 +503,13 @@ if (CLR_CMAKE_TARGET_ARCH_AMD64 AND CLR_CMAKE_TARGET_WIN32) ) endif (CLR_CMAKE_TARGET_ARCH_AMD64 AND CLR_CMAKE_TARGET_WIN32) +if (CLR_CMAKE_TARGET_WIN32) + set ( GC_SOURCES_WKS + ${GC_SOURCES_WKS} + gcenv.os.cpp + ) +endif (CLR_CMAKE_TARGET_WIN32) + set(GC_HEADERS_WKS ${GC_HEADERS_DAC_AND_WKS_COMMON} ../gc/gceventstatus.h From 225f7253b821c54775896f774598a1d1dc7ccd89 Mon Sep 17 00:00:00 2001 From: Manish Godse <61718172+mangod9@users.noreply.github.com> Date: Thu, 13 Oct 2022 16:02:26 -0700 Subject: [PATCH 03/11] macos build break and reducing renaming. --- src/coreclr/gc/env/gcenv.os.h | 3 +- src/coreclr/gc/gc.cpp | 2 +- src/coreclr/gc/unix/cgroup.cpp | 23 ++++++----- src/coreclr/gc/unix/gcenv.unix.cpp | 64 ++++++++++-------------------- 4 files changed, 36 insertions(+), 56 deletions(-) diff --git a/src/coreclr/gc/env/gcenv.os.h b/src/coreclr/gc/env/gcenv.os.h index c38892b0cadc2..7b61403849539 100644 --- a/src/coreclr/gc/env/gcenv.os.h +++ b/src/coreclr/gc/env/gcenv.os.h @@ -429,7 +429,8 @@ class GCToOSInterface // available_page_file - The maximum amount of memory the current process can commit, in bytes. // Remarks: // Any parameter can be null. - static void GetMemoryStatus(uint64_t restricted_limit, uint32_t* memory_load, uint64_t* available_physical, uint64_t* available_page_file); + // explicit (unsigned long long) is used to conform to both Linux and MacOS + static void GetMemoryStatus(unsigned long long restricted_limit, uint32_t* memory_load, unsigned long long* available_physical, unsigned long long* available_page_file); // Get size of an OS memory page static size_t GetPageSize(); diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index 768bba0f1001a..a43b92ffe5980 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -25888,7 +25888,7 @@ void gc_heap::get_memory_info (uint32_t* memory_load, uint64_t* available_physical, uint64_t* available_page_file) { - GCToOSInterface::GetMemoryStatus(is_restricted_physical_mem ? total_physical_mem : 0, memory_load, available_physical, available_page_file); + GCToOSInterface::GetMemoryStatus(is_restricted_physical_mem ? total_physical_mem : 0, memory_load, (unsigned long long*) available_physical, (unsigned long long*) available_page_file); } //returns TRUE is an overflow happened. diff --git a/src/coreclr/gc/unix/cgroup.cpp b/src/coreclr/gc/unix/cgroup.cpp index 447e6ee336cc6..136ff3fb19105 100644 --- a/src/coreclr/gc/unix/cgroup.cpp +++ b/src/coreclr/gc/unix/cgroup.cpp @@ -52,9 +52,11 @@ Module Name: #define CGROUP1_MEMORY_STAT_INACTIVE_FIELD "total_inactive_file " #define CGROUP2_MEMORY_STAT_INACTIVE_FIELD "inactive_file " -extern bool ReadMemoryValueFromFile_GC(const char* filename, uint64_t* val); +extern bool ReadMemoryValueFromFile(const char* filename, uint64_t* val); -class CGroup_GC +namespace +{ +class CGroup { // the cgroup version number or 0 to indicate cgroups are not found or not enabled static int s_cgroup_version; @@ -374,7 +376,7 @@ class CGroup_GC if (asprintf(&mem_limit_filename, "%s%s", s_memory_cgroup_path, filename) < 0) return false; - bool result = ReadMemoryValueFromFile_GC(mem_limit_filename, val); + bool result = ReadMemoryValueFromFile(mem_limit_filename, val); free(mem_limit_filename); return result; } @@ -393,7 +395,7 @@ class CGroup_GC size_t usage = 0; - bool result = ReadMemoryValueFromFile_GC(mem_usage_filename, &temp); + bool result = ReadMemoryValueFromFile(mem_usage_filename, &temp); if (result) { if (temp > std::numeric_limits::max()) @@ -453,25 +455,26 @@ class CGroup_GC return foundInactiveFileValue; } }; +} -int CGroup_GC::s_cgroup_version = 0; -char *CGroup_GC::s_memory_cgroup_path = nullptr; +int CGroup::s_cgroup_version = 0; +char *CGroup::s_memory_cgroup_path = nullptr; void InitializeCGroup() { - CGroup_GC::Initialize(); + CGroup::Initialize(); } void CleanupCGroup() { - CGroup_GC::Cleanup(); + CGroup::Cleanup(); } size_t GetRestrictedPhysicalMemoryLimit() { uint64_t physical_memory_limit = 0; - if (!CGroup_GC::GetPhysicalMemoryLimit(&physical_memory_limit)) + if (!CGroup::GetPhysicalMemoryLimit(&physical_memory_limit)) return 0; // If there's no memory limit specified on the container this @@ -526,7 +529,7 @@ bool GetPhysicalMemoryUsed(size_t* val) return false; // Linux uses cgroup usage to trigger oom kills. - if (CGroup_GC::GetPhysicalMemoryUsage(val)) + if (CGroup::GetPhysicalMemoryUsage(val)) return true; // process resident set size. diff --git a/src/coreclr/gc/unix/gcenv.unix.cpp b/src/coreclr/gc/unix/gcenv.unix.cpp index 07078613fd1aa..027018f7e6ad2 100644 --- a/src/coreclr/gc/unix/gcenv.unix.cpp +++ b/src/coreclr/gc/unix/gcenv.unix.cpp @@ -137,32 +137,13 @@ typedef cpuset_t cpu_set_t; #if HAVE_NUMA_H -#include +#include <../../pal/src/numa/numashim.h> #include #include #include #include #include -// List of all functions from the numa library that are used -#define FOR_ALL_NUMA_FUNCTIONS \ - PER_FUNCTION_BLOCK(mbind) \ - PER_FUNCTION_BLOCK(numa_available) \ - PER_FUNCTION_BLOCK(numa_max_node) \ - PER_FUNCTION_BLOCK(numa_node_of_cpu) - -// Declare pointers to all the used numa functions -#define PER_FUNCTION_BLOCK(fn) extern decltype(fn)* fn##_ptr_gc; -FOR_ALL_NUMA_FUNCTIONS -#undef PER_FUNCTION_BLOCK - -// Redefine all calls to numa functions as calls through pointers that are set -// to the functions of libnuma in the initialization. -#define mbind(...) mbind_ptr_gc(__VA_ARGS__) -#define numa_available() numa_available_ptr_gc() -#define numa_max_node() numa_max_node_ptr_gc() -#define numa_node_of_cpu(...) numa_node_of_cpu_ptr_gc(__VA_ARGS__) - #endif // HAVE_NUMA_H #if defined(HOST_ARM) || defined(HOST_ARM64) || defined(HOST_LOONGARCH64) @@ -234,16 +215,12 @@ uint32_t g_pageSizeUnixInl = 0; AffinitySet g_processAffinitySet; // The highest NUMA node available -int g_highestNumaNode_gc = 0; +static int g_highestNumaNode = 0; // Is numa available -bool g_numaAvailable_gc = false; +static bool g_numaAvailable = false; void* g_numaHandle = nullptr; -#if HAVE_NUMA_H -#define PER_FUNCTION_BLOCK(fn) decltype(fn)* fn##_ptr_gc; -FOR_ALL_NUMA_FUNCTIONS -#undef PER_FUNCTION_BLOCK #if defined(__linux__) static bool ShouldOpenLibNuma() @@ -286,7 +263,6 @@ static bool ShouldOpenLibNuma() } #endif // __linux__ -#endif // HAVE_NUMA_H // Initialize data structures for getting and setting thread affinities to processors and // querying NUMA related processor information. @@ -297,8 +273,8 @@ void NUMASupportInitialize() #if HAVE_NUMA_H if (!ShouldOpenLibNuma()) { - g_numaAvailable_gc = false; - g_highestNumaNode_gc = 0; + g_numaAvailable = false; + g_highestNumaNode = 0; return; } @@ -314,8 +290,8 @@ void NUMASupportInitialize() if (g_numaHandle != 0) { #define PER_FUNCTION_BLOCK(fn) \ - fn##_ptr_gc = (decltype(fn)*)dlsym(g_numaHandle, #fn); \ - if (fn##_ptr_gc == NULL) { fprintf(stderr, "Cannot get symbol " #fn " from libnuma\n"); abort(); } + fn##_ptr = (decltype(fn)*)dlsym(g_numaHandle, #fn); \ + if (fn##_ptr == NULL) { fprintf(stderr, "Cannot get symbol " #fn " from libnuma\n"); abort(); } FOR_ALL_NUMA_FUNCTIONS #undef PER_FUNCTION_BLOCK @@ -325,15 +301,15 @@ FOR_ALL_NUMA_FUNCTIONS } else { - g_numaAvailable_gc = true; - g_highestNumaNode_gc = numa_max_node(); + g_numaAvailable = true; + g_highestNumaNode = numa_max_node(); } } #endif // HAVE_NUMA_H - if (!g_numaAvailable_gc) + if (!g_numaAvailable) { // No NUMA - g_highestNumaNode_gc = 0; + g_highestNumaNode = 0; } } @@ -341,7 +317,7 @@ FOR_ALL_NUMA_FUNCTIONS void NUMASupportCleanup() { #if HAVE_NUMA_H - if (g_numaAvailable_gc) + if (g_numaAvailable) { dlclose(g_numaHandle); } @@ -725,11 +701,11 @@ bool GCToOSInterface::VirtualCommit(void* address, size_t size, uint16_t node) bool success = mprotect(address, size, PROT_WRITE | PROT_READ) == 0; #if HAVE_NUMA_H - if (success && g_numaAvailable_gc && (node != NUMA_NODE_UNDEFINED)) + if (success && g_numaAvailable && (node != NUMA_NODE_UNDEFINED)) { - if ((int)node <= g_highestNumaNode_gc) + if ((int)node <= g_highestNumaNode) { - int usedNodeMaskBits = g_highestNumaNode_gc + 1; + int usedNodeMaskBits = g_highestNumaNode + 1; int nodeMaskLength = (usedNodeMaskBits + sizeof(unsigned long) - 1) / sizeof(unsigned long); unsigned long nodeMask[nodeMaskLength]; memset(nodeMask, 0, sizeof(nodeMask)); @@ -825,7 +801,7 @@ bool GCToOSInterface::GetWriteWatch(bool resetState, void* address, size_t size, return false; } -bool ReadMemoryValueFromFile_GC(const char* filename, uint64_t* val) +static bool ReadMemoryValueFromFile(const char* filename, uint64_t* val) { bool result = false; char* line = nullptr; @@ -917,11 +893,11 @@ static size_t GetLogicalProcessorCacheSizeFromOS() { path_to_size_file[index] = (char)(48 + i); - if (ReadMemoryValueFromFile_GC(path_to_size_file, &size)) + if (ReadMemoryValueFromFile(path_to_size_file, &size)) { path_to_level_file[index] = (char)(48 + i); - if (ReadMemoryValueFromFile_GC(path_to_level_file, &level)) + if (ReadMemoryValueFromFile(path_to_level_file, &level)) { UPDATE_CACHE_SIZE_AND_LEVEL(size, level) } @@ -1360,7 +1336,7 @@ uint64_t GetAvailablePageFile() // that is in use (0 indicates no memory use and 100 indicates full memory use). // available_physical - The amount of physical memory currently available, in bytes. // available_page_file - The maximum amount of memory the current process can commit, in bytes. -void GCToOSInterface::GetMemoryStatus(uint64_t restricted_limit, uint32_t* memory_load, uint64_t* available_physical, uint64_t* available_page_file) +void GCToOSInterface::GetMemoryStatus(unsigned long long restricted_limit, uint32_t* memory_load, unsigned long long* available_physical, unsigned long long* available_page_file) { uint64_t available = 0; uint32_t load = 0; @@ -1494,7 +1470,7 @@ uint32_t GCToOSInterface::GetTotalProcessorCount() bool GCToOSInterface::CanEnableGCNumaAware() { - return g_numaAvailable_gc; + return g_numaAvailable; } bool GCToOSInterface::CanEnableGCCPUGroups() From 4c54b0a4b423e949733ed542b504cb4b7cba5a08 Mon Sep 17 00:00:00 2001 From: Manish Godse <61718172+mangod9@users.noreply.github.com> Date: Fri, 14 Oct 2022 20:05:46 -0700 Subject: [PATCH 04/11] trying to remove numa support from PAL --- src/coreclr/gc/unix/gcenv.unix.cpp | 30 +++++++++++++++++++++++++++--- src/coreclr/pal/src/CMakeLists.txt | 1 - src/coreclr/pal/src/init/pal.cpp | 7 ------- src/coreclr/utilcode/util.cpp | 5 +++-- src/coreclr/vm/ceemain.cpp | 3 ++- 5 files changed, 32 insertions(+), 14 deletions(-) diff --git a/src/coreclr/gc/unix/gcenv.unix.cpp b/src/coreclr/gc/unix/gcenv.unix.cpp index 027018f7e6ad2..12e423d2609b6 100644 --- a/src/coreclr/gc/unix/gcenv.unix.cpp +++ b/src/coreclr/gc/unix/gcenv.unix.cpp @@ -137,13 +137,32 @@ typedef cpuset_t cpu_set_t; #if HAVE_NUMA_H -#include <../../pal/src/numa/numashim.h> +#include #include #include #include #include #include +// List of all functions from the numa library that are used +#define FOR_ALL_NUMA_FUNCTIONS \ + PER_FUNCTION_BLOCK(mbind) \ + PER_FUNCTION_BLOCK(numa_available) \ + PER_FUNCTION_BLOCK(numa_max_node) \ + PER_FUNCTION_BLOCK(numa_node_of_cpu) + +// Declare pointers to all the used numa functions +#define PER_FUNCTION_BLOCK(fn) extern decltype(fn)* fn##_ptr; +FOR_ALL_NUMA_FUNCTIONS +#undef PER_FUNCTION_BLOCK + +// Redefine all calls to numa functions as calls through pointers that are set +// to the functions of libnuma in the initialization. +#define mbind(...) mbind_ptr(__VA_ARGS__) +#define numa_available() numa_available_ptr() +#define numa_max_node() numa_max_node_ptr() +#define numa_node_of_cpu(...) numa_node_of_cpu_ptr(__VA_ARGS__) + #endif // HAVE_NUMA_H #if defined(HOST_ARM) || defined(HOST_ARM64) || defined(HOST_LOONGARCH64) @@ -215,12 +234,16 @@ uint32_t g_pageSizeUnixInl = 0; AffinitySet g_processAffinitySet; // The highest NUMA node available -static int g_highestNumaNode = 0; +int g_highestNumaNode = 0; // Is numa available -static bool g_numaAvailable = false; +bool g_numaAvailable = false; void* g_numaHandle = nullptr; +#if HAVE_NUMA_H +#define PER_FUNCTION_BLOCK(fn) decltype(fn)* fn##_ptr; +FOR_ALL_NUMA_FUNCTIONS +#undef PER_FUNCTION_BLOCK #if defined(__linux__) static bool ShouldOpenLibNuma() @@ -263,6 +286,7 @@ static bool ShouldOpenLibNuma() } #endif // __linux__ +#endif // HAVE_NUMA_H // Initialize data structures for getting and setting thread affinities to processors and // querying NUMA related processor information. diff --git a/src/coreclr/pal/src/CMakeLists.txt b/src/coreclr/pal/src/CMakeLists.txt index 1315dac0cb1b9..1088bb1791869 100644 --- a/src/coreclr/pal/src/CMakeLists.txt +++ b/src/coreclr/pal/src/CMakeLists.txt @@ -171,7 +171,6 @@ set(SOURCES misc/sysinfo.cpp misc/time.cpp misc/utils.cpp - numa/numa.cpp objmgr/palobjbase.cpp objmgr/shmobject.cpp objmgr/shmobjectmanager.cpp diff --git a/src/coreclr/pal/src/init/pal.cpp b/src/coreclr/pal/src/init/pal.cpp index 72c0ffb9fa6e8..bddda8ceb023b 100644 --- a/src/coreclr/pal/src/init/pal.cpp +++ b/src/coreclr/pal/src/init/pal.cpp @@ -673,13 +673,6 @@ Initialize( goto CLEANUP15; } - if (FALSE == NUMASupportInitialize()) - { - ERROR("Unable to initialize NUMA support\n"); - palError = ERROR_PALINIT_NUMA; - goto CLEANUP15; - } - TRACE("First-time PAL initialization complete.\n"); init_count++; diff --git a/src/coreclr/utilcode/util.cpp b/src/coreclr/utilcode/util.cpp index 68cee1fc37094..0ef69fdcf73b8 100644 --- a/src/coreclr/utilcode/util.cpp +++ b/src/coreclr/utilcode/util.cpp @@ -513,6 +513,8 @@ BYTE * ClrVirtualAllocWithinRange(const BYTE *pMinAddr, return pResult; } +#ifdef HOST_WINDOWS + //****************************************************************************** // NumaNodeInfo //****************************************************************************** @@ -524,7 +526,6 @@ BYTE * ClrVirtualAllocWithinRange(const BYTE *pMinAddr, return ::VirtualAllocExNuma(hProc, lpAddr, dwSize, allocType, prot, node); } -#ifdef HOST_WINDOWS /*static*/ BOOL NumaNodeInfo::GetNumaProcessorNodeEx(PPROCESSOR_NUMBER proc_no, PUSHORT node_no) { return ::GetNumaProcessorNodeEx(proc_no, node_no); @@ -566,6 +567,7 @@ BYTE * ClrVirtualAllocWithinRange(const BYTE *pMinAddr, #endif // HOST_WINDOWS #endif +#ifdef HOST_WINDOWS /*static*/ BOOL NumaNodeInfo::m_enableGCNumaAware = FALSE; /*static*/ uint16_t NumaNodeInfo::m_nNodes = 0; /*static*/ BOOL NumaNodeInfo::InitNumaNodeInfoAPI() @@ -599,7 +601,6 @@ BYTE * ClrVirtualAllocWithinRange(const BYTE *pMinAddr, m_enableGCNumaAware = InitNumaNodeInfoAPI(); } -#ifdef HOST_WINDOWS //****************************************************************************** // CPUGroupInfo diff --git a/src/coreclr/vm/ceemain.cpp b/src/coreclr/vm/ceemain.cpp index cb6720645c43f..a2040948c31ec 100644 --- a/src/coreclr/vm/ceemain.cpp +++ b/src/coreclr/vm/ceemain.cpp @@ -624,12 +624,13 @@ void EEStartupHelper() #ifdef HOST_WINDOWS InitializeCrashDump(); -#endif // HOST_WINDOWS + // Initialize Numa and CPU group information // Need to do this as early as possible. Used by creating object handle // table inside Ref_Initialization() before GC is initialized. NumaNodeInfo::InitNumaNodeInfo(); +#endif // HOST_WINDOWS #ifndef TARGET_UNIX CPUGroupInfo::EnsureInitialized(); #endif // !TARGET_UNIX From c4ac1e746a0cdb8e15a204e5249a513f20462629 Mon Sep 17 00:00:00 2001 From: Manish Godse <61718172+mangod9@users.noreply.github.com> Date: Fri, 14 Oct 2022 21:52:45 -0700 Subject: [PATCH 05/11] one more rename to resolve MacOS break --- src/coreclr/dlls/mscordac/mscordac_unixexports.src | 3 --- src/coreclr/gc/unix/gcenv.unix.cpp | 2 +- src/coreclr/pal/src/include/pal/palinternal.h | 2 +- src/coreclr/pal/src/misc/cgroup.cpp | 2 +- src/coreclr/pal/src/misc/sysinfo.cpp | 6 +++--- 5 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/coreclr/dlls/mscordac/mscordac_unixexports.src b/src/coreclr/dlls/mscordac/mscordac_unixexports.src index f9f082ebf3a90..004fcad35d09a 100644 --- a/src/coreclr/dlls/mscordac/mscordac_unixexports.src +++ b/src/coreclr/dlls/mscordac/mscordac_unixexports.src @@ -30,7 +30,6 @@ nativeStringResourceTable_mscorrc #PAL_free #PAL_GetLogicalCpuCountFromOS #PAL_GetTotalCpuCount -#PAL_GetNumaProcessorNode #PAL_GetUnwindInfoSize #PAL_get_stdout #PAL_get_stderr @@ -125,7 +124,6 @@ nativeStringResourceTable_mscorrc #GetFullPathNameW #GetLastError #GetModuleFileNameW -#GetNumaHighestNodeNumber #GetProcAddress #GetStdHandle #GetSystemInfo @@ -167,7 +165,6 @@ nativeStringResourceTable_mscorrc #SwitchToThread #TerminateProcess #VirtualAlloc -#VirtualAllocExNuma #VirtualFree #VirtualProtect #VirtualQuery diff --git a/src/coreclr/gc/unix/gcenv.unix.cpp b/src/coreclr/gc/unix/gcenv.unix.cpp index 12e423d2609b6..4be8b789d617b 100644 --- a/src/coreclr/gc/unix/gcenv.unix.cpp +++ b/src/coreclr/gc/unix/gcenv.unix.cpp @@ -825,7 +825,7 @@ bool GCToOSInterface::GetWriteWatch(bool resetState, void* address, size_t size, return false; } -static bool ReadMemoryValueFromFile(const char* filename, uint64_t* val) +bool ReadMemoryValueFromFile(const char* filename, uint64_t* val) { bool result = false; char* line = nullptr; diff --git a/src/coreclr/pal/src/include/pal/palinternal.h b/src/coreclr/pal/src/include/pal/palinternal.h index b5d81aedbfd17..dd4e34c599631 100644 --- a/src/coreclr/pal/src/include/pal/palinternal.h +++ b/src/coreclr/pal/src/include/pal/palinternal.h @@ -647,7 +647,7 @@ typedef enum _TimeConversionConstants } bool -ReadMemoryValueFromFile(const char* filename, uint64_t* val); +PAL_ReadMemoryValueFromFile(const char* filename, uint64_t* val); #ifdef __APPLE__ bool diff --git a/src/coreclr/pal/src/misc/cgroup.cpp b/src/coreclr/pal/src/misc/cgroup.cpp index 6a100d9389c5f..0eae4e8db451d 100644 --- a/src/coreclr/pal/src/misc/cgroup.cpp +++ b/src/coreclr/pal/src/misc/cgroup.cpp @@ -470,7 +470,7 @@ class CGroup static bool ReadMemoryValueFromFile(const char* filename, uint64_t* val) { - return ::ReadMemoryValueFromFile(filename, val); + return ::PAL_ReadMemoryValueFromFile(filename, val); } static bool GetCGroup1CpuLimit(UINT *val) diff --git a/src/coreclr/pal/src/misc/sysinfo.cpp b/src/coreclr/pal/src/misc/sysinfo.cpp index d9ddb02f52166..5380fe5f6d721 100644 --- a/src/coreclr/pal/src/misc/sysinfo.cpp +++ b/src/coreclr/pal/src/misc/sysinfo.cpp @@ -504,7 +504,7 @@ PAL_HasGetCurrentProcessorNumber() } bool -ReadMemoryValueFromFile(const char* filename, uint64_t* val) +PAL_ReadMemoryValueFromFile(const char* filename, uint64_t* val) { bool result = false; char *line = nullptr; @@ -585,11 +585,11 @@ PAL_GetLogicalProcessorCacheSizeFromOS() { path_to_size_file[index] = (char)(48 + i); - if (ReadMemoryValueFromFile(path_to_size_file, &size)) + if (PAL_ReadMemoryValueFromFile(path_to_size_file, &size)) { path_to_level_file[index] = (char)(48 + i); - if (ReadMemoryValueFromFile(path_to_level_file, &level)) + if (PAL_ReadMemoryValueFromFile(path_to_level_file, &level)) { UPDATE_CACHE_SIZE_AND_LEVEL(size, level) } From 64af4b796b9293564aa1db4597688ee45eae1aa2 Mon Sep 17 00:00:00 2001 From: Manish Godse <61718172+mangod9@users.noreply.github.com> Date: Mon, 17 Oct 2022 08:37:02 -0700 Subject: [PATCH 06/11] delete pal numa code. --- src/coreclr/pal/src/numa/numa.cpp | 292 ---------------------------- src/coreclr/pal/src/numa/numashim.h | 36 ---- 2 files changed, 328 deletions(-) delete mode 100644 src/coreclr/pal/src/numa/numa.cpp delete mode 100644 src/coreclr/pal/src/numa/numashim.h diff --git a/src/coreclr/pal/src/numa/numa.cpp b/src/coreclr/pal/src/numa/numa.cpp deleted file mode 100644 index 676775ca63735..0000000000000 --- a/src/coreclr/pal/src/numa/numa.cpp +++ /dev/null @@ -1,292 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*++ - - - -Module Name: - - numa.cpp - -Abstract: - - Implementation of NUMA related APIs - ---*/ - -#include "pal/dbgmsg.h" -SET_DEFAULT_DEBUG_CHANNEL(NUMA); - -#include "pal/palinternal.h" -#include "pal/dbgmsg.h" -#include "pal/numa.h" -#include "pal/corunix.hpp" -#include "pal/thread.hpp" - -#include -#ifdef __FreeBSD__ -#include -#else -#include -#endif - -#include - -#include "numashim.h" - -using namespace CorUnix; - -// The highest NUMA node available -int g_highestNumaNode = 0; -// Is numa available -bool g_numaAvailable = false; - -void* numaHandle = nullptr; - -#if HAVE_NUMA_H -#include -#include -#include - -#define PER_FUNCTION_BLOCK(fn) decltype(fn)* fn##_ptr; -FOR_ALL_NUMA_FUNCTIONS -#undef PER_FUNCTION_BLOCK - -#if defined(__linux__) -static bool ShouldOpenLibNuma() -{ - // This is a simple heuristic to determine if libnuma.so should be opened. There's - // no point in linking and resolving everything in this library if we're running on - // a system that's not NUMA-capable. - int fd = open("/sys/devices/system/node/possible", O_RDONLY | O_CLOEXEC); - - if (fd == -1) - { - // sysfs might not be mounted, not available, or the interface might have - // changed. Return `true' here so NUMASupportInitialize() can try initializing - // NUMA support with libnuma. - return true; - } - - while (true) - { - char buffer[32]; - ssize_t bytesRead = read(fd, buffer, 32); - - if (bytesRead == -1 && errno == EINTR) - { - continue; - } - - close(fd); - - // If an unknown error happened (bytesRead < 0), or the file was empty - // (bytesRead = 0), let libnuma handle this. Otherwise, if there's just - // one NUMA node, don't bother linking in libnuma. - return (bytesRead <= 0) ? true : strncmp(buffer, "0\n", bytesRead) != 0; - } -} -#else -static bool ShouldOpenLibNuma() -{ - return true; -} -#endif // __linux__ - -#endif // HAVE_NUMA_H - -/*++ -Function: - NUMASupportInitialize - -Initialize data structures for getting and setting thread affinities to processors and -querying NUMA related processor information. -On systems with no NUMA support, it behaves as if there was a single NUMA node with -a single group of processors. ---*/ -BOOL -NUMASupportInitialize() -{ -#if HAVE_NUMA_H - if (!ShouldOpenLibNuma()) - { - g_numaAvailable = false; - g_highestNumaNode = 0; - return TRUE; - } - - numaHandle = dlopen("libnuma.so.1", RTLD_LAZY); - if (numaHandle == 0) - { - numaHandle = dlopen("libnuma.so.1.0.0", RTLD_LAZY); - if (numaHandle == 0) - { - numaHandle = dlopen("libnuma.so", RTLD_LAZY); - } - } - if (numaHandle != 0) - { -#define PER_FUNCTION_BLOCK(fn) \ - fn##_ptr = (decltype(fn)*)dlsym(numaHandle, #fn); \ - if (fn##_ptr == NULL) { fprintf(stderr, "Cannot get symbol " #fn " from libnuma\n"); abort(); } -FOR_ALL_NUMA_FUNCTIONS -#undef PER_FUNCTION_BLOCK - - if (numa_available() == -1) - { - dlclose(numaHandle); - } - else - { - g_numaAvailable = true; - g_highestNumaNode = numa_max_node(); - } - } -#endif // HAVE_NUMA_H - if (!g_numaAvailable) - { - // No NUMA - g_highestNumaNode = 0; - } - - return TRUE; -} - -/*++ -Function: - NUMASupportCleanup - -Cleanup of the NUMA support data structures ---*/ -VOID -NUMASupportCleanup() -{ -#if HAVE_NUMA_H - if (g_numaAvailable) - { - dlclose(numaHandle); - } -#endif // HAVE_NUMA_H -} - -/*++ -Function: - GetNumaHighestNodeNumber - -See MSDN doc. ---*/ -BOOL -PALAPI -GetNumaHighestNodeNumber( - OUT PULONG HighestNodeNumber -) -{ - PERF_ENTRY(GetNumaHighestNodeNumber); - ENTRY("GetNumaHighestNodeNumber(HighestNodeNumber=%p)\n", HighestNodeNumber); - *HighestNodeNumber = (ULONG)g_highestNumaNode; - - BOOL success = TRUE; - - LOGEXIT("GetNumaHighestNodeNumber returns BOOL %d\n", success); - PERF_EXIT(GetNumaHighestNodeNumber); - - return success; -} - -/*++ -Function: - PAL_GetNumaProcessorNode - -Abstract - Get NUMA node of a processor - -Parameters: - procNo - number of the processor to get the NUMA node for - node - the resulting NUMA node - -Return value: - TRUE if the function was able to get the NUMA node, FALSE if it has failed. ---*/ -BOOL -PALAPI -PAL_GetNumaProcessorNode(WORD procNo, WORD* node) -{ -#if HAVE_NUMA_H - if (g_numaAvailable) - { - int result = numa_node_of_cpu(procNo); - if (result >= 0) - { - *node = (WORD)result; - return TRUE; - } - } -#endif // HAVE_NUMA_H - - return FALSE; -} - -/*++ -Function: - VirtualAllocExNuma - -See MSDN doc. ---*/ -LPVOID -PALAPI -VirtualAllocExNuma( - IN HANDLE hProcess, - IN OPTIONAL LPVOID lpAddress, - IN SIZE_T dwSize, - IN DWORD flAllocationType, - IN DWORD flProtect, - IN DWORD nndPreferred -) -{ - PERF_ENTRY(VirtualAllocExNuma); - ENTRY("VirtualAllocExNuma(hProcess=%p, lpAddress=%p, dwSize=%u, flAllocationType=%#x, flProtect=%#x, nndPreferred=%d\n", - hProcess, lpAddress, dwSize, flAllocationType, flProtect, nndPreferred); - - LPVOID result = NULL; - - if (hProcess == GetCurrentProcess()) - { - if ((int)nndPreferred <= g_highestNumaNode) - { - result = VirtualAlloc(lpAddress, dwSize, flAllocationType, flProtect); -#if HAVE_NUMA_H - if (result != NULL && g_numaAvailable) - { - int usedNodeMaskBits = g_highestNumaNode + 1; - int nodeMaskLength = (usedNodeMaskBits + sizeof(unsigned long) - 1) / sizeof(unsigned long); - unsigned long nodeMask[nodeMaskLength]; - memset(nodeMask, 0, sizeof(nodeMask)); - - int index = nndPreferred / sizeof(unsigned long); - nodeMask[index] = ((unsigned long)1) << (nndPreferred & (sizeof(unsigned long) - 1)); - - int st = mbind(result, dwSize, MPOL_PREFERRED, nodeMask, usedNodeMaskBits, 0); - - _ASSERTE(st == 0); - // If the mbind fails, we still return the allocated memory since the nndPreferred is just a hint - } -#endif // HAVE_NUMA_H - } - else - { - // The specified node number is larger than the maximum available one - SetLastError(ERROR_INVALID_PARAMETER); - } - } - else - { - // PAL supports allocating from the current process virtual space only - SetLastError(ERROR_INVALID_PARAMETER); - } - - LOGEXIT("VirtualAllocExNuma returns %p\n", result); - PERF_EXIT(VirtualAllocExNuma); - - return result; -} diff --git a/src/coreclr/pal/src/numa/numashim.h b/src/coreclr/pal/src/numa/numashim.h deleted file mode 100644 index c6594b5d06325..0000000000000 --- a/src/coreclr/pal/src/numa/numashim.h +++ /dev/null @@ -1,36 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -// Enable calling numa functions through shims to make it a soft -// runtime dependency. - -#ifndef __NUMASHIM_H__ -#define __NUMASHIM_H__ - -#if HAVE_NUMA_H - -#include -#include - -// List of all functions from the numa library that are used -#define FOR_ALL_NUMA_FUNCTIONS \ - PER_FUNCTION_BLOCK(numa_available) \ - PER_FUNCTION_BLOCK(mbind) \ - PER_FUNCTION_BLOCK(numa_max_node) \ - PER_FUNCTION_BLOCK(numa_node_of_cpu) - -// Declare pointers to all the used numa functions -#define PER_FUNCTION_BLOCK(fn) extern decltype(fn)* fn##_ptr; -FOR_ALL_NUMA_FUNCTIONS -#undef PER_FUNCTION_BLOCK - -// Redefine all calls to numa functions as calls through pointers that are set -// to the functions of libnuma in the initialization. -#define numa_available() numa_available_ptr() -#define mbind(...) mbind_ptr(__VA_ARGS__) -#define numa_max_node() numa_max_node_ptr() -#define numa_node_of_cpu(...) numa_node_of_cpu_ptr(__VA_ARGS__) - -#endif // HAVE_NUMA_H - -#endif // __NUMASHIM_H__ From a585fc3a0df6c4da8eeae64911374dc1855c7f3a Mon Sep 17 00:00:00 2001 From: Manish Godse <61718172+mangod9@users.noreply.github.com> Date: Wed, 19 Oct 2022 10:22:16 -0700 Subject: [PATCH 07/11] Adding missing madvise in GC PAL --- src/coreclr/gc/unix/gcenv.unix.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/coreclr/gc/unix/gcenv.unix.cpp b/src/coreclr/gc/unix/gcenv.unix.cpp index 4be8b789d617b..c35c9f9cdaf2e 100644 --- a/src/coreclr/gc/unix/gcenv.unix.cpp +++ b/src/coreclr/gc/unix/gcenv.unix.cpp @@ -724,6 +724,11 @@ bool GCToOSInterface::VirtualCommit(void* address, size_t size, uint16_t node) { bool success = mprotect(address, size, PROT_WRITE | PROT_READ) == 0; +#ifdef MADV_DODUMP + // Include committed memory in coredump. + madvise(address, size, MADV_DODUMP); +#endif + #if HAVE_NUMA_H if (success && g_numaAvailable && (node != NUMA_NODE_UNDEFINED)) { From 4c53ff85edaef68cf0c77b565a8eb3bc6885f84b Mon Sep 17 00:00:00 2001 From: Manish Godse <61718172+mangod9@users.noreply.github.com> Date: Wed, 19 Oct 2022 11:24:36 -0700 Subject: [PATCH 08/11] added missing MADV_DONTDUMP calls. --- src/coreclr/gc/unix/gcenv.unix.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/coreclr/gc/unix/gcenv.unix.cpp b/src/coreclr/gc/unix/gcenv.unix.cpp index c35c9f9cdaf2e..6f6151c9dd0ac 100644 --- a/src/coreclr/gc/unix/gcenv.unix.cpp +++ b/src/coreclr/gc/unix/gcenv.unix.cpp @@ -661,6 +661,11 @@ static void* VirtualReserveInner(size_t size, size_t alignment, uint32_t flags, pRetVal = pAlignedRetVal; } +#ifdef MADV_DONTDUMP + // Do not include reserved memory in coredump. + madvise(pRetVal, size, MADV_DONTDUMP); +#endif + return pRetVal; } @@ -765,7 +770,14 @@ bool GCToOSInterface::VirtualDecommit(void* address, size_t size) // that much more clear to the operating system that we no // longer need these pages. Also, GC depends on re-committed pages to // be zeroed-out. - return mmap(address, size, PROT_NONE, MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0) != NULL; + void* bRetVal = mmap(address, size, PROT_NONE, MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0); + +#ifdef MADV_DONTDUMP + // Do not include freed memory in coredump. + madvise(address, size, MADV_DONTDUMP); +#endif + + return (bRetVal != NULL); } // Reset virtual memory range. Indicates that data in the memory range specified by address and size is no @@ -796,6 +808,11 @@ bool GCToOSInterface::VirtualReset(void * address, size_t size, bool unlock) #endif } +#ifdef MADV_DONTDUMP + // Do not include reset memory in coredump. + madvise(address, size, MADV_DONTDUMP); +#endif + return (st == 0); } From 6d441b7e8756f57490a443da23830f2a93281fcc Mon Sep 17 00:00:00 2001 From: Manish Godse <61718172+mangod9@users.noreply.github.com> Date: Wed, 19 Oct 2022 17:43:55 -0700 Subject: [PATCH 09/11] CR feedback --- src/coreclr/gc/unix/gcenv.unix.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/coreclr/gc/unix/gcenv.unix.cpp b/src/coreclr/gc/unix/gcenv.unix.cpp index 6f6151c9dd0ac..a27d5e4c0034a 100644 --- a/src/coreclr/gc/unix/gcenv.unix.cpp +++ b/src/coreclr/gc/unix/gcenv.unix.cpp @@ -659,12 +659,11 @@ static void* VirtualReserveInner(size_t size, size_t alignment, uint32_t flags, } pRetVal = pAlignedRetVal; - } - #ifdef MADV_DONTDUMP - // Do not include reserved memory in coredump. - madvise(pRetVal, size, MADV_DONTDUMP); + // Do not include reserved memory in coredump. + madvise(pRetVal, size, MADV_DONTDUMP); #endif + } return pRetVal; } @@ -777,7 +776,7 @@ bool GCToOSInterface::VirtualDecommit(void* address, size_t size) madvise(address, size, MADV_DONTDUMP); #endif - return (bRetVal != NULL); + return (bRetVal != MAP_FAILED); } // Reset virtual memory range. Indicates that data in the memory range specified by address and size is no @@ -809,8 +808,8 @@ bool GCToOSInterface::VirtualReset(void * address, size_t size, bool unlock) } #ifdef MADV_DONTDUMP - // Do not include reset memory in coredump. - madvise(address, size, MADV_DONTDUMP); + // Do not include reset memory in coredump. + madvise(address, size, MADV_DONTDUMP); #endif return (st == 0); From 71a58961901ebd2ad42568c06fc87f98639825eb Mon Sep 17 00:00:00 2001 From: Manish Godse <61718172+mangod9@users.noreply.github.com> Date: Thu, 20 Oct 2022 15:52:25 -0700 Subject: [PATCH 10/11] undo (long long) cast in GetMemoryStatus --- src/coreclr/gc/env/gcenv.os.h | 3 +-- src/coreclr/gc/gc.cpp | 2 +- src/coreclr/gc/unix/gcenv.unix.cpp | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/coreclr/gc/env/gcenv.os.h b/src/coreclr/gc/env/gcenv.os.h index 7b61403849539..c38892b0cadc2 100644 --- a/src/coreclr/gc/env/gcenv.os.h +++ b/src/coreclr/gc/env/gcenv.os.h @@ -429,8 +429,7 @@ class GCToOSInterface // available_page_file - The maximum amount of memory the current process can commit, in bytes. // Remarks: // Any parameter can be null. - // explicit (unsigned long long) is used to conform to both Linux and MacOS - static void GetMemoryStatus(unsigned long long restricted_limit, uint32_t* memory_load, unsigned long long* available_physical, unsigned long long* available_page_file); + static void GetMemoryStatus(uint64_t restricted_limit, uint32_t* memory_load, uint64_t* available_physical, uint64_t* available_page_file); // Get size of an OS memory page static size_t GetPageSize(); diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index bf2d977db060f..ddae524ef0d07 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -25888,7 +25888,7 @@ void gc_heap::get_memory_info (uint32_t* memory_load, uint64_t* available_physical, uint64_t* available_page_file) { - GCToOSInterface::GetMemoryStatus(is_restricted_physical_mem ? total_physical_mem : 0, memory_load, (unsigned long long*) available_physical, (unsigned long long*) available_page_file); + GCToOSInterface::GetMemoryStatus(is_restricted_physical_mem ? total_physical_mem : 0, memory_load, available_physical, available_page_file); } //returns TRUE is an overflow happened. diff --git a/src/coreclr/gc/unix/gcenv.unix.cpp b/src/coreclr/gc/unix/gcenv.unix.cpp index a27d5e4c0034a..5f01276929d47 100644 --- a/src/coreclr/gc/unix/gcenv.unix.cpp +++ b/src/coreclr/gc/unix/gcenv.unix.cpp @@ -1381,7 +1381,7 @@ uint64_t GetAvailablePageFile() // that is in use (0 indicates no memory use and 100 indicates full memory use). // available_physical - The amount of physical memory currently available, in bytes. // available_page_file - The maximum amount of memory the current process can commit, in bytes. -void GCToOSInterface::GetMemoryStatus(unsigned long long restricted_limit, uint32_t* memory_load, unsigned long long* available_physical, unsigned long long* available_page_file) +void GCToOSInterface::GetMemoryStatus(uint64_t restricted_limit, uint32_t* memory_load, uint64_t* available_physical, uint64_t* available_page_file) { uint64_t available = 0; uint32_t load = 0; From b6d04a11675065d3ad164774ce571929a03fc007 Mon Sep 17 00:00:00 2001 From: Manish Godse <61718172+mangod9@users.noreply.github.com> Date: Fri, 21 Oct 2022 14:36:47 -0700 Subject: [PATCH 11/11] only invoke madvise on success. --- src/coreclr/gc/unix/gcenv.unix.cpp | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/coreclr/gc/unix/gcenv.unix.cpp b/src/coreclr/gc/unix/gcenv.unix.cpp index 5f01276929d47..b02f6d29c151b 100644 --- a/src/coreclr/gc/unix/gcenv.unix.cpp +++ b/src/coreclr/gc/unix/gcenv.unix.cpp @@ -729,8 +729,11 @@ bool GCToOSInterface::VirtualCommit(void* address, size_t size, uint16_t node) bool success = mprotect(address, size, PROT_WRITE | PROT_READ) == 0; #ifdef MADV_DODUMP - // Include committed memory in coredump. - madvise(address, size, MADV_DODUMP); + if (success) + { + // Include committed memory in coredump. + madvise(address, size, MADV_DODUMP); + } #endif #if HAVE_NUMA_H @@ -769,14 +772,17 @@ bool GCToOSInterface::VirtualDecommit(void* address, size_t size) // that much more clear to the operating system that we no // longer need these pages. Also, GC depends on re-committed pages to // be zeroed-out. - void* bRetVal = mmap(address, size, PROT_NONE, MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0); + bool bRetVal = mmap(address, size, PROT_NONE, MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0) != MAP_FAILED; #ifdef MADV_DONTDUMP - // Do not include freed memory in coredump. - madvise(address, size, MADV_DONTDUMP); + if (bRetVal) + { + // Do not include freed memory in coredump. + madvise(address, size, MADV_DONTDUMP); + } #endif - return (bRetVal != MAP_FAILED); + return bRetVal; } // Reset virtual memory range. Indicates that data in the memory range specified by address and size is no @@ -808,8 +814,11 @@ bool GCToOSInterface::VirtualReset(void * address, size_t size, bool unlock) } #ifdef MADV_DONTDUMP - // Do not include reset memory in coredump. - madvise(address, size, MADV_DONTDUMP); + if (st == 0) + { + // Do not include reset memory in coredump. + madvise(address, size, MADV_DONTDUMP); + } #endif return (st == 0);