From bf44aaab18b8f8281264b0ccdd47f8a621514aa2 Mon Sep 17 00:00:00 2001 From: Trung Nguyen <57174311+trungnt2910@users.noreply.github.com> Date: Fri, 6 Dec 2024 11:52:57 +1100 Subject: [PATCH] Haiku: Initial CoreCLR support (#109580) * Haiku: Initial CoreCLR support This contains a part of the code required to build CoreCLR and get `paltests` to pass on Haiku. This commit covers `src/coreclr/**`, except the PAL files included in the previous commit. Co-authored-by: Jessica Hamilton * pal: Add back checks for HAVE_CLOCK_THREAD_CPUTIME This was removed in #103441 but required for Haiku builds. --------- Co-authored-by: Jessica Hamilton --- eng/native/tryrun.cmake | 2 ++ eng/native/tryrun_ios_tvos.cmake | 1 + src/coreclr/debug/dbgutil/elfreader.cpp | 16 +++++++-- src/coreclr/debug/dbgutil/elfreader.h | 2 +- src/coreclr/gc/unix/cgroup.cpp | 4 +-- src/coreclr/gc/unix/gcenv.unix.cpp | 26 ++++++++++++--- src/coreclr/gc/unix/numasupport.cpp | 5 ++- src/coreclr/inc/crosscomp.h | 2 ++ src/coreclr/minipal/Unix/doublemapping.cpp | 33 ++++++++++++------- .../nativeaot/Runtime/unix/PalRedhawkUnix.cpp | 9 ++++- .../nativeaot/Runtime/unix/UnixContext.cpp | 20 +++++++++++ .../nativeaot/Runtime/unix/UnixContext.h | 4 +++ .../nativeaot/Runtime/unix/cgroupcpu.cpp | 2 +- src/coreclr/pal/src/config.h.in | 1 + src/coreclr/pal/src/configure.cmake | 16 +++++++++ src/coreclr/utilcode/sstring.cpp | 12 ------- 16 files changed, 120 insertions(+), 35 deletions(-) diff --git a/eng/native/tryrun.cmake b/eng/native/tryrun.cmake index c0fe823dd78f1e..f952d7e034103d 100644 --- a/eng/native/tryrun.cmake +++ b/eng/native/tryrun.cmake @@ -55,6 +55,7 @@ if(DARWIN) set_cache_value(HAVE_CLOCK_MONOTONIC_COARSE_EXITCODE 1) set_cache_value(HAVE_CLOCK_MONOTONIC_EXITCODE 0) set_cache_value(HAVE_CLOCK_REALTIME_EXITCODE 0) + set_cache_value(HAVE_CLOCK_THREAD_CPUTIME_EXITCODE 0) set_cache_value(HAVE_CLOCK_GETTIME_NSEC_NP_EXITCODE 0) set_cache_value(HAVE_FUNCTIONAL_PTHREAD_ROBUST_MUTEXES_EXITCODE 1) set_cache_value(HAVE_MMAP_DEV_ZERO_EXITCODE 1) @@ -79,6 +80,7 @@ elseif(TARGET_ARCH_NAME MATCHES "^(armel|arm|armv6|arm64|loongarch64|riscv64|s39 set_cache_value(HAVE_CLOCK_MONOTONIC_COARSE_EXITCODE 0) set_cache_value(HAVE_CLOCK_MONOTONIC_EXITCODE 0) set_cache_value(HAVE_CLOCK_REALTIME_EXITCODE 0) + set_cache_value(HAVE_CLOCK_THREAD_CPUTIME_EXITCODE 0) set_cache_value(HAVE_MMAP_DEV_ZERO_EXITCODE 0) set_cache_value(HAVE_PROCFS_CTL_EXITCODE 1) set_cache_value(HAVE_PROCFS_STAT_EXITCODE 0) diff --git a/eng/native/tryrun_ios_tvos.cmake b/eng/native/tryrun_ios_tvos.cmake index cb82c7af0677c9..7a260f2af212fe 100644 --- a/eng/native/tryrun_ios_tvos.cmake +++ b/eng/native/tryrun_ios_tvos.cmake @@ -14,6 +14,7 @@ set_cache_value(HAS_POSIX_SEMAPHORES_EXITCODE 1) set_cache_value(HAVE_BROKEN_FIFO_KEVENT_EXITCODE 1) set_cache_value(HAVE_BROKEN_FIFO_SELECT_EXITCODE 1) set_cache_value(HAVE_CLOCK_REALTIME_EXITCODE 0) +set_cache_value(HAVE_CLOCK_THREAD_CPUTIME_EXITCODE 0) set_cache_value(HAVE_CLOCK_GETTIME_NSEC_NP_EXITCODE 0) set_cache_value(HAVE_FUNCTIONAL_PTHREAD_ROBUST_MUTEXES_EXITCODE 1) set_cache_value(HAVE_MMAP_DEV_ZERO_EXITCODE 1) diff --git a/src/coreclr/debug/dbgutil/elfreader.cpp b/src/coreclr/debug/dbgutil/elfreader.cpp index 452ae6669b11dd..c0b1c3cf4dbaaa 100644 --- a/src/coreclr/debug/dbgutil/elfreader.cpp +++ b/src/coreclr/debug/dbgutil/elfreader.cpp @@ -9,12 +9,24 @@ #include #include "elfreader.h" +#ifndef Elf_Ehdr #define Elf_Ehdr ElfW(Ehdr) +#endif +#ifndef Elf_Phdr #define Elf_Phdr ElfW(Phdr) +#endif +#ifndef Elf_Shdr #define Elf_Shdr ElfW(Shdr) +#endif +#ifndef Elf_Nhdr #define Elf_Nhdr ElfW(Nhdr) +#endif +#ifndef Elf_Dyn #define Elf_Dyn ElfW(Dyn) +#endif +#ifndef Elf_Sym #define Elf_Sym ElfW(Sym) +#endif #if TARGET_64BIT #define PRIx PRIx64 @@ -314,7 +326,7 @@ ElfReader::GetStringAtIndex(int index, std::string& result) return true; } -#ifdef HOST_UNIX +#if defined(HOST_UNIX) && !defined(TARGET_HAIKU) // // Enumerate all the ELF info starting from the root program header. This @@ -414,7 +426,7 @@ ElfReader::EnumerateLinkMapEntries(Elf_Dyn* dynamicAddr) return true; } -#endif // HOST_UNIX +#endif // defined(HOST_UNIX) && !defined(TARGET_HAIKU) bool ElfReader::EnumerateProgramHeaders(uint64_t baseAddress, uint64_t* ploadbias, Elf_Dyn** pdynamicAddr) diff --git a/src/coreclr/debug/dbgutil/elfreader.h b/src/coreclr/debug/dbgutil/elfreader.h index 67ddc0d8646530..9a51912bc41e7f 100644 --- a/src/coreclr/debug/dbgutil/elfreader.h +++ b/src/coreclr/debug/dbgutil/elfreader.h @@ -38,7 +38,7 @@ class ElfReader void* m_symbolTableAddr; // DT_SYMTAB GnuHashTable m_hashTable; // gnu hash table info - int32_t* m_buckets; // gnu hash table buckets + int32_t* m_buckets; // gnu hash table buckets void* m_chainsAddress; public: diff --git a/src/coreclr/gc/unix/cgroup.cpp b/src/coreclr/gc/unix/cgroup.cpp index 3be77727363920..8389e8692bf00d 100644 --- a/src/coreclr/gc/unix/cgroup.cpp +++ b/src/coreclr/gc/unix/cgroup.cpp @@ -24,7 +24,7 @@ Module Name: #if defined(__APPLE__) || defined(__FreeBSD__) #include #include -#else +#elif !defined(__HAIKU__) #include #endif #include @@ -55,7 +55,7 @@ Module Name: extern bool ReadMemoryValueFromFile(const char* filename, uint64_t* val); -namespace +namespace { class CGroup { diff --git a/src/coreclr/gc/unix/gcenv.unix.cpp b/src/coreclr/gc/unix/gcenv.unix.cpp index 866d85f60df196..2d972590e48b68 100644 --- a/src/coreclr/gc/unix/gcenv.unix.cpp +++ b/src/coreclr/gc/unix/gcenv.unix.cpp @@ -90,6 +90,10 @@ extern "C" #endif // __APPLE__ +#ifdef __HAIKU__ +#include +#endif // __HAIKU__ + #ifdef __linux__ #include // __NR_membarrier // Ensure __NR_membarrier is defined for portable builds. @@ -572,7 +576,11 @@ static void* VirtualReserveInner(size_t size, size_t alignment, uint32_t flags, } size_t alignedSize = size + (alignment - OS_PAGE_SIZE); - void * pRetVal = mmap(nullptr, alignedSize, PROT_NONE, MAP_ANON | MAP_PRIVATE | hugePagesFlag, -1, 0); + int mmapFlags = MAP_ANON | MAP_PRIVATE | hugePagesFlag; +#ifdef __HAIKU__ + mmapFlags |= MAP_NORESERVE; +#endif + void * pRetVal = mmap(nullptr, alignedSize, PROT_NONE, mmapFlags, -1, 0); if (pRetVal != MAP_FAILED) { @@ -721,7 +729,11 @@ 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. - bool bRetVal = mmap(address, size, PROT_NONE, MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0) != MAP_FAILED; + int mmapFlags = MAP_FIXED | MAP_ANON | MAP_PRIVATE; +#ifdef TARGET_HAIKU + mmapFlags |= MAP_NORESERVE; +#endif + bool bRetVal = mmap(address, size, PROT_NONE, mmapFlags, -1, 0) != MAP_FAILED; #ifdef MADV_DONTDUMP if (bRetVal) @@ -1022,7 +1034,7 @@ static uint64_t GetMemorySizeMultiplier(char units) return 1; } -#ifndef __APPLE__ +#if !defined(__APPLE__) && !defined(__HAIKU__) // Try to read the MemAvailable entry from /proc/meminfo. // Return true if the /proc/meminfo existed, the entry was present and we were able to parse it. static bool ReadMemAvailable(uint64_t* memAvailable) @@ -1055,7 +1067,7 @@ static bool ReadMemAvailable(uint64_t* memAvailable) return foundMemAvailable; } -#endif // __APPLE__ +#endif // !defined(__APPLE__) && !defined(__HAIKU__) // Get size of the largest cache on the processor die // Parameters: @@ -1284,6 +1296,12 @@ uint64_t GetAvailablePhysicalMemory() sysctlbyname("vm.stats.vm.v_free_count", &free_count, &sz, NULL, 0); available = (inactive_count + laundry_count + free_count) * sysconf(_SC_PAGESIZE); +#elif defined(__HAIKU__) + system_info info; + if (get_system_info(&info) == B_OK) + { + available = info.free_memory; + } #else // Linux static volatile bool tryReadMemInfo = true; diff --git a/src/coreclr/gc/unix/numasupport.cpp b/src/coreclr/gc/unix/numasupport.cpp index cec61e59073c21..17e2764f456e2d 100644 --- a/src/coreclr/gc/unix/numasupport.cpp +++ b/src/coreclr/gc/unix/numasupport.cpp @@ -10,9 +10,12 @@ #include #include #include -#include #include +#ifdef TARGET_LINUX +#include +#endif + // The highest NUMA node available int g_highestNumaNode = 0; // Is numa available diff --git a/src/coreclr/inc/crosscomp.h b/src/coreclr/inc/crosscomp.h index 10a196302f35e4..50867accca1ac9 100644 --- a/src/coreclr/inc/crosscomp.h +++ b/src/coreclr/inc/crosscomp.h @@ -720,6 +720,8 @@ typedef struct _T_KNONVOLATILE_CONTEXT_POINTERS { #define DAC_CS_NATIVE_DATA_SIZE 56 #elif defined(__sun) && defined(TARGET_AMD64) #define DAC_CS_NATIVE_DATA_SIZE 48 +#elif defined(TARGET_HAIKU) && defined(TARGET_AMD64) +#define DAC_CS_NATIVE_DATA_SIZE 56 #else #warning #error DAC_CS_NATIVE_DATA_SIZE is not defined for this architecture. This should be same value as PAL_CS_NATIVE_DATA_SIZE (aka sizeof(PAL_CS_NATIVE_DATA)). diff --git a/src/coreclr/minipal/Unix/doublemapping.cpp b/src/coreclr/minipal/Unix/doublemapping.cpp index 67d516fb322a56..ba43e72a0c673c 100644 --- a/src/coreclr/minipal/Unix/doublemapping.cpp +++ b/src/coreclr/minipal/Unix/doublemapping.cpp @@ -48,15 +48,22 @@ bool VMToOSInterface::CreateDoubleMemoryMapper(void** pHandle, size_t *pMaxExecu #ifdef TARGET_FREEBSD int fd = shm_open(SHM_ANON, O_RDWR | O_CREAT, S_IRWXU); -#elif defined(TARGET_SUNOS) // has POSIX implementation - char name[24]; - sprintf(name, "/shm-dotnet-%d", getpid()); - name[sizeof(name) - 1] = '\0'; - shm_unlink(name); - int fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW, 0600); -#else // TARGET_FREEBSD +#elif defined(TARGET_LINUX) int fd = memfd_create("doublemapper", MFD_CLOEXEC); -#endif // TARGET_FREEBSD +#else + int fd = -1; +#endif + + // POSIX fallback + if (fd == -1) + { + char name[24]; + sprintf(name, "/shm-dotnet-%d", getpid()); + name[sizeof(name) - 1] = '\0'; + shm_unlink(name); + fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW, 0600); + shm_unlink(name); + } if (fd == -1) { @@ -135,10 +142,14 @@ void* VMToOSInterface::ReserveDoubleMappedMemory(void *mapperHandle, size_t offs void* result = PAL_VirtualReserveFromExecutableMemoryAllocatorWithinRange(rangeStart, rangeEnd, size, 0 /* fStoreAllocationInfo */); #ifndef TARGET_OSX + int mmapFlags = MAP_SHARED; +#ifdef TARGET_HAIKU + mmapFlags |= MAP_NORESERVE; +#endif // TARGET_HAIKU if (result != NULL) { // Map the shared memory over the range reserved from the executable memory allocator. - result = mmap(result, size, PROT_NONE, MAP_SHARED | MAP_FIXED, fd, offset); + result = mmap(result, size, PROT_NONE, mmapFlags | MAP_FIXED, fd, offset); if (result == MAP_FAILED) { assert(false); @@ -154,7 +165,7 @@ void* VMToOSInterface::ReserveDoubleMappedMemory(void *mapperHandle, size_t offs } #ifndef TARGET_OSX - result = mmap(NULL, size, PROT_NONE, MAP_SHARED, fd, offset); + result = mmap(NULL, size, PROT_NONE, mmapFlags, fd, offset); #else int mmapFlags = MAP_ANON | MAP_PRIVATE; if (IsMapJitFlagNeeded()) @@ -162,7 +173,7 @@ void* VMToOSInterface::ReserveDoubleMappedMemory(void *mapperHandle, size_t offs mmapFlags |= MAP_JIT; } result = mmap(NULL, size, PROT_NONE, mmapFlags, -1, 0); -#endif +#endif if (result == MAP_FAILED) { assert(false); diff --git a/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp b/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp index 5cacb58e86970c..ffdaa0d1fb7c1a 100644 --- a/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -44,6 +43,10 @@ #include #include +#ifdef TARGET_LINUX +#include +#endif + #if HAVE_PTHREAD_GETTHREADID_NP #include #endif @@ -60,6 +63,10 @@ #include #endif +#ifdef TARGET_HAIKU +#include +#endif + using std::nullptr_t; #define PalRaiseFailFastException RaiseFailFastException diff --git a/src/coreclr/nativeaot/Runtime/unix/UnixContext.cpp b/src/coreclr/nativeaot/Runtime/unix/UnixContext.cpp index e084fb35e391f3..a4a9e599af1276 100644 --- a/src/coreclr/nativeaot/Runtime/unix/UnixContext.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/UnixContext.cpp @@ -76,6 +76,26 @@ #endif // HOST_ARM64 +#elif defined(__HAIKU__) + +#define MCREG_Rip(mc) ((mc).rip) +#define MCREG_Rsp(mc) ((mc).rsp) +#define MCREG_Rax(mc) ((mc).rax) +#define MCREG_Rbx(mc) ((mc).rbx) +#define MCREG_Rcx(mc) ((mc).rcx) +#define MCREG_Rdx(mc) ((mc).rdx) +#define MCREG_Rsi(mc) ((mc).rsi) +#define MCREG_Rdi(mc) ((mc).rdi) +#define MCREG_Rbp(mc) ((mc).rbp) +#define MCREG_R8(mc) ((mc).r8) +#define MCREG_R9(mc) ((mc).r9) +#define MCREG_R10(mc) ((mc).r10) +#define MCREG_R11(mc) ((mc).r11) +#define MCREG_R12(mc) ((mc).r12) +#define MCREG_R13(mc) ((mc).r13) +#define MCREG_R14(mc) ((mc).r14) +#define MCREG_R15(mc) ((mc).r15) + #else #if HAVE___GREGSET_T diff --git a/src/coreclr/nativeaot/Runtime/unix/UnixContext.h b/src/coreclr/nativeaot/Runtime/unix/UnixContext.h index 662b697715da0a..c12fae7d033550 100644 --- a/src/coreclr/nativeaot/Runtime/unix/UnixContext.h +++ b/src/coreclr/nativeaot/Runtime/unix/UnixContext.h @@ -4,7 +4,11 @@ #ifndef __UNIX_CONTEXT_H__ #define __UNIX_CONTEXT_H__ +#if HAVE_UCONTEXT_H #include +#else +#include +#endif // Convert Unix native context to PAL_LIMITED_CONTEXT void NativeContextToPalContext(const void* context, PAL_LIMITED_CONTEXT* palContext); diff --git a/src/coreclr/nativeaot/Runtime/unix/cgroupcpu.cpp b/src/coreclr/nativeaot/Runtime/unix/cgroupcpu.cpp index 9b30d817828302..7543c0aa2a53b9 100644 --- a/src/coreclr/nativeaot/Runtime/unix/cgroupcpu.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/cgroupcpu.cpp @@ -25,7 +25,7 @@ Module Name: #if defined(__APPLE__) || defined(__FreeBSD__) #include #include -#else +#elif !defined(__HAIKU__) #include #endif #include diff --git a/src/coreclr/pal/src/config.h.in b/src/coreclr/pal/src/config.h.in index 18ef4c2f93217e..a3c83373d6d955 100644 --- a/src/coreclr/pal/src/config.h.in +++ b/src/coreclr/pal/src/config.h.in @@ -92,6 +92,7 @@ #cmakedefine01 HAVE_CLOCK_MONOTONIC #cmakedefine01 HAVE_CLOCK_MONOTONIC_COARSE #cmakedefine01 HAVE_CLOCK_GETTIME_NSEC_NP +#cmakedefine01 HAVE_CLOCK_THREAD_CPUTIME #cmakedefine01 HAVE_PTHREAD_CONDATTR_SETCLOCK #cmakedefine01 MMAP_ANON_IGNORES_PROTECTION #cmakedefine01 ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS diff --git a/src/coreclr/pal/src/configure.cmake b/src/coreclr/pal/src/configure.cmake index 79140466b97d59..8dd44c550ba5db 100644 --- a/src/coreclr/pal/src/configure.cmake +++ b/src/coreclr/pal/src/configure.cmake @@ -401,6 +401,22 @@ int main() exit((ret == 0) ? 1 : 0); }" HAVE_CLOCK_GETTIME_NSEC_NP) +set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_RT_LIBS}) +check_cxx_source_runs(" +#include +#include +#include + +int main() +{ + int ret; + struct timespec ts; + ret = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts); + + exit(ret); +}" HAVE_CLOCK_THREAD_CPUTIME) +set(CMAKE_REQUIRED_LIBRARIES) + check_cxx_source_runs(" #include #include diff --git a/src/coreclr/utilcode/sstring.cpp b/src/coreclr/utilcode/sstring.cpp index 2fb454c369cab4..d500d48bbeb4f0 100644 --- a/src/coreclr/utilcode/sstring.cpp +++ b/src/coreclr/utilcode/sstring.cpp @@ -1713,18 +1713,6 @@ void SString::Printf(const CHAR *format, ...) va_end(args); } -#ifndef EBADF -#define EBADF 9 -#endif - -#ifndef ENOMEM -#define ENOMEM 12 -#endif - -#ifndef ERANGE -#define ERANGE 34 -#endif - #if defined(_MSC_VER) #undef va_copy #define va_copy(dest,src) (dest = src)