diff --git a/src/native/libs/System.IO.Compression.Native/CMakeLists.txt b/src/native/libs/System.IO.Compression.Native/CMakeLists.txt index c105ffe5b0c586..d3a1132b5faf6c 100644 --- a/src/native/libs/System.IO.Compression.Native/CMakeLists.txt +++ b/src/native/libs/System.IO.Compression.Native/CMakeLists.txt @@ -251,6 +251,10 @@ else () endif () +if (TARGET System.IO.Compression.Native) + target_link_libraries(System.IO.Compression.Native PRIVATE minipal) +endif() + install (TARGETS System.IO.Compression.Native-Static DESTINATION ${STATIC_LIB_DESTINATION} COMPONENT libs) if(CLR_CMAKE_HOST_ANDROID OR CLR_CMAKE_HOST_IOS OR CLR_CMAKE_HOST_TVOS OR CLR_CMAKE_HOST_MACCATALYST OR CLR_CMAKE_TARGET_BROWSER OR CLR_CMAKE_TARGET_WASI) diff --git a/src/native/minipal/CMakeLists.txt b/src/native/minipal/CMakeLists.txt index bd219f66c97e2f..53960991f53080 100644 --- a/src/native/minipal/CMakeLists.txt +++ b/src/native/minipal/CMakeLists.txt @@ -5,8 +5,11 @@ include(configure.cmake) set(SOURCES cpufeatures.c descriptorlimit.c + entrypoints.c + getexepath.c memorybarrierprocesswide.c mutex.c + ospagesize.c guid.c random.c debugger.c @@ -18,19 +21,10 @@ set(SOURCES log.c ) -# ospagesize is provided inline in the header on Windows and WASM; the .c file -# only contains the POSIX implementation. Including it on those platforms would -# produce a redefinition error (mono builds for wasi/browser set HOST_WASM but -# not CLR_CMAKE_TARGET_ARCH_WASM, so check both). In cross-component builds -# (e.g. host=x64, target=wasm) the code runs on the host, so we still need the -# POSIX implementation; only skip when the HOST is actually wasm. -if(NOT WIN32 AND NOT HOST_WASM AND NOT (CLR_CMAKE_TARGET_ARCH_WASM AND NOT CLR_CROSS_COMPONENTS_BUILD)) - list(APPEND SOURCES ospagesize.c) -endif() - if(CLR_CMAKE_HOST_UNIX) list(APPEND SOURCES cpucount.c + cpuid.c thread.c ) endif() diff --git a/src/native/minipal/configure.cmake b/src/native/minipal/configure.cmake index 75ab81d852a339..00be7c33163c69 100644 --- a/src/native/minipal/configure.cmake +++ b/src/native/minipal/configure.cmake @@ -12,6 +12,7 @@ check_function_exists(fsync HAVE_FSYNC) check_symbol_exists(elf_aux_info "sys/auxv.h" HAVE_ELF_AUX_INFO) check_symbol_exists(arc4random_buf "stdlib.h" HAVE_ARC4RANDOM_BUF) +check_symbol_exists(getauxval "sys/auxv.h" HAVE_GETAUXVAL) check_symbol_exists(getrandom "sys/random.h" HAVE_GETRANDOM) check_symbol_exists(getentropy "unistd.h" HAVE_GETENTROPY) check_symbol_exists(O_CLOEXEC fcntl.h HAVE_O_CLOEXEC) diff --git a/src/native/minipal/cpuid.c b/src/native/minipal/cpuid.c new file mode 100644 index 00000000000000..49ad45de7e38da --- /dev/null +++ b/src/native/minipal/cpuid.c @@ -0,0 +1,18 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "cpuid.h" + +#if defined(HOST_X86) || defined(HOST_AMD64) +#if defined(HOST_UNIX) + +#if !__has_builtin(__cpuid) +extern void __cpuid(int cpuInfo[4], int function_id); +#endif + +#if !__has_builtin(__cpuidex) +extern void __cpuidex(int cpuInfo[4], int function_id, int subFunction_id); +#endif + +#endif // HOST_UNIX +#endif // defined(HOST_X86) || defined(HOST_AMD64) diff --git a/src/native/minipal/cpuid.h b/src/native/minipal/cpuid.h index 8020775dd6df33..4e83b79fe506b1 100644 --- a/src/native/minipal/cpuid.h +++ b/src/native/minipal/cpuid.h @@ -16,13 +16,19 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + // MSVC directly defines intrinsics for __cpuid and __cpuidex matching the below signatures // We define matching signatures for use on Unix platforms. // // IMPORTANT: Unlike MSVC, Unix does not explicitly zero ECX for __cpuid #if !__has_builtin(__cpuid) -static void __cpuid(int cpuInfo[4], int function_id) +inline void __cpuid(int cpuInfo[4], int function_id) __asm("minipal_cpuid"); + +inline void __cpuid(int cpuInfo[4], int function_id) { // Based on the Clang implementation provided in cpuid.h: // https://github.com/llvm/llvm-project/blob/main/clang/lib/Headers/cpuid.h @@ -37,7 +43,9 @@ void __cpuid(int cpuInfo[4], int function_id); #endif #if !__has_builtin(__cpuidex) -static void __cpuidex(int cpuInfo[4], int function_id, int subFunction_id) +inline void __cpuidex(int cpuInfo[4], int function_id, int subFunction_id) __asm("minipal_cpuidex"); + +inline void __cpuidex(int cpuInfo[4], int function_id, int subFunction_id) { // Based on the Clang implementation provided in cpuid.h: // https://github.com/llvm/llvm-project/blob/main/clang/lib/Headers/cpuid.h @@ -51,6 +59,10 @@ static void __cpuidex(int cpuInfo[4], int function_id, int subFunction_id) void __cpuidex(int cpuInfo[4], int function_id, int subFunction_id); #endif +#ifdef __cplusplus +} +#endif // extern "C" + #endif // HOST_UNIX #endif // defined(HOST_X86) || defined(HOST_AMD64) diff --git a/src/native/minipal/entrypoints.c b/src/native/minipal/entrypoints.c new file mode 100644 index 00000000000000..7af669924dac62 --- /dev/null +++ b/src/native/minipal/entrypoints.c @@ -0,0 +1,6 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "entrypoints.h" + +extern const void* minipal_resolve_dllimport(const Entry* resolutionTable, size_t tableLength, const char* name); diff --git a/src/native/minipal/entrypoints.h b/src/native/minipal/entrypoints.h index 5ef45699cacdf1..65f1f114741d89 100644 --- a/src/native/minipal/entrypoints.h +++ b/src/native/minipal/entrypoints.h @@ -18,7 +18,11 @@ typedef struct #define DllImportEntry(impl) \ {#impl, (void*)&impl}, -static const void* minipal_resolve_dllimport(const Entry* resolutionTable, size_t tableLength, const char* name) +#ifdef __cplusplus +extern "C" { +#endif + +inline const void* minipal_resolve_dllimport(const Entry* resolutionTable, size_t tableLength, const char* name) { for (size_t i = 0; i < tableLength; i++) { @@ -31,4 +35,8 @@ static const void* minipal_resolve_dllimport(const Entry* resolutionTable, size_ return NULL; } +#ifdef __cplusplus +} +#endif // extern "C" + #endif // HAVE_MINIPAL_ENTRYPOINTS_H diff --git a/src/native/minipal/getexepath.c b/src/native/minipal/getexepath.c new file mode 100644 index 00000000000000..40785b0d7e0439 --- /dev/null +++ b/src/native/minipal/getexepath.c @@ -0,0 +1,183 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "minipalconfig.h" +#include "getexepath.h" + +#include +#include +#include +#include +#include +#include + +#if defined(__APPLE__) +#include +#elif defined(__FreeBSD__) +#include +#include +#include +#elif defined(__OpenBSD__) +#include +#include +#include +#elif defined(_WIN32) +#include +#elif defined(__HAIKU__) +#include +#include +#elif HAVE_GETAUXVAL +#include +#endif + +char* minipal_getexepath(void) +{ +#if defined(__APPLE__) + uint32_t len = PATH_MAX; + char pathBuf[PATH_MAX]; + if (_NSGetExecutablePath(pathBuf, &len) != 0) + { + errno = EINVAL; + return NULL; + } + + return realpath(pathBuf, NULL); +#elif defined(__FreeBSD__) + static const int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; + char path[PATH_MAX]; + size_t len = sizeof(path); + if (sysctl(name, 4, path, &len, NULL, 0) != 0) + { + return NULL; + } + + return strdup(path); +#elif defined(__OpenBSD__) + const int name[] = { CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_ARGV }; + size_t len = 0; + if (sysctl(name, 4, NULL, &len, NULL, 0) != 0 || len == 0) + { + return NULL; + } + + char *buf = (char *)malloc(len); + if (buf == NULL) + { + return NULL; + } + + if (sysctl(name, 4, buf, &len, NULL, 0) != 0) + { + free(buf); + return NULL; + } + + // Cast the start of the buffer to access the char * layout safely + char **argv = (char **)buf; + const char *exe = argv[0]; + + if (strchr(exe, '/') == NULL) + { + const char *p = getenv("PATH"); + while (p != NULL && *p != '\0') + { + size_t seg = strcspn(p, ":"); + char path[PATH_MAX]; + + if (snprintf(path, sizeof(path), "%.*s/%s", (int)seg, p, exe) < (int)sizeof(path)) + { + struct stat sb; + if (stat(path, &sb) == 0 && S_ISREG(sb.st_mode)) + { + char *resolved = realpath(path, NULL); + free(buf); + return resolved; + } + } + + p += seg; + if (*p == ':') + p++; + } + } + + char *resolved = realpath(exe, NULL); + free(buf); + return resolved; +#elif defined(__sun) + const char* path = getexecname(); + if (path == NULL) + { + return NULL; + } + + return realpath(path, NULL); +#elif defined(__HAIKU__) + char path[B_PATH_NAME_LENGTH]; + status_t status = find_path(B_APP_IMAGE_SYMBOL, B_FIND_PATH_IMAGE_PATH, NULL, path, B_PATH_NAME_LENGTH); + if (status != B_OK) + { + errno = status; + return NULL; + } + + return realpath(path, NULL); +#elif defined(_WIN32) + char path[MAX_PATH]; + if (GetModuleFileNameA(NULL, path, MAX_PATH) == 0) + { + return NULL; + } + + return _strdup(path); +#elif defined(TARGET_BROWSER) + const char *browserVirtualAppBase = "/"; // keep in sync other places that define browserVirtualAppBase + return strdup(browserVirtualAppBase); +#elif defined(TARGET_WASI) + // WASI has no /proc, no AT_EXECFN, and argv[0] is unreliable (often "/"). + // corerun.wasm is launched with the CORE_ROOT env var set to the directory + // that holds CoreCLR (System.Private.CoreLib.dll and friends). The PAL only + // needs a path whose dirname is that directory, so synthesize one here. + const char* coreRoot = getenv("CORE_ROOT"); + if (coreRoot == NULL || coreRoot[0] == '\0') + { + return strdup("/"); + } + size_t coreRootLen = strlen(coreRoot); + const char* suffix = "/corerun"; + size_t suffixLen = strlen(suffix); + char* result = (char*)malloc(coreRootLen + suffixLen + 1); + if (result == NULL) + { + return NULL; + } + memcpy(result, coreRoot, coreRootLen); + memcpy(result + coreRootLen, suffix, suffixLen + 1); + return result; +#else +#ifdef __linux__ + const char* symlinkEntrypointExecutable = "/proc/self/exe"; +#else + const char* symlinkEntrypointExecutable = "/proc/curproc/exe"; +#endif + + // Resolve the symlink to the executable from /proc + char* path = realpath(symlinkEntrypointExecutable, NULL); + if (path) + { + return path; + } + +#if HAVE_GETAUXVAL && defined(AT_EXECFN) + // fallback to AT_EXECFN, which does not work properly in rare cases + // when .NET process is set as interpreter (shebang). + const char* exePath = (const char *)(getauxval(AT_EXECFN)); + if (exePath) + { + return realpath(exePath, NULL); + } +#endif // HAVE_GETAUXVAL && defined(AT_EXECFN) + + return NULL; +#endif // defined(__APPLE__) +} diff --git a/src/native/minipal/getexepath.h b/src/native/minipal/getexepath.h index 3d0c0ffdc413c2..da35e02a981586 100644 --- a/src/native/minipal/getexepath.h +++ b/src/native/minipal/getexepath.h @@ -4,33 +4,6 @@ #ifndef HAVE_MINIPAL_GETEXEPATH_H #define HAVE_MINIPAL_GETEXEPATH_H -#include -#include -#include - -#if defined(__APPLE__) -#include -#elif defined(__FreeBSD__) -#include -#include -#include -#include -#elif defined(__OpenBSD__) -#include -#include -#include -#include -#elif defined(_WIN32) -#include -#elif defined(__HAIKU__) -#include -#include -#elif defined(TARGET_WASI) -#include -#elif HAVE_GETAUXVAL -#include -#endif - #ifdef __cplusplus extern "C" { #endif @@ -39,160 +12,10 @@ extern "C" { * Get the full path to the executable for the current process. * Resolves symbolic links. The caller is responsible for releasing the buffer. * - * @return A pointer to a null-terminated string containing the executable path, + * @return A pointer to a null-terminated string containing the executable path, * or NULL if an error occurs. */ -static inline char* minipal_getexepath(void) -{ -#if defined(__APPLE__) - uint32_t len = PATH_MAX; - char pathBuf[PATH_MAX]; - if (_NSGetExecutablePath(pathBuf, &len) != 0) - { - errno = EINVAL; - return NULL; - } - - return realpath(pathBuf, NULL); -#elif defined(__FreeBSD__) - static const int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; - char path[PATH_MAX]; - size_t len = sizeof(path); - if (sysctl(name, 4, path, &len, NULL, 0) != 0) - { - return NULL; - } - - return strdup(path); -#elif defined(__OpenBSD__) - const int name[] = { CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_ARGV }; - size_t len = 0; - if (sysctl(name, 4, NULL, &len, NULL, 0) != 0 || len == 0) - { - return NULL; - } - - char *buf = (char *)malloc(len); - if (buf == NULL) - { - return NULL; - } - - if (sysctl(name, 4, buf, &len, NULL, 0) != 0) - { - free(buf); - return NULL; - } - - // Cast the start of the buffer to access the char * layout safely - char **argv = (char **)buf; - const char *exe = argv[0]; - - if (strchr(exe, '/') == NULL) - { - const char *p = getenv("PATH"); - while (p != NULL && *p != '\0') - { - size_t seg = strcspn(p, ":"); - char path[PATH_MAX]; - - if (snprintf(path, sizeof(path), "%.*s/%s", (int)seg, p, exe) < (int)sizeof(path)) - { - struct stat sb; - if (stat(path, &sb) == 0 && S_ISREG(sb.st_mode)) - { - char *resolved = realpath(path, NULL); - free(buf); - return resolved; - } - } - - p += seg; - if (*p == ':') - p++; - } - } - - char *resolved = realpath(exe, NULL); - free(buf); - return resolved; -#elif defined(__sun) - const char* path = getexecname(); - if (path == NULL) - { - return NULL; - } - - return realpath(path, NULL); -#elif defined(__HAIKU__) - char path[B_PATH_NAME_LENGTH]; - status_t status = find_path(B_APP_IMAGE_SYMBOL, B_FIND_PATH_IMAGE_PATH, NULL, path, B_PATH_NAME_LENGTH); - if (status != B_OK) - { - errno = status; - return NULL; - } - - return realpath(path, NULL); -#elif defined(_WIN32) - char path[MAX_PATH]; - if (GetModuleFileNameA(NULL, path, MAX_PATH) == 0) - { - return NULL; - } - - return strdup(path); -#elif defined(TARGET_BROWSER) - const char *browserVirtualAppBase = "/"; // keep in sync other places that define browserVirtualAppBase - return strdup(browserVirtualAppBase); -#elif defined(TARGET_WASI) - // WASI has no /proc, no AT_EXECFN, and argv[0] is unreliable (often "/"). - // corerun.wasm is launched with the CORE_ROOT env var set to the directory - // that holds CoreCLR (System.Private.CoreLib.dll and friends). The PAL only - // needs a path whose dirname is that directory, so synthesize one here. - const char* coreRoot = getenv("CORE_ROOT"); - if (coreRoot == NULL || coreRoot[0] == '\0') - { - return strdup("/"); - } - size_t coreRootLen = strlen(coreRoot); - const char* suffix = "/corerun"; - size_t suffixLen = strlen(suffix); - char* result = (char*)malloc(coreRootLen + suffixLen + 1); - if (result == NULL) - { - return NULL; - } - memcpy(result, coreRoot, coreRootLen); - memcpy(result + coreRootLen, suffix, suffixLen + 1); - return result; -#else -#ifdef __linux__ - const char* symlinkEntrypointExecutable = "/proc/self/exe"; -#else - const char* symlinkEntrypointExecutable = "/proc/curproc/exe"; -#endif - - // Resolve the symlink to the executable from /proc - char* path = realpath(symlinkEntrypointExecutable, NULL); - if (path) - { - return path; - } - -#if HAVE_GETAUXVAL && defined(AT_EXECFN) - // fallback to AT_EXECFN, which does not work properly in rare cases - // when .NET process is set as interpreter (shebang). - const char* exePath = (const char *)(getauxval(AT_EXECFN)); - if (exePath) - { - return realpath(exePath, NULL); - } -#endif // HAVE_GETAUXVAL && defined(AT_EXECFN) - - return NULL; -#endif // defined(__APPLE__) -} +char* minipal_getexepath(void); #ifdef __cplusplus } diff --git a/src/native/minipal/minipalconfig.h.in b/src/native/minipal/minipalconfig.h.in index 938eb42c415187..f78a66a7fcd852 100644 --- a/src/native/minipal/minipalconfig.h.in +++ b/src/native/minipal/minipalconfig.h.in @@ -4,6 +4,7 @@ #cmakedefine01 HAVE_ARC4RANDOM_BUF #cmakedefine01 HAVE_GETRANDOM #cmakedefine01 HAVE_GETENTROPY +#cmakedefine01 HAVE_GETAUXVAL #cmakedefine01 HAVE_AUXV_HWCAP_H #cmakedefine01 HAVE_HWPROBE_H #cmakedefine01 HAVE_RESOURCE_H diff --git a/src/native/minipal/ospagesize.c b/src/native/minipal/ospagesize.c index 88e9354556fdc7..a76b80b78774b2 100644 --- a/src/native/minipal/ospagesize.c +++ b/src/native/minipal/ospagesize.c @@ -1,15 +1,17 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// POSIX implementation of minipal_getpagesize. On WASM and Windows the page size -// is a compile-time constant and minipal_getpagesize is defined inline in the -// header; this file is excluded from the build on those platforms by -// src/native/minipal/CMakeLists.txt to avoid an empty translation unit. +#include "ospagesize.h" + +#if defined(HOST_WASM) || defined(HOST_WINDOWS) + +extern uint32_t minipal_getpagesize(void); + +#else #include #include #include -#include "ospagesize.h" uint32_t minipal_getpagesize(void) { @@ -38,3 +40,5 @@ uint32_t minipal_getpagesize(void) } return page_size; } + +#endif // HOST_WASM || HOST_WINDOWS diff --git a/src/native/minipal/ospagesize.h b/src/native/minipal/ospagesize.h index 0b6e0c317e2f2f..a7f31bde5d3d7f 100644 --- a/src/native/minipal/ospagesize.h +++ b/src/native/minipal/ospagesize.h @@ -19,7 +19,7 @@ extern "C" { // On other platforms the value is queried from the OS once and cached; the // definition lives in ospagesize.c so there is exactly one cache per process. #if defined(HOST_WASM) -static inline uint32_t minipal_getpagesize(void) +inline uint32_t minipal_getpagesize(void) { // WASM has no hardware pages; getpagesize() returns the 64KB memory.grow granularity, // which is too coarse for GC alignment and thresholds. Reduce the OS page size used @@ -27,7 +27,7 @@ static inline uint32_t minipal_getpagesize(void) return 16 * 1024; } #elif defined(HOST_WINDOWS) -static inline uint32_t minipal_getpagesize(void) +inline uint32_t minipal_getpagesize(void) { // The page size on Windows is 4KB and is not going to change. return 4 * 1024; diff --git a/src/native/minipal/thread.c b/src/native/minipal/thread.c index 8e86796289d46c..cc527a4ca1c522 100644 --- a/src/native/minipal/thread.c +++ b/src/native/minipal/thread.c @@ -1,9 +1,110 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#include -#include +#if defined(__linux__) && !defined(_GNU_SOURCE) +// glibc declares pthread_setname_np only when _GNU_SOURCE is defined before . +#define _GNU_SOURCE +#endif + +#include "thread.h" + +#include +#include +#include + +#if defined(__linux__) +#include +#include +#elif defined(__FreeBSD__) +#include +#elif defined(__OpenBSD__) +#include +#include +#elif defined(__NetBSD__) +#include +#elif defined(__HAIKU__) +#include +#endif + +#ifdef PTHREAD_MAX_NAMELEN_NP +#define MINIPAL_MAX_THREAD_NAME_LENGTH (PTHREAD_MAX_NAMELEN_NP - 1) +#elif defined(__APPLE__) +#define MINIPAL_MAX_THREAD_NAME_LENGTH 63 +#elif defined(__FreeBSD__) +#define MINIPAL_MAX_THREAD_NAME_LENGTH MAXCOMLEN +#elif defined(__HAIKU__) +#define MINIPAL_MAX_THREAD_NAME_LENGTH (B_OS_NAME_LENGTH - 1) +#else +#define MINIPAL_MAX_THREAD_NAME_LENGTH 15 +#endif #if !defined(__wasm) || defined(_REENTRANT) PLATFORM_THREAD_LOCAL size_t minipal_cached_thread_id; #endif + +size_t minipal_get_current_thread_id_no_cache(void) +{ + size_t tid; +#if defined(__wasm) && !defined(_REENTRANT) + tid = 1; // In non-reentrant WASM builds, we define a single thread with ID 1. +#else // !__wasm || _REENTRANT + +#if defined(__linux__) + tid = (size_t)syscall(SYS_gettid); +#elif defined(__APPLE__) + uint64_t thread_id; + pthread_threadid_np(pthread_self(), &thread_id); + tid = (size_t)thread_id; // Cast the uint64_t thread ID to size_t +#elif defined(__FreeBSD__) + tid = (size_t)pthread_getthreadid_np(); +#elif defined(__NetBSD__) + tid = (size_t)_lwp_self(); +#elif defined(__OpenBSD__) + tid = (size_t)getthrid(); +#elif defined(__HAIKU__) + tid = (size_t)find_thread(NULL); +#elif defined(__sun) + tid = (size_t)pthread_self(); +#elif defined(__wasm) + tid = (size_t)(void*)pthread_self(); +#else +#error "Unsupported platform" +#endif + +#endif // __wasm && !_REENTRANT + return tid; +} + +extern size_t minipal_get_current_thread_id(void); + +int minipal_set_thread_name(pthread_t thread, const char* name) +{ +#ifdef __wasm + // WASM does not support pthread_setname_np yet: https://github.com/emscripten-core/emscripten/pull/18751 + return 0; +#else + const char* threadName = name; + char truncatedName[MINIPAL_MAX_THREAD_NAME_LENGTH + 1]; + + if (strlen(name) > MINIPAL_MAX_THREAD_NAME_LENGTH) + { + strncpy(truncatedName, name, MINIPAL_MAX_THREAD_NAME_LENGTH); + truncatedName[MINIPAL_MAX_THREAD_NAME_LENGTH] = '\0'; + threadName = truncatedName; + } + +#if defined(__APPLE__) + // On Apple OSes, pthread_setname_np only works for the calling thread. + if (thread != pthread_self()) return 0; + + return pthread_setname_np(threadName); +#elif defined(__OpenBSD__) + pthread_set_name_np(thread, threadName); + return 0; +#elif defined(__HAIKU__) + return rename_thread(get_pthread_thread_id(thread), threadName); +#else + return pthread_setname_np(thread, threadName); +#endif +#endif +} diff --git a/src/native/minipal/thread.h b/src/native/minipal/thread.h index 1a22d365784d7a..10a1f22683e4fe 100644 --- a/src/native/minipal/thread.h +++ b/src/native/minipal/thread.h @@ -6,38 +6,10 @@ #ifndef HOST_WINDOWS +#include #include -#include -#include -#include #include -#if defined(__linux__) -#include -#include -#elif defined(__FreeBSD__) -#include -#elif defined(__OpenBSD__) -#include -#include -#elif defined(__NetBSD__) -#include -#elif defined(__HAIKU__) -#include -#endif - -#ifdef PTHREAD_MAX_NAMELEN_NP -#define MINIPAL_MAX_THREAD_NAME_LENGTH (PTHREAD_MAX_NAMELEN_NP - 1) -#elif defined(__APPLE__) -#define MINIPAL_MAX_THREAD_NAME_LENGTH 63 -#elif defined(__FreeBSD__) -#define MINIPAL_MAX_THREAD_NAME_LENGTH MAXCOMLEN -#elif defined(__HAIKU__) -#define MINIPAL_MAX_THREAD_NAME_LENGTH (B_OS_NAME_LENGTH - 1) -#else -#define MINIPAL_MAX_THREAD_NAME_LENGTH 15 -#endif - #ifdef __cplusplus extern "C" { #endif @@ -47,38 +19,7 @@ extern "C" { * * @return The current thread ID as a size_t value. */ -static inline size_t minipal_get_current_thread_id_no_cache(void) -{ - size_t tid; -#if defined(__wasm) && !defined(_REENTRANT) - tid = 1; // In non-reentrant WASM builds, we define a single thread with ID 1. -#else // !__wasm || _REENTRANT - -#if defined(__linux__) - tid = (size_t)syscall(SYS_gettid); -#elif defined(__APPLE__) - uint64_t thread_id; - pthread_threadid_np(pthread_self(), &thread_id); - tid = (size_t)thread_id; // Cast the uint64_t thread ID to size_t -#elif defined(__FreeBSD__) - tid = (size_t)pthread_getthreadid_np(); -#elif defined(__NetBSD__) - tid = (size_t)_lwp_self(); -#elif defined(__OpenBSD__) - tid = (size_t)getthrid(); -#elif defined(__HAIKU__) - tid = (size_t)find_thread(NULL); -#elif defined(__sun) - tid = (size_t)pthread_self(); -#elif defined(__wasm) - tid = (size_t)(void*)pthread_self(); -#else -#error "Unsupported platform" -#endif - -#endif // __wasm && !_REENTRANT - return tid; -} +size_t minipal_get_current_thread_id_no_cache(void); #if !defined(__wasm) || defined(_REENTRANT) extern PLATFORM_THREAD_LOCAL size_t minipal_cached_thread_id; @@ -89,7 +30,7 @@ extern PLATFORM_THREAD_LOCAL size_t minipal_cached_thread_id; * * @return The current thread ID as a size_t value. */ -static inline size_t minipal_get_current_thread_id(void) +inline size_t minipal_get_current_thread_id(void) { #if defined(__wasm) && !defined(_REENTRANT) return minipal_get_current_thread_id_no_cache(); @@ -111,38 +52,7 @@ static inline size_t minipal_get_current_thread_id(void) * @param name The desired name for the thread. * @return 0 on success, or an error code if the operation fails. */ -static inline int minipal_set_thread_name(pthread_t thread, const char* name) -{ -#ifdef __wasm - // WASM does not support pthread_setname_np yet: https://github.com/emscripten-core/emscripten/pull/18751 - return 0; -#else - const char* threadName = name; - char truncatedName[MINIPAL_MAX_THREAD_NAME_LENGTH + 1]; - - if (strlen(name) > MINIPAL_MAX_THREAD_NAME_LENGTH) - { - strncpy(truncatedName, name, MINIPAL_MAX_THREAD_NAME_LENGTH); - truncatedName[MINIPAL_MAX_THREAD_NAME_LENGTH] = '\0'; - threadName = truncatedName; - } - -#if defined(__APPLE__) - // On Apple OSes, pthread_setname_np only works for the calling thread. - if (thread != pthread_self()) return 0; - - return pthread_setname_np(threadName); -#elif defined(__OpenBSD__) - pthread_set_name_np(thread, threadName); - return 0; -#elif defined(__HAIKU__) - return rename_thread(get_pthread_thread_id(thread), threadName); -#else - return pthread_setname_np(thread, threadName); -#endif -#endif -} - +int minipal_set_thread_name(pthread_t thread, const char* name); #ifdef __cplusplus }