statically linking GC PAL on linux (#76985)
authorManish Godse <61718172+mangod9@users.noreply.github.com>
Tue, 25 Oct 2022 20:42:49 +0000 (13:42 -0700)
committerGitHub <noreply@github.com>
Tue, 25 Oct 2022 20:42:49 +0000 (13:42 -0700)
* statically linking GC PAL

The GC PAL will be used for both coreclr and standalone GC on linux

* fixing arm64 and nativeaot build breaks

* macos build break and reducing renaming.

* trying to remove numa support from PAL

* one more rename to resolve MacOS break

* delete pal numa code.

* Adding missing madvise in GC PAL

* added missing MADV_DONTDUMP calls.

* CR feedback

* undo (long long) cast in GetMemoryStatus

* only invoke madvise on success.

15 files changed:
src/coreclr/dlls/mscordac/mscordac_unixexports.src
src/coreclr/dlls/mscoree/coreclr/CMakeLists.txt
src/coreclr/gc/CMakeLists.txt
src/coreclr/gc/unix/cgroup.cpp
src/coreclr/gc/unix/gcenv.unix.cpp
src/coreclr/pal/src/CMakeLists.txt
src/coreclr/pal/src/include/pal/palinternal.h
src/coreclr/pal/src/init/pal.cpp
src/coreclr/pal/src/misc/cgroup.cpp
src/coreclr/pal/src/misc/sysinfo.cpp
src/coreclr/pal/src/numa/numa.cpp [deleted file]
src/coreclr/pal/src/numa/numashim.h [deleted file]
src/coreclr/utilcode/util.cpp
src/coreclr/vm/CMakeLists.txt
src/coreclr/vm/ceemain.cpp

index ab03a84..a6ffa08 100644 (file)
@@ -30,7 +30,6 @@ nativeStringResourceTable_mscorrc
 #PAL_free
 #PAL_GetLogicalCpuCountFromOS
 #PAL_GetTotalCpuCount
-#PAL_GetNumaProcessorNode
 #PAL_GetUnwindInfoSize
 #PAL_get_stdout
 #PAL_get_stderr
@@ -122,7 +121,6 @@ nativeStringResourceTable_mscorrc
 #GetFullPathNameW
 #GetLastError
 #GetModuleFileNameW
-#GetNumaHighestNodeNumber
 #GetProcAddress
 #GetStdHandle
 #GetSystemInfo
@@ -163,7 +161,6 @@ nativeStringResourceTable_mscorrc
 #SwitchToThread
 #TerminateProcess
 #VirtualAlloc
-#VirtualAllocExNuma
 #VirtualFree
 #VirtualProtect
 #VirtualQuery
index 688629d..6e22bd9 100644 (file)
@@ -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)
index 9052c4a..4441c41 100644 (file)
@@ -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})
index ad2a412..136ff3f 100644 (file)
@@ -54,6 +54,8 @@ Abstract:
 
 extern bool ReadMemoryValueFromFile(const char* filename, uint64_t* val);
 
+namespace 
+{
 class CGroup
 {
     // the cgroup version number or 0 to indicate cgroups are not found or not enabled
@@ -453,6 +455,7 @@ private:
         return foundInactiveFileValue;
     }
 };
+}
 
 int CGroup::s_cgroup_version = 0;
 char *CGroup::s_memory_cgroup_path = nullptr;
index 8037fa0..b02f6d2 100644 (file)
@@ -659,6 +659,10 @@ 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;
@@ -724,6 +728,14 @@ bool GCToOSInterface::VirtualCommit(void* address, size_t size, uint16_t node)
 {
     bool success = mprotect(address, size, PROT_WRITE | PROT_READ) == 0;
 
+#ifdef MADV_DODUMP
+    if (success)
+    {
+        // Include committed memory in coredump.
+        madvise(address, size, MADV_DODUMP);
+    }
+#endif
+
 #if HAVE_NUMA_H
     if (success && g_numaAvailable && (node != NUMA_NODE_UNDEFINED))
     {
@@ -760,7 +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.
-    return mmap(address, size, PROT_NONE, MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0) != NULL;
+    bool bRetVal = mmap(address, size, PROT_NONE, MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0) != MAP_FAILED;
+
+#ifdef MADV_DONTDUMP
+    if (bRetVal)
+    {
+        // Do not include freed memory in coredump.
+        madvise(address, size, MADV_DONTDUMP);
+    }
+#endif
+
+    return  bRetVal;
 }
 
 // Reset virtual memory range. Indicates that data in the memory range specified by address and size is no
@@ -791,6 +813,14 @@ bool GCToOSInterface::VirtualReset(void * address, size_t size, bool unlock)
 #endif
     }
 
+#ifdef MADV_DONTDUMP
+    if (st == 0)
+    {
+        // Do not include reset memory in coredump.
+        madvise(address, size, MADV_DONTDUMP);
+    }
+#endif
+
     return (st == 0);
 }
 
index 1315dac..1088bb1 100644 (file)
@@ -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
index 89923bf..cbe75eb 100644 (file)
@@ -648,7 +648,7 @@ typedef enum _TimeConversionConstants
 }
 
 bool
-ReadMemoryValueFromFile(const char* filename, uint64_t* val);
+PAL_ReadMemoryValueFromFile(const char* filename, uint64_t* val);
 
 #ifdef __APPLE__
 bool
index 72c0ffb..bddda8c 100644 (file)
@@ -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++;
 
index 6a100d9..0eae4e8 100644 (file)
@@ -470,7 +470,7 @@ private:
 
     static bool ReadMemoryValueFromFile(const char* filename, uint64_t* val)
     {
-        return ::ReadMemoryValueFromFile(filename, val);
+        return ::PAL_ReadMemoryValueFromFile(filename, val);
     }
 
     static bool GetCGroup1CpuLimit(UINT *val)
index 102a012..f9731f4 100644 (file)
@@ -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)
                 }
diff --git a/src/coreclr/pal/src/numa/numa.cpp b/src/coreclr/pal/src/numa/numa.cpp
deleted file mode 100644 (file)
index 676775c..0000000
+++ /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 <dlfcn.h>
-#ifdef __FreeBSD__
-#include <stdlib.h>
-#else
-#include <alloca.h>
-#endif
-
-#include <algorithm>
-
-#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 <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#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 (file)
index c6594b5..0000000
+++ /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 <numa.h>
-#include <numaif.h>
-
-// 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__
index 1639960..a331cdd 100644 (file)
@@ -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
index 153fe06..8ac8280 100644 (file)
@@ -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
@@ -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
index cb67206..a204094 100644 (file)
@@ -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