diff --git a/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake b/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake index 82d06e2b9eb55..0752dfa8b19ea 100644 --- a/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake +++ b/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake @@ -110,6 +110,10 @@ function(_get_compile_options_from_config output_var) list(APPEND config_options "-DLIBC_ERRNO_MODE=${LIBC_CONF_ERRNO_MODE}") endif() + if(LIBC_CONF_THREAD_MODE) + list(APPEND config_options "-DLIBC_THREAD_MODE=${LIBC_CONF_THREAD_MODE}") + endif() + set(${output_var} ${config_options} PARENT_SCOPE) endfunction(_get_compile_options_from_config) diff --git a/libc/config/baremetal/config.json b/libc/config/baremetal/config.json index 105e417d165f0..f01e5084b9695 100644 --- a/libc/config/baremetal/config.json +++ b/libc/config/baremetal/config.json @@ -4,6 +4,11 @@ "value": "LIBC_ERRNO_MODE_EXTERNAL" } }, + "threads": { + "LIBC_CONF_THREAD_MODE": { + "value": "LIBC_THREAD_MODE_SINGLE" + } + }, "printf": { "LIBC_CONF_PRINTF_DISABLE_FIXED_POINT": { "value": true diff --git a/libc/config/config.json b/libc/config/config.json index d53b2936edb07..1b0546980e6ba 100644 --- a/libc/config/config.json +++ b/libc/config/config.json @@ -5,6 +5,12 @@ "doc": "The implementation used for errno, acceptable values are LIBC_ERRNO_MODE_DEFAULT, LIBC_ERRNO_MODE_UNDEFINED, LIBC_ERRNO_MODE_THREAD_LOCAL, LIBC_ERRNO_MODE_SHARED, LIBC_ERRNO_MODE_EXTERNAL, LIBC_ERRNO_MODE_SYSTEM, and LIBC_ERRNO_MODE_SYSTEM_INLINE." } }, + "threads": { + "LIBC_CONF_THREAD_MODE": { + "value": "LIBC_THREAD_MODE_PLATFORM", + "doc": "The implementation used for Mutex, acceptable values are LIBC_THREAD_MODE_PLATFORM, LIBC_THREAD_MODE_SINGLE, and LIBC_THREAD_MODE_EXTERNAL." + } + }, "printf": { "LIBC_CONF_PRINTF_DISABLE_FLOAT": { "value": false, diff --git a/libc/config/gpu/amdgpu/config.json b/libc/config/gpu/amdgpu/config.json index 30ae10e2cfd61..fa179b849dcf7 100644 --- a/libc/config/gpu/amdgpu/config.json +++ b/libc/config/gpu/amdgpu/config.json @@ -4,6 +4,11 @@ "value": "LIBC_ERRNO_MODE_SHARED" } }, + "threads": { + "LIBC_CONF_THREAD_MODE": { + "value": "LIBC_THREAD_MODE_SINGLE" + } + }, "printf": { "LIBC_CONF_PRINTF_DISABLE_FLOAT": { "value": true diff --git a/libc/config/gpu/nvptx/config.json b/libc/config/gpu/nvptx/config.json index 30ae10e2cfd61..fa179b849dcf7 100644 --- a/libc/config/gpu/nvptx/config.json +++ b/libc/config/gpu/nvptx/config.json @@ -4,6 +4,11 @@ "value": "LIBC_ERRNO_MODE_SHARED" } }, + "threads": { + "LIBC_CONF_THREAD_MODE": { + "value": "LIBC_THREAD_MODE_SINGLE" + } + }, "printf": { "LIBC_CONF_PRINTF_DISABLE_FLOAT": { "value": true diff --git a/libc/docs/configure.rst b/libc/docs/configure.rst index 109412225634f..95c51b8517e64 100644 --- a/libc/docs/configure.rst +++ b/libc/docs/configure.rst @@ -60,5 +60,7 @@ to learn about the defaults for your platform and target. * **"string" options** - ``LIBC_CONF_MEMSET_X86_USE_SOFTWARE_PREFETCHING``: Inserts prefetch for write instructions (PREFETCHW) for memset on x86 to recover performance when hardware prefetcher is disabled. - ``LIBC_CONF_STRING_UNSAFE_WIDE_READ``: Read more than a byte at a time to perform byte-string operations like strlen. +* **"threads" options** + - ``LIBC_CONF_THREAD_MODE``: The implementation used for Mutex, acceptable values are LIBC_THREAD_MODE_PLATFORM, LIBC_THREAD_MODE_SINGLE, and LIBC_THREAD_MODE_EXTERNAL. * **"time" options** - ``LIBC_CONF_TIME_64BIT``: Force the size of time_t to 64 bits, even on platforms where compatibility considerations would otherwise make it 32-bit. diff --git a/libc/src/__support/macros/attributes.h b/libc/src/__support/macros/attributes.h index c6474673de85a..0e57f67d5770a 100644 --- a/libc/src/__support/macros/attributes.h +++ b/libc/src/__support/macros/attributes.h @@ -18,6 +18,7 @@ #define LLVM_LIBC_SRC___SUPPORT_MACROS_ATTRIBUTES_H #include "properties/architectures.h" +#include "properties/os.h" #ifndef __has_attribute #define __has_attribute(x) 0 @@ -28,7 +29,9 @@ #define LIBC_INLINE_ASM __asm__ __volatile__ #define LIBC_UNUSED __attribute__((unused)) -#ifdef LIBC_TARGET_ARCH_IS_GPU +// TODO: we need a proper way to only turn this on for single-threaded baremetal +// We cannot use LIBC_THREAD_MODE because libcxx doesn't define that +#if defined(LIBC_TARGET_ARCH_IS_GPU) || defined(LIBC_TARGET_OS_IS_BAREMETAL) #define LIBC_THREAD_LOCAL #else #define LIBC_THREAD_LOCAL thread_local diff --git a/libc/src/__support/macros/properties/os.h b/libc/src/__support/macros/properties/os.h index 807ce1812735c..c142fad441498 100644 --- a/libc/src/__support/macros/properties/os.h +++ b/libc/src/__support/macros/properties/os.h @@ -29,4 +29,12 @@ #define LIBC_TARGET_OS_IS_FUCHSIA #endif +#if !defined(LIBC_TARGET_OS_IS_FREEBSD) && \ + !defined(LIBC_TARGET_OS_IS_ANDROID) && \ + !defined(LIBC_TARGET_OS_IS_LINUX) && \ + !defined(LIBC_TARGET_OS_IS_WINDOWS) && \ + !defined(LIBC_TARGET_OS_IS_FUCHSIA) && defined(__ELF__) +#define LIBC_TARGET_OS_IS_BAREMETAL +#endif + #endif // LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_OS_H diff --git a/libc/src/__support/threads/CMakeLists.txt b/libc/src/__support/threads/CMakeLists.txt index bd49bbb5ad2fe..8e98c1e5da26f 100644 --- a/libc/src/__support/threads/CMakeLists.txt +++ b/libc/src/__support/threads/CMakeLists.txt @@ -42,6 +42,14 @@ if(TARGET libc.src.__support.threads.${LIBC_TARGET_OS}.mutex) .mutex libc.src.__support.CPP.mutex ) +elseif(NOT (LIBC_CONF_THREAD_MODE STREQUAL LIBC_THREAD_MODE_PLATFORM)) + add_header_library( + mutex + HDRS + mutex.h + DEPENDS + .mutex_common + ) endif() add_header_library( diff --git a/libc/src/__support/threads/gpu/CMakeLists.txt b/libc/src/__support/threads/gpu/CMakeLists.txt deleted file mode 100644 index ea89feb0c5c68..0000000000000 --- a/libc/src/__support/threads/gpu/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -add_header_library( - mutex - HDRS - mutex.h -) diff --git a/libc/src/__support/threads/gpu/mutex.h b/libc/src/__support/threads/gpu/mutex.h deleted file mode 100644 index c8c484ed2b794..0000000000000 --- a/libc/src/__support/threads/gpu/mutex.h +++ /dev/null @@ -1,32 +0,0 @@ -//===--- Implementation of a GPU mutex class --------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIBC_SRC___SUPPORT_THREADS_GPU_MUTEX_H -#define LLVM_LIBC_SRC___SUPPORT_THREADS_GPU_MUTEX_H - -#include "src/__support/macros/attributes.h" -#include "src/__support/macros/config.h" -#include "src/__support/threads/mutex_common.h" - -namespace LIBC_NAMESPACE_DECL { - -/// Implementation of a simple passthrough mutex which guards nothing. A -/// complete Mutex locks in general cannot be implemented on the GPU. We simply -/// define the Mutex interface and require that only a single thread executes -/// code requiring a mutex lock. -struct Mutex { - LIBC_INLINE constexpr Mutex(bool, bool, bool, bool) {} - - LIBC_INLINE MutexError lock() { return MutexError::NONE; } - LIBC_INLINE MutexError unlock() { return MutexError::NONE; } - LIBC_INLINE MutexError reset() { return MutexError::NONE; } -}; - -} // namespace LIBC_NAMESPACE_DECL - -#endif // LLVM_LIBC_SRC___SUPPORT_THREADS_GPU_MUTEX_H diff --git a/libc/src/__support/threads/mutex.h b/libc/src/__support/threads/mutex.h index 392b38984dc0a..cbef0d00009b2 100644 --- a/libc/src/__support/threads/mutex.h +++ b/libc/src/__support/threads/mutex.h @@ -9,10 +9,35 @@ #ifndef LLVM_LIBC_SRC___SUPPORT_THREADS_MUTEX_H #define LLVM_LIBC_SRC___SUPPORT_THREADS_MUTEX_H -#include "src/__support/macros/properties/architectures.h" +#include "src/__support/macros/attributes.h" +#include "src/__support/macros/config.h" + +// Uses the platform specific specialization +#define LIBC_THREAD_MODE_PLATFORM 0 + +// Mutex guards nothing, used in single-threaded implementations +#define LIBC_THREAD_MODE_SINGLE 1 + +// Vendor provides implementation +#define LIBC_THREAD_MODE_EXTERNAL 2 + +#if !defined(LIBC_THREAD_MODE) +#error LIBC_THREAD_MODE is undefined +#endif // LIBC_THREAD_MODE + +#if LIBC_THREAD_MODE != LIBC_THREAD_MODE_PLATFORM && \ + LIBC_THREAD_MODE != LIBC_THREAD_MODE_SINGLE && \ + LIBC_THREAD_MODE != LIBC_THREAD_MODE_EXTERNAL +#error LIBC_THREAD_MODE must be one of the following values: \ +LIBC_THREAD_MODE_PLATFORM, \ +LIBC_THREAD_MODE_SINGLE, \ +LIBC_THREAD_MODE_EXTERNAL. +#endif + +#if LIBC_THREAD_MODE == LIBC_THREAD_MODE_PLATFORM // Platform independent code will include this header file which pulls -// the platfrom specific specializations using platform macros. +// the platform specific specializations using platform macros. // // The platform specific specializations should define a class by name // Mutex with non-static methods having the following signature: @@ -39,8 +64,32 @@ #if defined(__linux__) #include "src/__support/threads/linux/mutex.h" -#elif defined(LIBC_TARGET_ARCH_IS_GPU) -#include "src/__support/threads/gpu/mutex.h" #endif // __linux__ +#elif LIBC_THREAD_MODE == LIBC_THREAD_MODE_SINGLE + +#include "src/__support/threads/mutex_common.h" + +namespace LIBC_NAMESPACE_DECL { + +/// Implementation of a simple passthrough mutex which guards nothing. A +/// complete Mutex locks in general cannot be implemented on the GPU, or on some +/// baremetal platforms. We simply define the Mutex interface and require that +/// only a single thread executes code requiring a mutex lock. +struct Mutex { + LIBC_INLINE constexpr Mutex(bool, bool, bool, bool) {} + + LIBC_INLINE MutexError lock() { return MutexError::NONE; } + LIBC_INLINE MutexError unlock() { return MutexError::NONE; } + LIBC_INLINE MutexError reset() { return MutexError::NONE; } +}; + +} // namespace LIBC_NAMESPACE_DECL + +#elif LIBC_THREAD_MODE == LIBC_THREAD_MODE_EXTERNAL + +// TODO: Implement the interfacing, if necessary, e.g. "extern struct Mutex;" + +#endif // LIBC_THREAD_MODE == LIBC_THREAD_MODE_PLATFORM + #endif // LLVM_LIBC_SRC___SUPPORT_THREADS_MUTEX_H