[libc-commits] [libc] [libc] Support configurable errno modes (PR #98287)
Petr Hosek via libc-commits
libc-commits at lists.llvm.org
Thu Jul 11 21:15:30 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/9] [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/9] 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/9] 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/9] 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
>From f4b0578c9984622183bf8eba414c1bf6c902aa9e Mon Sep 17 00:00:00 2001
From: Petr Hosek <phosek at google.com>
Date: Wed, 10 Jul 2024 23:59:07 -0700
Subject: [PATCH 5/9] Address review feedback
---
libc/config/config.json | 2 +-
libc/docs/configure.rst | 2 +-
libc/src/errno/libc_errno.cpp | 32 ++++++++++++++------------------
3 files changed, 16 insertions(+), 20 deletions(-)
diff --git a/libc/config/config.json b/libc/config/config.json
index 220b84fea5c66..3a9c08d195445 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_SYSTEM."
+ "doc": "The implementation used for errno, acceptable values are LIBC_ERRNO_MODE_UNDEFINED, LIBC_ERRNO_MODE_THREAD_LOCAL, LIBC_ERRNO_MODE_SHARED, LIBC_ERRNO_MODE_EXTERNAL, and LIBC_ERRNO_MODE_SYSTEM."
}
},
"printf": {
diff --git a/libc/docs/configure.rst b/libc/docs/configure.rst
index 43e1d373998f7..24ef2ef189ffd 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_SYSTEM.
+ - ``LIBC_CONF_ERRNO_MODE``: The implementation used for errno, acceptable values are LIBC_ERRNO_MODE_UNDEFINED, LIBC_ERRNO_MODE_THREAD_LOCAL, LIBC_ERRNO_MODE_SHARED, LIBC_ERRNO_MODE_EXTERNAL, 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/src/errno/libc_errno.cpp b/libc/src/errno/libc_errno.cpp
index 4b74056897cc4..303b0ae8f7e5b 100644
--- a/libc/src/errno/libc_errno.cpp
+++ b/libc/src/errno/libc_errno.cpp
@@ -9,18 +9,14 @@
#include "libc_errno.h"
#include "src/__support/CPP/atomic.h"
-#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
+#define LIBC_ERRNO_MODE_UNDEFINED 1
+#define LIBC_ERRNO_MODE_THREAD_LOCAL 2
+#define LIBC_ERRNO_MODE_SHARED 3
+#define LIBC_ERRNO_MODE_EXTERNAL 4
+#define LIBC_ERRNO_MODE_SYSTEM 5
#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.
+#if defined(LIBC_FULL_BUILD) || !defined(LIBC_COPT_PUBLIC_PACKAGING)
#define LIBC_ERRNO_MODE LIBC_ERRNO_MODE_THREAD_LOCAL
#else
#define LIBC_ERRNO_MODE LIBC_ERRNO_MODE_SYSTEM
@@ -29,13 +25,13 @@
#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_SHARED && \
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_UNDEFINED, \
LIBC_ERRNO_MODE_THREAD_LOCAL, \
-LIBC_ERRNO_MODE_GLOBAL, \
+LIBC_ERRNO_MODE_SHARED, \
LIBC_ERRNO_MODE_EXTERNAL, \
LIBC_ERRNO_MODE_SYSTEM
#endif
@@ -53,11 +49,11 @@ Errno::operator int() { return 0; }
#elif LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_THREAD_LOCAL
namespace {
-LIBC_THREAD_LOCAL int __libc_errno;
+LIBC_THREAD_LOCAL int thread_errno;
}
extern "C" {
-int *__llvm_libc_errno(void) { return &__libc_errno; }
+int *__llvm_libc_errno() { return &thread_errno; }
}
void Errno::operator=(int a) { __libc_errno = a; }
@@ -66,11 +62,11 @@ Errno::operator int() { return __libc_errno; }
#elif LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_GLOBAL
namespace {
-LIBC_NAMESPACE::cpp::Atomic<int> __libc_errno;
+cpp::Atomic<int> global_errno;
}
extern "C" {
-int *__llvm_libc_errno(void) { return &__libc_errno; }
+int *__llvm_libc_errno() { return &global_errno; }
}
void Errno::operator=(int a) {
@@ -83,7 +79,7 @@ Errno::operator int() {
#elif LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_EXTERNAL
extern "C" {
-int *__llvm_libc_errno(void);
+int *__llvm_libc_errno();
}
void Errno::operator=(int a) { *__llvm_libc_errno() = a; }
>From c03ff0e73b3a741dcc0cfc1a8390665c1b07d5cf Mon Sep 17 00:00:00 2001
From: Petr Hosek <phosek at google.com>
Date: Thu, 11 Jul 2024 00:08:51 -0700
Subject: [PATCH 6/9] Fix formatting
---
libc/src/errno/libc_errno.cpp | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/libc/src/errno/libc_errno.cpp b/libc/src/errno/libc_errno.cpp
index 303b0ae8f7e5b..ccf5a7f136227 100644
--- a/libc/src/errno/libc_errno.cpp
+++ b/libc/src/errno/libc_errno.cpp
@@ -72,9 +72,7 @@ int *__llvm_libc_errno() { return &global_errno; }
void Errno::operator=(int a) {
__libc_errno.store(a, cpp::MemoryOrder::RELAXED);
}
-Errno::operator int() {
- return __libc_errno.load(cpp::MemoryOrder::RELAXED);
-}
+Errno::operator int() { return __libc_errno.load(cpp::MemoryOrder::RELAXED); }
#elif LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_EXTERNAL
>From 28d218102e6659bd0a02e7fd371488eddcdc8bd6 Mon Sep 17 00:00:00 2001
From: Petr Hosek <phosek at google.com>
Date: Thu, 11 Jul 2024 00:17:16 -0700
Subject: [PATCH 7/9] Update documentation
---
libc/docs/configure.rst | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/libc/docs/configure.rst b/libc/docs/configure.rst
index 24ef2ef189ffd..2e6e40191bff8 100644
--- a/libc/docs/configure.rst
+++ b/libc/docs/configure.rst
@@ -29,7 +29,12 @@ 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_UNDEFINED, LIBC_ERRNO_MODE_THREAD_LOCAL, LIBC_ERRNO_MODE_SHARED, LIBC_ERRNO_MODE_EXTERNAL, and LIBC_ERRNO_MODE_SYSTEM.
+ - ``LIBC_CONF_ERRNO_MODE``: The implementation used for errno, acceptable values are:
+ - ``LIBC_ERRNO_MODE_UNDEFINED``: libc never stores a value; ``errno`` macro uses get link-time failure,
+ - ``LIBC_ERRNO_MODE_THREAD_LOCAL``: libc maintains per-thread state (requires C++ ``thread_local`` support for libc implementation code),
+ - ``LIBC_ERRNO_MODE_SHARED``: libc maintains an ``atomic_int`` used by all threads, contrary to standard C semantics (requires use of atomics in libc implementation code, may produce libcalls an embedder must supply),
+ - ``LIBC_ERRNO_MODE_EXTERNAL``: embedder must define ``int *__llvm_libc_errno(void);`` C function,
+ - ``LIBC_ERRNO_MODE_SYSTEM``: in overlay mode, system ``<errno.h>`` ``errno`` macro is used directly; in fullbuild mode, effectively the same as ``LIBC_ERRNO_MODE_EXTERNAL``.
* **"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**
>From 5959fb2fc5ece3ddaab53435cb2e234ee5d52da0 Mon Sep 17 00:00:00 2001
From: Petr Hosek <phosek at google.com>
Date: Thu, 11 Jul 2024 00:25:04 -0700
Subject: [PATCH 8/9] Address review feedback
---
libc/config/gpu/config.json | 2 +-
libc/docs/configure.rst | 2 +-
libc/src/errno/errno.h | 14 ++++++++++++++
libc/src/errno/libc_errno.cpp | 22 ++++++++--------------
4 files changed, 24 insertions(+), 16 deletions(-)
create mode 100644 libc/src/errno/errno.h
diff --git a/libc/config/gpu/config.json b/libc/config/gpu/config.json
index 390aafad92b95..954163947b8a4 100644
--- a/libc/config/gpu/config.json
+++ b/libc/config/gpu/config.json
@@ -1,7 +1,7 @@
{
"errno": {
"LIBC_CONF_ERRNO_MODE": {
- "value": "LIBC_ERRNO_MODE_GLOBAL"
+ "value": "LIBC_ERRNO_MODE_SHARED"
}
},
"printf": {
diff --git a/libc/docs/configure.rst b/libc/docs/configure.rst
index 2e6e40191bff8..271c51911cc93 100644
--- a/libc/docs/configure.rst
+++ b/libc/docs/configure.rst
@@ -32,7 +32,7 @@ to learn about the defaults for your platform and target.
- ``LIBC_CONF_ERRNO_MODE``: The implementation used for errno, acceptable values are:
- ``LIBC_ERRNO_MODE_UNDEFINED``: libc never stores a value; ``errno`` macro uses get link-time failure,
- ``LIBC_ERRNO_MODE_THREAD_LOCAL``: libc maintains per-thread state (requires C++ ``thread_local`` support for libc implementation code),
- - ``LIBC_ERRNO_MODE_SHARED``: libc maintains an ``atomic_int`` used by all threads, contrary to standard C semantics (requires use of atomics in libc implementation code, may produce libcalls an embedder must supply),
+ - ``LIBC_ERRNO_MODE_SHARED``: libc maintains shared state used by all threads, contrary to standard C semantics unless always single-threaded; nothing prevents data races,
- ``LIBC_ERRNO_MODE_EXTERNAL``: embedder must define ``int *__llvm_libc_errno(void);`` C function,
- ``LIBC_ERRNO_MODE_SYSTEM``: in overlay mode, system ``<errno.h>`` ``errno`` macro is used directly; in fullbuild mode, effectively the same as ``LIBC_ERRNO_MODE_EXTERNAL``.
* **"malloc" options**
diff --git a/libc/src/errno/errno.h b/libc/src/errno/errno.h
new file mode 100644
index 0000000000000..a2df93513ec62
--- /dev/null
+++ b/libc/src/errno/errno.h
@@ -0,0 +1,14 @@
+//===-- Implementation header for errno -------------------------*- 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_ERRNO_ERRNO_H
+#define LLVM_LIBC_SRC_ERRNO_ERRNO_H
+
+extern "C" int *__llvm_libc_errno();
+
+#endif // LLVM_LIBC_SRC_ERRNO_ERRNO_H
diff --git a/libc/src/errno/libc_errno.cpp b/libc/src/errno/libc_errno.cpp
index ccf5a7f136227..66d5d3f2463a5 100644
--- a/libc/src/errno/libc_errno.cpp
+++ b/libc/src/errno/libc_errno.cpp
@@ -7,7 +7,7 @@
//===----------------------------------------------------------------------===//
#include "libc_errno.h"
-#include "src/__support/CPP/atomic.h"
+#include "src/errno/errno.h"
#define LIBC_ERRNO_MODE_UNDEFINED 1
#define LIBC_ERRNO_MODE_THREAD_LOCAL 2
@@ -56,30 +56,24 @@ extern "C" {
int *__llvm_libc_errno() { return &thread_errno; }
}
-void Errno::operator=(int a) { __libc_errno = a; }
-Errno::operator int() { return __libc_errno; }
+void Errno::operator=(int a) { thread_errno = a; }
+Errno::operator int() { return thread_errno; }
-#elif LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_GLOBAL
+#elif LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_SHARED
namespace {
-cpp::Atomic<int> global_errno;
+int shared_errno;
}
extern "C" {
-int *__llvm_libc_errno() { return &global_errno; }
+int *__llvm_libc_errno() { return &shared_errno; }
}
-void Errno::operator=(int a) {
- __libc_errno.store(a, cpp::MemoryOrder::RELAXED);
-}
-Errno::operator int() { return __libc_errno.load(cpp::MemoryOrder::RELAXED); }
+void Errno::operator=(int a) { shared_errno = a; }
+Errno::operator int() { return shared_errno; }
#elif LIBC_ERRNO_MODE == LIBC_ERRNO_MODE_EXTERNAL
-extern "C" {
-int *__llvm_libc_errno();
-}
-
void Errno::operator=(int a) { *__llvm_libc_errno() = a; }
Errno::operator int() { return *__llvm_libc_errno(); }
>From 1ff0acc44a2443ff87ae2decad282b0a604ca5f6 Mon Sep 17 00:00:00 2001
From: Petr Hosek <phosek at google.com>
Date: Thu, 11 Jul 2024 21:15:07 -0700
Subject: [PATCH 9/9] Address review feedback
---
libc/docs/configure.rst | 7 +------
libc/src/errno/CMakeLists.txt | 1 +
libc/src/errno/libc_errno.cpp | 8 ++++++++
3 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/libc/docs/configure.rst b/libc/docs/configure.rst
index 271c51911cc93..24ef2ef189ffd 100644
--- a/libc/docs/configure.rst
+++ b/libc/docs/configure.rst
@@ -29,12 +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_UNDEFINED``: libc never stores a value; ``errno`` macro uses get link-time failure,
- - ``LIBC_ERRNO_MODE_THREAD_LOCAL``: libc maintains per-thread state (requires C++ ``thread_local`` support for libc implementation code),
- - ``LIBC_ERRNO_MODE_SHARED``: libc maintains shared state used by all threads, contrary to standard C semantics unless always single-threaded; nothing prevents data races,
- - ``LIBC_ERRNO_MODE_EXTERNAL``: embedder must define ``int *__llvm_libc_errno(void);`` C function,
- - ``LIBC_ERRNO_MODE_SYSTEM``: in overlay mode, system ``<errno.h>`` ``errno`` macro is used directly; in fullbuild mode, effectively the same as ``LIBC_ERRNO_MODE_EXTERNAL``.
+ - ``LIBC_CONF_ERRNO_MODE``: The implementation used for errno, acceptable values are LIBC_ERRNO_MODE_UNDEFINED, LIBC_ERRNO_MODE_THREAD_LOCAL, LIBC_ERRNO_MODE_SHARED, LIBC_ERRNO_MODE_EXTERNAL, 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/src/errno/CMakeLists.txt b/libc/src/errno/CMakeLists.txt
index 1d78a5eedff96..b05fd4e31ff68 100644
--- a/libc/src/errno/CMakeLists.txt
+++ b/libc/src/errno/CMakeLists.txt
@@ -18,6 +18,7 @@ add_entrypoint_object(
SRCS
libc_errno.cpp
HDRS
+ errno.h
libc_errno.h # Include this
COMPILE_OPTIONS
${full_build_flag}
diff --git a/libc/src/errno/libc_errno.cpp b/libc/src/errno/libc_errno.cpp
index 4581c3a280064..f7bd3a3b9eb4b 100644
--- a/libc/src/errno/libc_errno.cpp
+++ b/libc/src/errno/libc_errno.cpp
@@ -10,10 +10,18 @@
#include "src/errno/errno.h"
#include "src/__support/macros/config.h"
+// libc never stores a value; `errno` macro uses get link-time failure.
#define LIBC_ERRNO_MODE_UNDEFINED 1
+// libc maintains per-thread state (requires C++ `thread_local` support).
#define LIBC_ERRNO_MODE_THREAD_LOCAL 2
+// libc maintains shared state used by all threads, contrary to standard C
+// semantics unless always single-threaded; nothing prevents data races.
#define LIBC_ERRNO_MODE_SHARED 3
+// libc doesn't maintain any internal state, instead the embedder must define
+// `int *__llvm_libc_errno(void);` C function.
#define LIBC_ERRNO_MODE_EXTERNAL 4
+// libc uses system `<errno.h>` `errno` macro directly in the overlay mode; in
+// fullbuild mode, effectively the same as `LIBC_ERRNO_MODE_EXTERNAL`.
#define LIBC_ERRNO_MODE_SYSTEM 5
#ifndef LIBC_ERRNO_MODE
More information about the libc-commits
mailing list