[libc-commits] [libc] [libc] Support configurable errno modes (PR #98287)

Roland McGrath via libc-commits libc-commits at lists.llvm.org
Wed Jul 10 23:48:34 PDT 2024


================
@@ -9,44 +9,91 @@
 #include "libc_errno.h"
 #include "src/__support/CPP/atomic.h"
 
-#ifdef LIBC_TARGET_ARCH_IS_GPU
-// LIBC_THREAD_LOCAL on GPU currently does nothing. So essentially this is just
-// a global errno for gpu to use for now.
+#define LIBC_ERRNO_MODE_UNDEFINED 0x01
+#define LIBC_ERRNO_MODE_THREAD_LOCAL 0x02
+#define LIBC_ERRNO_MODE_GLOBAL 0x04
+#define LIBC_ERRNO_MODE_EXTERNAL 0x08
+#define LIBC_ERRNO_MODE_SYSTEM 0x10
+
+#ifndef LIBC_ERRNO_MODE
+#ifndef LIBC_COPT_PUBLIC_PACKAGING
+// This mode is for unit testing. We just use our internal errno.
+#define LIBC_ERRNO_MODE LIBC_ERRNO_MODE_INTERNAL
+#elif defined(LIBC_FULL_BUILD)
+// In full build mode, we provide the errno storage ourselves.
+#define LIBC_ERRNO_MODE LIBC_ERRNO_MODE_THREAD_LOCAL
+#else
+#define LIBC_ERRNO_MODE LIBC_ERRNO_MODE_SYSTEM
+#endif
+#endif // LIBC_ERRNO_MODE
+
+#if LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_UNDEFINED &&                            \
+    LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_THREAD_LOCAL &&                         \
+    LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_GLOBAL &&                               \
+    LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_EXTERNAL &&                             \
+    LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_SYSTEM
+#error LIBC_ERRNO_MODE must be one of the following values: \
+LIBC_ERRNO_MODE_NONE, \
+LIBC_ERRNO_MODE_THREAD_LOCAL, \
+LIBC_ERRNO_MODE_GLOBAL, \
+LIBC_ERRNO_MODE_EXTERNAL, \
+LIBC_ERRNO_MODE_SYSTEM
+#endif
+
+namespace LIBC_NAMESPACE {
+
+// Define the global `libc_errno` instance.
+Errno libc_errno;
+
+#if LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_UNDEFINED
+
+void Errno::operator=(int) {}
+Errno::operator int() { return 0; }
+
+#elif LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_THREAD_LOCAL
+
+namespace {
+LIBC_THREAD_LOCAL int __libc_errno;
+}
+
 extern "C" {
-LIBC_THREAD_LOCAL LIBC_NAMESPACE::cpp::Atomic<int> __llvmlibc_errno;
+int *__llvm_libc_errno(void) { return &__libc_errno; }
 }
 
-void LIBC_NAMESPACE::Errno::operator=(int a) {
-  __llvmlibc_errno.store(a, cpp::MemoryOrder::RELAXED);
+void Errno::operator=(int a) { __libc_errno = a; }
+Errno::operator int() { return __libc_errno; }
+
+#elif LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_GLOBAL
+
+namespace {
+LIBC_NAMESPACE::cpp::Atomic<int> __libc_errno;
 }
-LIBC_NAMESPACE::Errno::operator int() {
-  return __llvmlibc_errno.load(cpp::MemoryOrder::RELAXED);
+
+extern "C" {
+int *__llvm_libc_errno(void) { return &__libc_errno; }
 }
 
-#elif !defined(LIBC_COPT_PUBLIC_PACKAGING)
-// This mode is for unit testing.  We just use our internal errno.
-LIBC_THREAD_LOCAL int __llvmlibc_internal_errno;
+void Errno::operator=(int a) {
+  __libc_errno.store(a, cpp::MemoryOrder::RELAXED);
+}
+Errno::operator int() {
+  return __libc_errno.load(cpp::MemoryOrder::RELAXED);
+}
 
-void LIBC_NAMESPACE::Errno::operator=(int a) { __llvmlibc_internal_errno = a; }
-LIBC_NAMESPACE::Errno::operator int() { return __llvmlibc_internal_errno; }
+#elif LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_EXTERNAL
 
-#elif defined(LIBC_FULL_BUILD)
-// This mode is for public libc archive, hermetic, and integration tests.
-// In full build mode, we provide the errno storage ourselves.
 extern "C" {
-LIBC_THREAD_LOCAL int __llvmlibc_errno;
+int *__llvm_libc_errno(void);
----------------
frobtech wrote:

I think there's a policy about using a `hdr/errno_macros.h` wrapper instead of doing it directly, but yeah.  In some fashion, the authoritative header file declaration of any public ABI function you're defining really ought to be in scope in the implementation file.


https://github.com/llvm/llvm-project/pull/98287


More information about the libc-commits mailing list