From c6d4bb75724f42738c37c691bef3530403a236d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Thu, 9 Dec 2021 16:45:31 +0900 Subject: [PATCH] Add System.Native APIs needed by NativeAOT Porting files over from runtimelab branch - no changes to what was there. --- src/native/libs/Common/pal_config.h.in | 2 + src/native/libs/System.Native/CMakeLists.txt | 7 ++ src/native/libs/System.Native/entrypoints.c | 8 +++ .../libs/System.Native/pal_dynamicload.c | 52 ++++++++++++++ .../libs/System.Native/pal_dynamicload.h | 13 ++++ src/native/libs/System.Native/pal_threading.c | 71 +++++++++++++++++++ src/native/libs/System.Native/pal_threading.h | 8 +++ src/native/libs/configure.cmake | 9 +++ 8 files changed, 170 insertions(+) create mode 100644 src/native/libs/System.Native/pal_dynamicload.c create mode 100644 src/native/libs/System.Native/pal_dynamicload.h diff --git a/src/native/libs/Common/pal_config.h.in b/src/native/libs/Common/pal_config.h.in index 00b774b87341b4..431071204dfb8e 100644 --- a/src/native/libs/Common/pal_config.h.in +++ b/src/native/libs/Common/pal_config.h.in @@ -45,7 +45,9 @@ #cmakedefine01 HAVE_TIOCGWINSZ #cmakedefine01 HAVE_SCHED_GETAFFINITY #cmakedefine01 HAVE_SCHED_SETAFFINITY +#cmakedefine01 HAVE_SCHED_GETCPU #cmakedefine01 HAVE_PTHREAD_SETCANCELSTATE +#cmakedefine01 HAVE_GNU_LIBNAMES_H #cmakedefine01 HAVE_ARC4RANDOM_BUF #cmakedefine01 KEVENT_HAS_VOID_UDATA #cmakedefine01 HAVE_FDS_BITS diff --git a/src/native/libs/System.Native/CMakeLists.txt b/src/native/libs/System.Native/CMakeLists.txt index 8fea908f798014..60780bf85c7089 100644 --- a/src/native/libs/System.Native/CMakeLists.txt +++ b/src/native/libs/System.Native/CMakeLists.txt @@ -4,11 +4,18 @@ if (NOT CLR_CMAKE_TARGET_MACCATALYST AND NOT CLR_CMAKE_TARGET_IOS AND NOT CLR_CM add_definitions(-DHAS_CONSOLE_SIGNALS) endif () +if (CLR_CMAKE_HOST_ALPINE_LINUX) + # Fix up the thread stack size for MUSL to more reasonable size. + # TODO: https://github.com/dotnet/runtimelab/issues/791 + add_definitions(-DENSURE_PRIMARY_STACK_SIZE) +endif () + if (CLR_CMAKE_TARGET_OSX) add_definitions(-D_DARWIN_C_SOURCE) endif () set(NATIVE_SOURCES + pal_dynamicload.c pal_errno.c pal_interfaceaddresses.c pal_io.c diff --git a/src/native/libs/System.Native/entrypoints.c b/src/native/libs/System.Native/entrypoints.c index ab227685b5a898..cefbd045d8c4f2 100644 --- a/src/native/libs/System.Native/entrypoints.c +++ b/src/native/libs/System.Native/entrypoints.c @@ -7,6 +7,7 @@ #include "pal_autoreleasepool.h" #include "pal_console.h" #include "pal_datetime.h" +#include "pal_dynamicload.h" #include "pal_environment.h" #include "pal_errno.h" #include "pal_interfaceaddresses.h" @@ -235,6 +236,12 @@ static const Entry s_sysNative[] = DllImportEntry(SystemNative_LowLevelMonitor_Wait) DllImportEntry(SystemNative_LowLevelMonitor_TimedWait) DllImportEntry(SystemNative_LowLevelMonitor_Signal_Release) + DllImportEntry(SystemNative_LoadLibrary) + DllImportEntry(SystemNative_GetProcAddress) + DllImportEntry(SystemNative_FreeLibrary) + DllImportEntry(SystemNative_SchedGetCpu) + DllImportEntry(SystemNative_Exit) + DllImportEntry(SystemNative_Abort) DllImportEntry(SystemNative_UTimensat) DllImportEntry(SystemNative_GetTimestamp) DllImportEntry(SystemNative_GetCpuUtilization) @@ -253,6 +260,7 @@ static const Entry s_sysNative[] = DllImportEntry(SystemNative_PWrite) DllImportEntry(SystemNative_PReadV) DllImportEntry(SystemNative_PWriteV) + DllImportEntry(SystemNative_RuntimeThread_CreateThread) DllImportEntry(SystemNative_EnablePosixSignalHandling) DllImportEntry(SystemNative_DisablePosixSignalHandling) DllImportEntry(SystemNative_HandleNonCanceledPosixSignal) diff --git a/src/native/libs/System.Native/pal_dynamicload.c b/src/native/libs/System.Native/pal_dynamicload.c new file mode 100644 index 00000000000000..20ac55859eb1ad --- /dev/null +++ b/src/native/libs/System.Native/pal_dynamicload.c @@ -0,0 +1,52 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "pal_config.h" +#include "pal_dynamicload.h" + +#include +#include + +#if HAVE_GNU_LIBNAMES_H +#include +#endif + +void* SystemNative_LoadLibrary(const char* filename) +{ + // Check whether we have been requested to load 'libc'. If that's the case, then: + // * For Linux, use the full name of the library that is defined in by the + // LIBC_SO constant. The problem is that calling dlopen("libc.so") will fail for libc even + // though it works for other libraries. The reason is that libc.so is just linker script + // (i.e. a test file). + // As a result, we have to use the full name (i.e. lib.so.6) that is defined by LIBC_SO. + // * For macOS, use constant value absolute path "/usr/lib/libc.dylib". + // * For FreeBSD, use constant value "libc.so.7". + // * For rest of Unices, use constant value "libc.so". + if (strcmp(filename, "libc") == 0) + { +#if defined(__APPLE__) + filename = "/usr/lib/libc.dylib"; +#elif defined(__FreeBSD__) + filename = "libc.so.7"; +#elif defined(LIBC_SO) + filename = LIBC_SO; +#else + filename = "libc.so"; +#endif + } + + return dlopen(filename, RTLD_LAZY); +} + +void* SystemNative_GetProcAddress(void* handle, const char* symbol) +{ + // We're not trying to disambiguate between "symbol was not found" and "symbol found, but + // the value is null". .NET does not define a behavior for DllImports of null entrypoints, + // so we might as well take the "not found" path on the managed side. + return dlsym(handle, symbol); +} + +void SystemNative_FreeLibrary(void* handle) +{ + dlclose(handle); +} diff --git a/src/native/libs/System.Native/pal_dynamicload.h b/src/native/libs/System.Native/pal_dynamicload.h new file mode 100644 index 00000000000000..857f45def88eb3 --- /dev/null +++ b/src/native/libs/System.Native/pal_dynamicload.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#pragma once + +#include "pal_compiler.h" +#include "pal_types.h" + +PALEXPORT void* SystemNative_LoadLibrary(const char* filename); + +PALEXPORT void* SystemNative_GetProcAddress(void* handle, const char* symbol); + +PALEXPORT void SystemNative_FreeLibrary(void* handle); diff --git a/src/native/libs/System.Native/pal_threading.c b/src/native/libs/System.Native/pal_threading.c index 6f69d1056b8f1f..2aa6790d4bcf4c 100644 --- a/src/native/libs/System.Native/pal_threading.c +++ b/src/native/libs/System.Native/pal_threading.c @@ -12,6 +12,9 @@ #include #include #include +#if HAVE_SCHED_GETCPU +#include +#endif #if defined(TARGET_OSX) // So we can use the declaration of pthread_cond_timedwait_relative_np @@ -214,3 +217,71 @@ void SystemNative_LowLevelMonitor_Signal_Release(LowLevelMonitor* monitor) (void)error; // unused in release build } + +int32_t SystemNative_RuntimeThread_CreateThread(uintptr_t stackSize, void *(*startAddress)(void*), void *parameter) +{ + bool result = false; + pthread_attr_t attrs; + + int error = pthread_attr_init(&attrs); + if (error != 0) + { + // Do not call pthread_attr_destroy + return false; + } + + error = pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED); + assert(error == 0); + +#ifdef ENSURE_PRIMARY_STACK_SIZE + // TODO: https://github.com/dotnet/runtimelab/issues/791 + if (stackSize == 0) + { + stackSize = 1536 * 1024; + } +#endif + + if (stackSize > 0) + { + if (stackSize < PTHREAD_STACK_MIN) + { + stackSize = PTHREAD_STACK_MIN; + } + + error = pthread_attr_setstacksize(&attrs, stackSize); + if (error != 0) goto CreateThreadExit; + } + + pthread_t threadId; + error = pthread_create(&threadId, &attrs, startAddress, parameter); + if (error != 0) goto CreateThreadExit; + + result = true; + +CreateThreadExit: + error = pthread_attr_destroy(&attrs); + assert(error == 0); + + return result; +} + +int32_t SystemNative_SchedGetCpu() +{ +#if HAVE_SCHED_GETCPU + return sched_getcpu(); +#else + return -1; +#endif +} + +__attribute__((noreturn)) +void SystemNative_Exit(int32_t exitCode) +{ + exit(exitCode); +} + +__attribute__((noreturn)) +void SystemNative_Abort() +{ + abort(); +} diff --git a/src/native/libs/System.Native/pal_threading.h b/src/native/libs/System.Native/pal_threading.h index 599d678fc98666..ab59c7ddb83a39 100644 --- a/src/native/libs/System.Native/pal_threading.h +++ b/src/native/libs/System.Native/pal_threading.h @@ -21,3 +21,11 @@ PALEXPORT void SystemNative_LowLevelMonitor_Wait(LowLevelMonitor* monitor); PALEXPORT int32_t SystemNative_LowLevelMonitor_TimedWait(LowLevelMonitor *monitor, int32_t timeoutMilliseconds); PALEXPORT void SystemNative_LowLevelMonitor_Signal_Release(LowLevelMonitor* monitor); + +PALEXPORT int32_t SystemNative_RuntimeThread_CreateThread(uintptr_t stackSize, void *(*startAddress)(void*), void *parameter); + +PALEXPORT int32_t SystemNative_SchedGetCpu(void); + +PALEXPORT __attribute__((noreturn)) void SystemNative_Exit(int32_t exitCode); + +PALEXPORT __attribute__((noreturn)) void SystemNative_Abort(void); diff --git a/src/native/libs/configure.cmake b/src/native/libs/configure.cmake index 57708aff84b651..8eadf95602021f 100644 --- a/src/native/libs/configure.cmake +++ b/src/native/libs/configure.cmake @@ -261,11 +261,20 @@ check_symbol_exists( "sched.h" HAVE_SCHED_SETAFFINITY) +check_symbol_exists( + sched_getcpu + "sched.h" + HAVE_SCHED_GETCPU) + check_symbol_exists( pthread_setcancelstate "pthread.h" HAVE_PTHREAD_SETCANCELSTATE) +check_include_files( + gnu/lib-names.h + HAVE_GNU_LIBNAMES_H) + check_symbol_exists( arc4random_buf "stdlib.h"