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

Petr Hosek via libc-commits libc-commits at lists.llvm.org
Wed Jul 10 14:19:12 PDT 2024


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

>From 3c915c740cd1439486fd2578ed54e2cfa7edef82 Mon Sep 17 00:00:00 2001
From: Petr Hosek <phosek at google.com>
Date: Thu, 4 Jul 2024 16:49:27 -0700
Subject: [PATCH 1/4] [libc] Support configurable errno modes

Rather than selecting the errno implementation based on the platform
which doesn't provide the necessary flexibility, make it configurable.

The errno value location is returned by __errno_location() which is a
solution used by glibc.
---
 libc/config/baremetal/config.json |   5 ++
 libc/config/config.json           |   6 ++
 libc/config/gpu/config.json       |   5 ++
 libc/docs/configure.rst           |   2 +
 libc/include/errno.h.def          |  18 ++---
 libc/src/errno/CMakeLists.txt     |  12 ++++
 libc/src/errno/libc_errno.cpp     | 106 +++++++++++++++++++++++-------
 libc/src/errno/libc_errno.h       |   1 +
 8 files changed, 118 insertions(+), 37 deletions(-)

diff --git a/libc/config/baremetal/config.json b/libc/config/baremetal/config.json
index dda4c42425755..9e66b682039f7 100644
--- a/libc/config/baremetal/config.json
+++ b/libc/config/baremetal/config.json
@@ -1,4 +1,9 @@
 {
+  "errno": {
+    "LIBC_CONF_ERRNO_MODE": {
+      "value": "LIBC_ERRNO_MODE_LOCATION"
+    }
+  },
   "printf": {
     "LIBC_CONF_PRINTF_DISABLE_FLOAT": {
       "value": true
diff --git a/libc/config/config.json b/libc/config/config.json
index e8feab20175f4..6c59ce95fdcc4 100644
--- a/libc/config/config.json
+++ b/libc/config/config.json
@@ -1,4 +1,10 @@
 {
+  "errno": {
+    "LIBC_CONF_ERRNO_MODE": {
+      "value": "",
+      "doc": "The implementation used for errno, acceptable values are LIBC_ERRNO_MODE_NONE, LIBC_ERRNO_MODE_INTERNAL, LIBC_ERRNO_MODE_EXTERNAL, LIBC_ERRNO_MODE_THREAD_LOCAL, LIBC_ERRNO_MODE_GLOBAL, and LIBC_ERRNO_MODE_LOCATION."
+    }
+  },
   "printf": {
     "LIBC_CONF_PRINTF_DISABLE_FLOAT": {
       "value": false,
diff --git a/libc/config/gpu/config.json b/libc/config/gpu/config.json
index 71107d26ea7ab..390aafad92b95 100644
--- a/libc/config/gpu/config.json
+++ b/libc/config/gpu/config.json
@@ -1,4 +1,9 @@
 {
+  "errno": {
+    "LIBC_CONF_ERRNO_MODE": {
+      "value": "LIBC_ERRNO_MODE_GLOBAL"
+    }
+  },
   "printf": {
     "LIBC_CONF_PRINTF_DISABLE_FLOAT": {
       "value": true
diff --git a/libc/docs/configure.rst b/libc/docs/configure.rst
index 9c641ef94570f..e1aaa28ee9b91 100644
--- a/libc/docs/configure.rst
+++ b/libc/docs/configure.rst
@@ -28,6 +28,8 @@ to learn about the defaults for your platform and target.
 * **"codegen" options**
     - ``LIBC_CONF_ENABLE_STRONG_STACK_PROTECTOR``: Enable -fstack-protector-strong to defend against stack smashing attack.
     - ``LIBC_CONF_KEEP_FRAME_POINTER``: Keep frame pointer in functions for better debugging experience.
+* **"errno" options**
+    - ``LIBC_CONF_ERRNO_MODE``: The implementation used for errno, acceptable values are LIBC_ERRNO_MODE_NONE, LIBC_ERRNO_MODE_INTERNAL, LIBC_ERRNO_MODE_EXTERNAL, LIBC_ERRNO_MODE_THREAD_LOCAL, LIBC_ERRNO_MODE_GLOBAL, and LIBC_ERRNO_MODE_LOCATION.
 * **"malloc" options**
     - ``LIBC_CONF_FREELIST_MALLOC_BUFFER_SIZE``: Default size for the constinit freelist buffer used for the freelist malloc implementation (default 1o 1GB).
 * **"math" options**
diff --git a/libc/include/errno.h.def b/libc/include/errno.h.def
index 1f7120e63bfc9..298f02116a25f 100644
--- a/libc/include/errno.h.def
+++ b/libc/include/errno.h.def
@@ -25,18 +25,12 @@
 #include "llvm-libc-macros/generic-error-number-macros.h"
 #endif
 
-#if defined(__AMDGPU__) || defined(__NVPTX__)
-extern int __llvmlibc_errno; // Not thread_local!
-#else
-#ifdef __cplusplus
-extern "C" {
-extern thread_local int __llvmlibc_errno;
-}
-#else
-extern _Thread_local int __llvmlibc_errno;
-#endif // __cplusplus
-#endif
+__BEGIN_C_DECLS
+
+int *__errno_location(void) __NOEXCEPT;
+
+__END_C_DECLS
 
-#define errno __llvmlibc_errno
+#define errno (*__errno_location())
 
 #endif // LLVM_LIBC_ERRNO_H
diff --git a/libc/src/errno/CMakeLists.txt b/libc/src/errno/CMakeLists.txt
index 2622e51261cc3..ca049143874ac 100644
--- a/libc/src/errno/CMakeLists.txt
+++ b/libc/src/errno/CMakeLists.txt
@@ -9,6 +9,17 @@ if(LLVM_LIBC_FULL_BUILD)
   set(full_build_flag "-DLIBC_FULL_BUILD")
 endif()
 
+if(LIBC_CONF_ERRNO_MODE)
+  set(errno_config_copts "-DLIBC_ERRNO_MODE=${LIBC_CONF_ERRNO_MODE}")
+else()
+  if(LLVM_LIBC_FULL_BUILD)
+    set(errno_mode "LIBC_ERRNO_MODE_THREAD_LOCAL")
+  else()
+    set(errno_mode "LIBC_ERRNO_MODE_EXTERNAL")
+  endif()
+  set(errno_config_copts "-DLIBC_ERRNO_MODE=${errno_mode}")
+endif()
+
 add_entrypoint_object(
   errno
   SRCS
@@ -17,6 +28,7 @@ add_entrypoint_object(
     libc_errno.h     # Include this
   COMPILE_OPTIONS
     ${full_build_flag}
+    ${errno_config_copts}
   DEPENDS
     libc.hdr.errno_macros
     libc.src.__support.common
diff --git a/libc/src/errno/libc_errno.cpp b/libc/src/errno/libc_errno.cpp
index bd1438c226143..ccc7467ed22ff 100644
--- a/libc/src/errno/libc_errno.cpp
+++ b/libc/src/errno/libc_errno.cpp
@@ -9,44 +9,100 @@
 #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_NONE 0x01
+#define LIBC_ERRNO_MODE_INTERNAL 0x02
+#define LIBC_ERRNO_MODE_EXTERNAL 0x04
+#define LIBC_ERRNO_MODE_THREAD_LOCAL 0x08
+#define LIBC_ERRNO_MODE_GLOBAL 0x10
+#define LIBC_ERRNO_MODE_LOCATION 0x20
+
+#ifndef LIBC_ERRNO_MODE
+#error LIBC_ERRNO_MODE is not defined
+#endif
+
+#if LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_NONE && \
+    LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_INTERNAL && \
+    LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_EXTERNAL && \
+    LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_THREAD_LOCAL && \
+    LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_GLOBAL && \
+    LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_LOCATION
+#error LIBC_ERRNO_MODE must be one of the following values: \
+LIBC_ERRNO_MODE_NONE, \
+LIBC_ERRNO_MODE_INTERNAL, \
+LIBC_ERRNO_MODE_EXTERNAL, \
+LIBC_ERRNO_MODE_THREAD_LOCAL, \
+LIBC_ERRNO_MODE_GLOBAL, \
+LIBC_ERRNO_MODE_LOCATION
+#endif
+
+namespace LIBC_NAMESPACE {
+
+// Define the global `libc_errno` instance.
+Errno libc_errno;
+
+#if LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_NONE
+
 extern "C" {
-LIBC_THREAD_LOCAL LIBC_NAMESPACE::cpp::Atomic<int> __llvmlibc_errno;
+const int __llvmlibc_errno = 0;
+int *__errno_location(void) { return &__llvmlibc_errno; }
 }
 
-void LIBC_NAMESPACE::Errno::operator=(int a) {
-  __llvmlibc_errno.store(a, cpp::MemoryOrder::RELAXED);
+void Errno::operator=(int) {}
+Errno::operator int() { return 0; }
+
+#elif LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_INTERNAL
+
+LIBC_THREAD_LOCAL int __llvmlibc_internal_errno;
+
+extern "C" {
+int *__errno_location(void) { return &__llvmlibc_internal_errno; }
 }
-LIBC_NAMESPACE::Errno::operator int() {
-  return __llvmlibc_errno.load(cpp::MemoryOrder::RELAXED);
+
+void Errno::operator=(int a) { __llvmlibc_internal_errno = a; }
+Errno::operator int() { return __llvmlibc_internal_errno; }
+
+#elif LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_EXTERNAL
+
+extern "C" {
+int *__errno_location(void) { return &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) { errno = a; }
+Errno::operator int() { return errno; }
 
-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_THREAD_LOCAL
 
-#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 *__errno_location(void) { return &__llvmlibc_errno; }
 }
 
-void LIBC_NAMESPACE::Errno::operator=(int a) { __llvmlibc_errno = a; }
-LIBC_NAMESPACE::Errno::operator int() { return __llvmlibc_errno; }
+void Errno::operator=(int a) { __llvmlibc_errno = a; }
+Errno::operator int() { return __llvmlibc_errno; }
 
-#else
-void LIBC_NAMESPACE::Errno::operator=(int a) { errno = a; }
-LIBC_NAMESPACE::Errno::operator int() { return errno; }
+#elif LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_GLOBAL
 
-#endif // LIBC_FULL_BUILD
+extern "C" {
+LIBC_NAMESPACE::cpp::Atomic<int> __llvmlibc_errno;
+int *__errno_location(void) { return &__llvmlibc_errno; }
+}
+
+void Errno::operator=(int a) {
+  __llvmlibc_errno.store(a, cpp::MemoryOrder::RELAXED);
+}
+Errno::operator int() {
+  return __llvmlibc_errno.load(cpp::MemoryOrder::RELAXED);
+}
+
+#elif LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_LOCATION
+
+extern "C" {
+int *__errno_location(void);
+}
+
+void Errno::operator=(int a) { *__errno_location() = a; }
+Errno::operator int() { return *__errno_location(); }
+
+#endif
 
-namespace LIBC_NAMESPACE {
-// Define the global `libc_errno` instance.
-Errno libc_errno;
 } // namespace LIBC_NAMESPACE
diff --git a/libc/src/errno/libc_errno.h b/libc/src/errno/libc_errno.h
index df67ea3b42faa..a5c1e3e485407 100644
--- a/libc/src/errno/libc_errno.h
+++ b/libc/src/errno/libc_errno.h
@@ -31,6 +31,7 @@
 // - Still depend on libc.src.errno.errno
 
 namespace LIBC_NAMESPACE {
+
 struct Errno {
   void operator=(int);
   operator int();

>From 8a866a0f6f14f809d4b8053cec46cc6ba768d0ab Mon Sep 17 00:00:00 2001
From: Petr Hosek <phosek at google.com>
Date: Wed, 10 Jul 2024 01:42:52 -0700
Subject: [PATCH 2/4] Fix formatting

---
 libc/src/errno/libc_errno.cpp | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/libc/src/errno/libc_errno.cpp b/libc/src/errno/libc_errno.cpp
index ccc7467ed22ff..cf42f26e0123f 100644
--- a/libc/src/errno/libc_errno.cpp
+++ b/libc/src/errno/libc_errno.cpp
@@ -20,11 +20,11 @@
 #error LIBC_ERRNO_MODE is not defined
 #endif
 
-#if LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_NONE && \
-    LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_INTERNAL && \
-    LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_EXTERNAL && \
-    LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_THREAD_LOCAL && \
-    LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_GLOBAL && \
+#if LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_NONE &&                                 \
+    LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_INTERNAL &&                             \
+    LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_EXTERNAL &&                             \
+    LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_THREAD_LOCAL &&                         \
+    LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_GLOBAL &&                               \
     LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_LOCATION
 #error LIBC_ERRNO_MODE must be one of the following values: \
 LIBC_ERRNO_MODE_NONE, \

>From 4ceb880f62f7069db1cd89ae7e72f7b185d72911 Mon Sep 17 00:00:00 2001
From: Petr Hosek <phosek at google.com>
Date: Wed, 10 Jul 2024 12:35:15 -0700
Subject: [PATCH 3/4] Address review feedback

---
 libc/config/baremetal/config.json |  2 +-
 libc/config/config.json           |  2 +-
 libc/docs/configure.rst           |  2 +-
 libc/src/errno/CMakeLists.txt     |  7 -------
 libc/src/errno/libc_errno.cpp     | 31 ++++++++++++++-----------------
 5 files changed, 17 insertions(+), 27 deletions(-)

diff --git a/libc/config/baremetal/config.json b/libc/config/baremetal/config.json
index 9e66b682039f7..b7426dd341d97 100644
--- a/libc/config/baremetal/config.json
+++ b/libc/config/baremetal/config.json
@@ -1,7 +1,7 @@
 {
   "errno": {
     "LIBC_CONF_ERRNO_MODE": {
-      "value": "LIBC_ERRNO_MODE_LOCATION"
+      "value": "LIBC_ERRNO_MODE_EXTERNAL"
     }
   },
   "printf": {
diff --git a/libc/config/config.json b/libc/config/config.json
index 6c59ce95fdcc4..0df91aa9a6e73 100644
--- a/libc/config/config.json
+++ b/libc/config/config.json
@@ -2,7 +2,7 @@
   "errno": {
     "LIBC_CONF_ERRNO_MODE": {
       "value": "",
-      "doc": "The implementation used for errno, acceptable values are LIBC_ERRNO_MODE_NONE, LIBC_ERRNO_MODE_INTERNAL, LIBC_ERRNO_MODE_EXTERNAL, LIBC_ERRNO_MODE_THREAD_LOCAL, LIBC_ERRNO_MODE_GLOBAL, and LIBC_ERRNO_MODE_LOCATION."
+      "doc": "The implementation used for errno, acceptable values are LIBC_ERRNO_MODE_NONE, LIBC_ERRNO_MODE_INTERNAL, LIBC_ERRNO_MODE_EXTERNAL, LIBC_ERRNO_MODE_THREAD_LOCAL, and LIBC_ERRNO_MODE_GLOBAL."
     }
   },
   "printf": {
diff --git a/libc/docs/configure.rst b/libc/docs/configure.rst
index e1aaa28ee9b91..348945fe71645 100644
--- a/libc/docs/configure.rst
+++ b/libc/docs/configure.rst
@@ -29,7 +29,7 @@ to learn about the defaults for your platform and target.
     - ``LIBC_CONF_ENABLE_STRONG_STACK_PROTECTOR``: Enable -fstack-protector-strong to defend against stack smashing attack.
     - ``LIBC_CONF_KEEP_FRAME_POINTER``: Keep frame pointer in functions for better debugging experience.
 * **"errno" options**
-    - ``LIBC_CONF_ERRNO_MODE``: The implementation used for errno, acceptable values are LIBC_ERRNO_MODE_NONE, LIBC_ERRNO_MODE_INTERNAL, LIBC_ERRNO_MODE_EXTERNAL, LIBC_ERRNO_MODE_THREAD_LOCAL, LIBC_ERRNO_MODE_GLOBAL, and LIBC_ERRNO_MODE_LOCATION.
+    - ``LIBC_CONF_ERRNO_MODE``: The implementation used for errno, acceptable values are LIBC_ERRNO_MODE_NONE, LIBC_ERRNO_MODE_INTERNAL, LIBC_ERRNO_MODE_EXTERNAL, LIBC_ERRNO_MODE_THREAD_LOCAL, and LIBC_ERRNO_MODE_GLOBAL.
 * **"malloc" options**
     - ``LIBC_CONF_FREELIST_MALLOC_BUFFER_SIZE``: Default size for the constinit freelist buffer used for the freelist malloc implementation (default 1o 1GB).
 * **"math" options**
diff --git a/libc/src/errno/CMakeLists.txt b/libc/src/errno/CMakeLists.txt
index ca049143874ac..1d78a5eedff96 100644
--- a/libc/src/errno/CMakeLists.txt
+++ b/libc/src/errno/CMakeLists.txt
@@ -11,13 +11,6 @@ endif()
 
 if(LIBC_CONF_ERRNO_MODE)
   set(errno_config_copts "-DLIBC_ERRNO_MODE=${LIBC_CONF_ERRNO_MODE}")
-else()
-  if(LLVM_LIBC_FULL_BUILD)
-    set(errno_mode "LIBC_ERRNO_MODE_THREAD_LOCAL")
-  else()
-    set(errno_mode "LIBC_ERRNO_MODE_EXTERNAL")
-  endif()
-  set(errno_config_copts "-DLIBC_ERRNO_MODE=${errno_mode}")
 endif()
 
 add_entrypoint_object(
diff --git a/libc/src/errno/libc_errno.cpp b/libc/src/errno/libc_errno.cpp
index cf42f26e0123f..7afd367912ef0 100644
--- a/libc/src/errno/libc_errno.cpp
+++ b/libc/src/errno/libc_errno.cpp
@@ -17,22 +17,28 @@
 #define LIBC_ERRNO_MODE_LOCATION 0x20
 
 #ifndef LIBC_ERRNO_MODE
-#error LIBC_ERRNO_MODE is not defined
+#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_EXTERNAL
 #endif
+#endif // LIBC_ERRNO_MODE
 
 #if LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_NONE &&                                 \
     LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_INTERNAL &&                             \
     LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_EXTERNAL &&                             \
     LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_THREAD_LOCAL &&                         \
-    LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_GLOBAL &&                               \
-    LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_LOCATION
+    LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_GLOBAL
 #error LIBC_ERRNO_MODE must be one of the following values: \
 LIBC_ERRNO_MODE_NONE, \
 LIBC_ERRNO_MODE_INTERNAL, \
 LIBC_ERRNO_MODE_EXTERNAL, \
 LIBC_ERRNO_MODE_THREAD_LOCAL, \
-LIBC_ERRNO_MODE_GLOBAL, \
-LIBC_ERRNO_MODE_LOCATION
+LIBC_ERRNO_MODE_GLOBAL
 #endif
 
 namespace LIBC_NAMESPACE {
@@ -64,11 +70,11 @@ Errno::operator int() { return __llvmlibc_internal_errno; }
 #elif LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_EXTERNAL
 
 extern "C" {
-int *__errno_location(void) { return &errno; }
+int *__errno_location(void);
 }
 
-void Errno::operator=(int a) { errno = a; }
-Errno::operator int() { return errno; }
+void Errno::operator=(int a) { *__errno_location() = a; }
+Errno::operator int() { return *__errno_location(); }
 
 #elif LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_THREAD_LOCAL
 
@@ -94,15 +100,6 @@ Errno::operator int() {
   return __llvmlibc_errno.load(cpp::MemoryOrder::RELAXED);
 }
 
-#elif LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_LOCATION
-
-extern "C" {
-int *__errno_location(void);
-}
-
-void Errno::operator=(int a) { *__errno_location() = a; }
-Errno::operator int() { return *__errno_location(); }
-
 #endif
 
 } // namespace LIBC_NAMESPACE

>From 34f55c6b9133e226f308cbc2df65fc5896798c4d Mon Sep 17 00:00:00 2001
From: Petr Hosek <phosek at google.com>
Date: Wed, 10 Jul 2024 14:18:49 -0700
Subject: [PATCH 4/4] Update symbol naming

---
 libc/config/config.json       |  2 +-
 libc/docs/configure.rst       |  2 +-
 libc/include/errno.h.def      |  4 +-
 libc/src/errno/libc_errno.cpp | 86 ++++++++++++++++-------------------
 4 files changed, 44 insertions(+), 50 deletions(-)

diff --git a/libc/config/config.json b/libc/config/config.json
index 0df91aa9a6e73..220b84fea5c66 100644
--- a/libc/config/config.json
+++ b/libc/config/config.json
@@ -2,7 +2,7 @@
   "errno": {
     "LIBC_CONF_ERRNO_MODE": {
       "value": "",
-      "doc": "The implementation used for errno, acceptable values are LIBC_ERRNO_MODE_NONE, LIBC_ERRNO_MODE_INTERNAL, LIBC_ERRNO_MODE_EXTERNAL, LIBC_ERRNO_MODE_THREAD_LOCAL, and LIBC_ERRNO_MODE_GLOBAL."
+      "doc": "The implementation used for errno, acceptable values are LIBC_ERRNO_MODE_NONE, LIBC_ERRNO_MODE_INTERNAL, LIBC_ERRNO_MODE_EXTERNAL, LIBC_ERRNO_MODE_THREAD_LOCAL, LIBC_ERRNO_MODE_GLOBAL, and LIBC_ERRNO_MODE_SYSTEM."
     }
   },
   "printf": {
diff --git a/libc/docs/configure.rst b/libc/docs/configure.rst
index 348945fe71645..43e1d373998f7 100644
--- a/libc/docs/configure.rst
+++ b/libc/docs/configure.rst
@@ -29,7 +29,7 @@ to learn about the defaults for your platform and target.
     - ``LIBC_CONF_ENABLE_STRONG_STACK_PROTECTOR``: Enable -fstack-protector-strong to defend against stack smashing attack.
     - ``LIBC_CONF_KEEP_FRAME_POINTER``: Keep frame pointer in functions for better debugging experience.
 * **"errno" options**
-    - ``LIBC_CONF_ERRNO_MODE``: The implementation used for errno, acceptable values are LIBC_ERRNO_MODE_NONE, LIBC_ERRNO_MODE_INTERNAL, LIBC_ERRNO_MODE_EXTERNAL, LIBC_ERRNO_MODE_THREAD_LOCAL, and LIBC_ERRNO_MODE_GLOBAL.
+    - ``LIBC_CONF_ERRNO_MODE``: The implementation used for errno, acceptable values are LIBC_ERRNO_MODE_NONE, LIBC_ERRNO_MODE_INTERNAL, LIBC_ERRNO_MODE_EXTERNAL, LIBC_ERRNO_MODE_THREAD_LOCAL, LIBC_ERRNO_MODE_GLOBAL, and LIBC_ERRNO_MODE_SYSTEM.
 * **"malloc" options**
     - ``LIBC_CONF_FREELIST_MALLOC_BUFFER_SIZE``: Default size for the constinit freelist buffer used for the freelist malloc implementation (default 1o 1GB).
 * **"math" options**
diff --git a/libc/include/errno.h.def b/libc/include/errno.h.def
index 298f02116a25f..aa1f6c9e48444 100644
--- a/libc/include/errno.h.def
+++ b/libc/include/errno.h.def
@@ -27,10 +27,10 @@
 
 __BEGIN_C_DECLS
 
-int *__errno_location(void) __NOEXCEPT;
+int *__llvm_libc_errno(void) __NOEXCEPT;
 
 __END_C_DECLS
 
-#define errno (*__errno_location())
+#define errno (*__llvm_libc_errno())
 
 #endif // LLVM_LIBC_ERRNO_H
diff --git a/libc/src/errno/libc_errno.cpp b/libc/src/errno/libc_errno.cpp
index 7afd367912ef0..4b74056897cc4 100644
--- a/libc/src/errno/libc_errno.cpp
+++ b/libc/src/errno/libc_errno.cpp
@@ -9,12 +9,11 @@
 #include "libc_errno.h"
 #include "src/__support/CPP/atomic.h"
 
-#define LIBC_ERRNO_MODE_NONE 0x01
-#define LIBC_ERRNO_MODE_INTERNAL 0x02
-#define LIBC_ERRNO_MODE_EXTERNAL 0x04
-#define LIBC_ERRNO_MODE_THREAD_LOCAL 0x08
-#define LIBC_ERRNO_MODE_GLOBAL 0x10
-#define LIBC_ERRNO_MODE_LOCATION 0x20
+#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
@@ -24,21 +23,21 @@
 // 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_EXTERNAL
+#define LIBC_ERRNO_MODE LIBC_ERRNO_MODE_SYSTEM
 #endif
 #endif // LIBC_ERRNO_MODE
 
-#if LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_NONE &&                                 \
-    LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_INTERNAL &&                             \
-    LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_EXTERNAL &&                             \
+#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_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_INTERNAL, \
-LIBC_ERRNO_MODE_EXTERNAL, \
 LIBC_ERRNO_MODE_THREAD_LOCAL, \
-LIBC_ERRNO_MODE_GLOBAL
+LIBC_ERRNO_MODE_GLOBAL, \
+LIBC_ERRNO_MODE_EXTERNAL, \
+LIBC_ERRNO_MODE_SYSTEM
 #endif
 
 namespace LIBC_NAMESPACE {
@@ -46,60 +45,55 @@ namespace LIBC_NAMESPACE {
 // Define the global `libc_errno` instance.
 Errno libc_errno;
 
-#if LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_NONE
-
-extern "C" {
-const int __llvmlibc_errno = 0;
-int *__errno_location(void) { return &__llvmlibc_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_INTERNAL
-
-LIBC_THREAD_LOCAL int __llvmlibc_internal_errno;
+#elif LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_THREAD_LOCAL
 
-extern "C" {
-int *__errno_location(void) { return &__llvmlibc_internal_errno; }
+namespace {
+LIBC_THREAD_LOCAL int __libc_errno;
 }
 
-void Errno::operator=(int a) { __llvmlibc_internal_errno = a; }
-Errno::operator int() { return __llvmlibc_internal_errno; }
-
-#elif LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_EXTERNAL
-
 extern "C" {
-int *__errno_location(void);
+int *__llvm_libc_errno(void) { return &__libc_errno; }
 }
 
-void Errno::operator=(int a) { *__errno_location() = a; }
-Errno::operator int() { return *__errno_location(); }
+void Errno::operator=(int a) { __libc_errno = a; }
+Errno::operator int() { return __libc_errno; }
 
-#elif LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_THREAD_LOCAL
+#elif LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_GLOBAL
 
-extern "C" {
-LIBC_THREAD_LOCAL int __llvmlibc_errno;
-int *__errno_location(void) { return &__llvmlibc_errno; }
+namespace {
+LIBC_NAMESPACE::cpp::Atomic<int> __libc_errno;
 }
 
-void Errno::operator=(int a) { __llvmlibc_errno = a; }
-Errno::operator int() { return __llvmlibc_errno; }
-
-#elif LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_GLOBAL
-
 extern "C" {
-LIBC_NAMESPACE::cpp::Atomic<int> __llvmlibc_errno;
-int *__errno_location(void) { return &__llvmlibc_errno; }
+int *__llvm_libc_errno(void) { return &__libc_errno; }
 }
 
 void Errno::operator=(int a) {
-  __llvmlibc_errno.store(a, cpp::MemoryOrder::RELAXED);
+  __libc_errno.store(a, cpp::MemoryOrder::RELAXED);
 }
 Errno::operator int() {
-  return __llvmlibc_errno.load(cpp::MemoryOrder::RELAXED);
+  return __libc_errno.load(cpp::MemoryOrder::RELAXED);
 }
 
+#elif LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_EXTERNAL
+
+extern "C" {
+int *__llvm_libc_errno(void);
+}
+
+void Errno::operator=(int a) { *__llvm_libc_errno() = a; }
+Errno::operator int() { return *__llvm_libc_errno(); }
+
+#elif LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_SYSTEM
+
+void Errno::operator=(int a) { errno = a; }
+Errno::operator int() { return errno; }
+
 #endif
 
 } // namespace LIBC_NAMESPACE



More information about the libc-commits mailing list