[libc-commits] [libc] [llvm] [libc] added at_quick_exit function (PR #94289)
via libc-commits
libc-commits at lists.llvm.org
Mon Jun 3 15:36:41 PDT 2024
https://github.com/aaryanshukla created https://github.com/llvm/llvm-project/pull/94289
- **[libc] implement quick exit function**
- **addressed comments regarding quick exit function**
- **addressing comments to quick exit function**
- **fixed no_stack_proctector brackets and noreturn**
- **added internal in front of exit for quick_exit**
- **updated build.BAZEL**
- **changed quick_exit to exit in cmakefiles in gpu and baremetal**
- **[libc] added at_quick_exit function**
>From 1bfb3baf6712864e6bbe604082c3a1b389441013 Mon Sep 17 00:00:00 2001
From: Aaryan Shukla <aaryanshukla at google.com>
Date: Tue, 28 May 2024 22:40:16 +0000
Subject: [PATCH 1/8] [libc] implement quick exit function
Implementing the quick exit function.
---
libc/config/linux/x86_64/entrypoints.txt | 1 +
libc/spec/stdc.td | 2 ++
.../baremetal/{quick_exit.cpp => exit.cpp} | 8 ++++--
.../__support/OSUtil/{quick_exit.h => exit.h} | 9 ++++---
.../OSUtil/gpu/{quick_exit.cpp => exit.cpp} | 7 ++++--
.../src/__support/OSUtil/linux/CMakeLists.txt | 2 +-
.../OSUtil/linux/{quick_exit.cpp => exit.cpp} | 7 +++++-
libc/src/__support/libc_assert.h | 4 +--
libc/src/stdlib/CMakeLists.txt | 16 ++++++++++--
libc/src/stdlib/_Exit.cpp | 4 +--
libc/src/stdlib/exit.cpp | 4 +--
libc/src/stdlib/quick_exit.cpp | 25 +++++++++++++++++++
libc/src/stdlib/quick_exit.h | 20 +++++++++++++++
libc/src/unistd/_exit.cpp | 4 +--
libc/test/IntegrationTest/test.h | 10 ++++----
libc/test/src/stdlib/CMakeLists.txt | 17 +++++++++++++
libc/test/src/stdlib/quick_exit_test.cpp | 17 +++++++++++++
libc/utils/HdrGen/Main.cpp | 1 +
18 files changed, 134 insertions(+), 24 deletions(-)
rename libc/src/__support/OSUtil/baremetal/{quick_exit.cpp => exit.cpp} (80%)
rename libc/src/__support/OSUtil/{quick_exit.h => exit.h} (75%)
rename libc/src/__support/OSUtil/gpu/{quick_exit.cpp => exit.cpp} (89%)
rename libc/src/__support/OSUtil/linux/{quick_exit.cpp => exit.cpp} (95%)
create mode 100644 libc/src/stdlib/quick_exit.cpp
create mode 100644 libc/src/stdlib/quick_exit.h
create mode 100644 libc/test/src/stdlib/quick_exit_test.cpp
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 5e3ddd34fb4dc..b6ead64e208c7 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -730,6 +730,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.stdlib.abort
libc.src.stdlib.atexit
libc.src.stdlib.exit
+ libc.src.stdlib.quick_exit
libc.src.stdlib.getenv
# signal.h entrypoints
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index eb67c9b0b009b..20a95b6aae385 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -1071,6 +1071,8 @@ def StdC : StandardSpec<"stdc"> {
FunctionSpec<"_Exit", RetValSpec<NoReturn>, [ArgSpec<IntType>]>,
FunctionSpec<"exit", RetValSpec<NoReturn>, [ArgSpec<IntType>]>,
FunctionSpec<"atexit", RetValSpec<IntType>, [ArgSpec<AtexitHandlerT>]>,
+ FunctionSpec<"quick_exit", RetValSpec<NoReturn>, [ArgSpec<IntType>]>,
+
]
>;
diff --git a/libc/src/__support/OSUtil/baremetal/quick_exit.cpp b/libc/src/__support/OSUtil/baremetal/exit.cpp
similarity index 80%
rename from libc/src/__support/OSUtil/baremetal/quick_exit.cpp
rename to libc/src/__support/OSUtil/baremetal/exit.cpp
index 5b6fcf42341eb..c77e21ae6602d 100644
--- a/libc/src/__support/OSUtil/baremetal/quick_exit.cpp
+++ b/libc/src/__support/OSUtil/baremetal/exit.cpp
@@ -6,13 +6,17 @@
//
//===----------------------------------------------------------------------===//
-#include "src/__support/OSUtil/quick_exit.h"
+#include "src/__support/OSUtil/exit.h"
// This is intended to be provided by the vendor.
extern "C" [[noreturn]] void __llvm_libc_quick_exit(int status);
namespace LIBC_NAMESPACE {
+namespace internal {
-[[noreturn]] void quick_exit(int status) { __llvm_libc_quick_exit(status); }
+[[noreturn]] void exit(int status) { __llvm_libc_quick_exit(status); }
+
+
+}
} // namespace LIBC_NAMESPACE
diff --git a/libc/src/__support/OSUtil/quick_exit.h b/libc/src/__support/OSUtil/exit.h
similarity index 75%
rename from libc/src/__support/OSUtil/quick_exit.h
rename to libc/src/__support/OSUtil/exit.h
index e445917059c3e..5bd967ecf8777 100644
--- a/libc/src/__support/OSUtil/quick_exit.h
+++ b/libc/src/__support/OSUtil/exit.h
@@ -6,12 +6,15 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_QUICK_EXIT_H
-#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_QUICK_EXIT_H
+#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_EXIT_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_EXIT_H
namespace LIBC_NAMESPACE {
+namespace internal {
-[[noreturn]] void quick_exit(int status);
+[[noreturn]] void exit(int status);
+
+}
}
diff --git a/libc/src/__support/OSUtil/gpu/quick_exit.cpp b/libc/src/__support/OSUtil/gpu/exit.cpp
similarity index 89%
rename from libc/src/__support/OSUtil/gpu/quick_exit.cpp
rename to libc/src/__support/OSUtil/gpu/exit.cpp
index af4795905e786..e9744a69650a4 100644
--- a/libc/src/__support/OSUtil/gpu/quick_exit.cpp
+++ b/libc/src/__support/OSUtil/gpu/exit.cpp
@@ -6,14 +6,15 @@
//
//===----------------------------------------------------------------------===//
-#include "src/__support/OSUtil/quick_exit.h"
+#include "src/__support/OSUtil/exit.h"
#include "src/__support/RPC/rpc_client.h"
#include "src/__support/macros/properties/architectures.h"
namespace LIBC_NAMESPACE {
+namespace internal {
-[[noreturn]] void quick_exit(int status) {
+[[noreturn]] void exit(int status) {
// We want to first make sure the server is listening before we exit.
rpc::Client::Port port = rpc::client.open<RPC_EXIT>();
port.send_and_recv([](rpc::Buffer *) {}, [](rpc::Buffer *) {});
@@ -25,4 +26,6 @@ namespace LIBC_NAMESPACE {
gpu::end_program();
}
+
+}
} // namespace LIBC_NAMESPACE
diff --git a/libc/src/__support/OSUtil/linux/CMakeLists.txt b/libc/src/__support/OSUtil/linux/CMakeLists.txt
index 239d115704927..9a55232d532fe 100644
--- a/libc/src/__support/OSUtil/linux/CMakeLists.txt
+++ b/libc/src/__support/OSUtil/linux/CMakeLists.txt
@@ -7,7 +7,7 @@ add_subdirectory(${LIBC_TARGET_ARCHITECTURE})
add_object_library(
linux_util
SRCS
- quick_exit.cpp
+ exit.cpp
HDRS
io.h
syscall.h
diff --git a/libc/src/__support/OSUtil/linux/quick_exit.cpp b/libc/src/__support/OSUtil/linux/exit.cpp
similarity index 95%
rename from libc/src/__support/OSUtil/linux/quick_exit.cpp
rename to libc/src/__support/OSUtil/linux/exit.cpp
index 51b3231d389f2..8dccfc22f3799 100644
--- a/libc/src/__support/OSUtil/linux/quick_exit.cpp
+++ b/libc/src/__support/OSUtil/linux/exit.cpp
@@ -11,6 +11,8 @@
#include <sys/syscall.h> // For syscall numbers.
namespace LIBC_NAMESPACE {
+namespace internal {
+
// mark as no_stack_protector for x86 since TLS can be torn down before calling
// quick_exit so that the stack protector canary cannot be loaded.
@@ -18,11 +20,14 @@ namespace LIBC_NAMESPACE {
__attribute__((no_stack_protector))
#endif
__attribute__((noreturn)) void
-quick_exit(int status) {
+exit(int status) {
for (;;) {
LIBC_NAMESPACE::syscall_impl<long>(SYS_exit_group, status);
LIBC_NAMESPACE::syscall_impl<long>(SYS_exit, status);
}
}
+
+}
+
} // namespace LIBC_NAMESPACE
diff --git a/libc/src/__support/libc_assert.h b/libc/src/__support/libc_assert.h
index 61f075435b552..ca04e7024964c 100644
--- a/libc/src/__support/libc_assert.h
+++ b/libc/src/__support/libc_assert.h
@@ -21,7 +21,7 @@
#else // Not LIBC_COPT_USE_C_ASSERT
#include "src/__support/OSUtil/io.h"
-#include "src/__support/OSUtil/quick_exit.h"
+#include "src/__support/OSUtil/exit.h"
#include "src/__support/integer_to_string.h"
#include "src/__support/macros/attributes.h" // For LIBC_INLINE
@@ -76,7 +76,7 @@ LIBC_INLINE void report_assertion_failure(const char *assertion,
"' in function: '"); \
LIBC_NAMESPACE::write_to_stderr(__PRETTY_FUNCTION__); \
LIBC_NAMESPACE::write_to_stderr("'\n"); \
- LIBC_NAMESPACE::quick_exit(0xFF); \
+ LIBC_NAMESPACE::internal::exit(0xFF); \
} \
} while (false)
#endif // NDEBUG
diff --git a/libc/src/stdlib/CMakeLists.txt b/libc/src/stdlib/CMakeLists.txt
index 9b76a6a0f8575..ef74ca4fd0e70 100644
--- a/libc/src/stdlib/CMakeLists.txt
+++ b/libc/src/stdlib/CMakeLists.txt
@@ -2,6 +2,7 @@ add_entrypoint_object(
atoi
SRCS
atoi.cpp
+ quick_exit.cpp
HDRS
atoi.h
DEPENDS
@@ -13,8 +14,7 @@ add_entrypoint_object(
atof
SRCS
atof.cpp
- HDRS
- atof.h
+ atof.h
DEPENDS
libc.src.errno.errno
libc.src.__support.str_to_float
@@ -432,6 +432,18 @@ add_entrypoint_object(
._Exit
.atexit
libc.src.__support.OSUtil.osutil
+
+)
+
+add_entrypoint_object(
+ quick_exit
+ SRCS
+ quick_exit.cpp
+ HDRS
+ quick_exit.h
+ DEPENDS
+ libc.src.errno.errno
+
)
add_entrypoint_object(
diff --git a/libc/src/stdlib/_Exit.cpp b/libc/src/stdlib/_Exit.cpp
index 233af20973924..03a766261014e 100644
--- a/libc/src/stdlib/_Exit.cpp
+++ b/libc/src/stdlib/_Exit.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "src/__support/OSUtil/quick_exit.h"
+#include "src/__support/OSUtil/exit.h"
#include "src/__support/common.h"
#include "src/stdlib/_Exit.h"
@@ -14,7 +14,7 @@
namespace LIBC_NAMESPACE {
[[noreturn]] LLVM_LIBC_FUNCTION(void, _Exit, (int status)) {
- quick_exit(status);
+ internal::exit(status);
}
} // namespace LIBC_NAMESPACE
diff --git a/libc/src/stdlib/exit.cpp b/libc/src/stdlib/exit.cpp
index ba87bffaeb541..1f7ccbb556607 100644
--- a/libc/src/stdlib/exit.cpp
+++ b/libc/src/stdlib/exit.cpp
@@ -7,7 +7,7 @@
//===----------------------------------------------------------------------===//
#include "src/stdlib/exit.h"
-#include "src/__support/OSUtil/quick_exit.h"
+#include "src/__support/OSUtil/exit.h"
#include "src/__support/common.h"
extern "C" void __cxa_finalize(void *);
@@ -16,7 +16,7 @@ namespace LIBC_NAMESPACE {
[[noreturn]] LLVM_LIBC_FUNCTION(void, exit, (int status)) {
__cxa_finalize(nullptr);
- quick_exit(status);
+ internal::exit(status);
}
} // namespace LIBC_NAMESPACE
diff --git a/libc/src/stdlib/quick_exit.cpp b/libc/src/stdlib/quick_exit.cpp
new file mode 100644
index 0000000000000..5b14683a0d956
--- /dev/null
+++ b/libc/src/stdlib/quick_exit.cpp
@@ -0,0 +1,25 @@
+//===-- Implementation of quick_exit --------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/stdlib/quick_exit.h"
+#include "src/__support/OSUtil/exit.h"
+#include "src/__support/common.h"
+
+//extern "C" void __cxa_finalize(void *);
+
+namespace LIBC_NAMESPACE {
+
+[[noreturn]] LLVM_LIBC_FUNCTION(void, quick_exit, (int status)) {
+ //__cxa_finalize(nullptr);
+ exit(status);
+}
+
+
+}
+ // namespace LIBC_NAMESPACE
+
diff --git a/libc/src/stdlib/quick_exit.h b/libc/src/stdlib/quick_exit.h
new file mode 100644
index 0000000000000..1ebf689e1868e
--- /dev/null
+++ b/libc/src/stdlib/quick_exit.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for quick_exit -------------------*- 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_STDLIB_QUICK_EXIT_H
+#define LLVM_LIBC_SRC_STDLIB_QUICK_EXIT_H
+
+#include <stdlib.h>
+
+namespace LIBC_NAMESPACE {
+
+[[noreturn]] void quick_exit(int status);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_STDLIB_QUICK_EXIT_H
diff --git a/libc/src/unistd/_exit.cpp b/libc/src/unistd/_exit.cpp
index 6fbf3a51d42f4..4b652a2c13fd1 100644
--- a/libc/src/unistd/_exit.cpp
+++ b/libc/src/unistd/_exit.cpp
@@ -7,13 +7,13 @@
//===----------------------------------------------------------------------===//
#include "src/unistd/_exit.h"
-#include "src/__support/OSUtil/quick_exit.h"
+#include "src/__support/OSUtil/exit.h"
#include "src/__support/common.h"
namespace LIBC_NAMESPACE {
[[noreturn]] LLVM_LIBC_FUNCTION(void, _exit, (int status)) {
- quick_exit(status);
+ internal::exit(status);
}
} // namespace LIBC_NAMESPACE
diff --git a/libc/test/IntegrationTest/test.h b/libc/test/IntegrationTest/test.h
index 64906ef179391..14e6f22f0ee67 100644
--- a/libc/test/IntegrationTest/test.h
+++ b/libc/test/IntegrationTest/test.h
@@ -10,7 +10,7 @@
#define LLVM_LIBC_UTILS_INTEGRATION_TEST_TEST_H
#include "src/__support/OSUtil/io.h"
-#include "src/__support/OSUtil/quick_exit.h"
+#include "src/__support/OSUtil/exit.h"
#define __AS_STRING(val) #val
#define __CHECK_TRUE(file, line, val, should_exit) \
@@ -18,7 +18,7 @@
LIBC_NAMESPACE::write_to_stderr(file ":" __AS_STRING( \
line) ": Expected '" #val "' to be true, but is false\n"); \
if (should_exit) \
- LIBC_NAMESPACE::quick_exit(127); \
+ LIBC_NAMESPACE::internal::exit(127); \
}
#define __CHECK_FALSE(file, line, val, should_exit) \
@@ -26,7 +26,7 @@
LIBC_NAMESPACE::write_to_stderr(file ":" __AS_STRING( \
line) ": Expected '" #val "' to be false, but is true\n"); \
if (should_exit) \
- LIBC_NAMESPACE::quick_exit(127); \
+ LIBC_NAMESPACE::internal::exit(127); \
}
#define __CHECK_EQ(file, line, val1, val2, should_exit) \
@@ -34,7 +34,7 @@
LIBC_NAMESPACE::write_to_stderr(file ":" __AS_STRING( \
line) ": Expected '" #val1 "' to be equal to '" #val2 "'\n"); \
if (should_exit) \
- LIBC_NAMESPACE::quick_exit(127); \
+ LIBC_NAMESPACE::internal::exit(127); \
}
#define __CHECK_NE(file, line, val1, val2, should_exit) \
@@ -42,7 +42,7 @@
LIBC_NAMESPACE::write_to_stderr(file ":" __AS_STRING( \
line) ": Expected '" #val1 "' to not be equal to '" #val2 "'\n"); \
if (should_exit) \
- LIBC_NAMESPACE::quick_exit(127); \
+ LIBC_NAMESPACE::internal::exit(127); \
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/libc/test/src/stdlib/CMakeLists.txt b/libc/test/src/stdlib/CMakeLists.txt
index 28c5b566cc477..e07e8b651322e 100644
--- a/libc/test/src/stdlib/CMakeLists.txt
+++ b/libc/test/src/stdlib/CMakeLists.txt
@@ -324,6 +324,23 @@ add_libc_test(
libc.src.stdlib.srand
)
+add_libc_test(
+ quick_exit_test
+ # The EXPECT_EXITS test is only availible for unit tests.
+ UNIT_TEST_ONLY
+ SUITE
+ libc-stdlib-tests
+ SRCS
+ quick_exit_test.cpp
+ DEPENDS
+ libc.include.stdlib
+ libc.src.stdlib._Exit
+ libc.src.stdlib.quick_exit
+ libc.src.stdlib.atexit
+ libc.src.__support.CPP.array
+ libc.src.__support.CPP.utility
+ )
+
if(LLVM_LIBC_FULL_BUILD)
add_libc_test(
diff --git a/libc/test/src/stdlib/quick_exit_test.cpp b/libc/test/src/stdlib/quick_exit_test.cpp
new file mode 100644
index 0000000000000..8ed878a11575b
--- /dev/null
+++ b/libc/test/src/stdlib/quick_exit_test.cpp
@@ -0,0 +1,17 @@
+//===-- Unittests for quick_exit ------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/stdlib/quick_exit.h"
+#include "test/UnitTest/Test.h"
+
+#include <stdlib.h>
+
+TEST(LlvmLibcStdlib, quick_exit) {
+ EXPECT_EXITS([] { LIBC_NAMESPACE::quick_exit(1); }, 1);
+ EXPECT_EXITS([] { LIBC_NAMESPACE::quick_exit(65); }, 65);
+}
diff --git a/libc/utils/HdrGen/Main.cpp b/libc/utils/HdrGen/Main.cpp
index d3418f206b10e..92269dd70ae19 100644
--- a/libc/utils/HdrGen/Main.cpp
+++ b/libc/utils/HdrGen/Main.cpp
@@ -65,3 +65,4 @@ int main(int argc, char *argv[]) {
llvm::cl::ParseCommandLineOptions(argc, argv);
return TableGenMain(argv[0], &llvm_libc::HeaderGeneratorMain);
}
+
>From 60298a6cbbc8d07390b6de409ee584b85b44ff65 Mon Sep 17 00:00:00 2001
From: Aaryan Shukla <aaryanshukla at google.com>
Date: Wed, 29 May 2024 21:47:26 +0000
Subject: [PATCH 2/8] addressed comments regarding quick exit function
fixed line spacing, max text per line, and unnecesary code that was
moved/deleted.
---
libc/spec/stdc.td | 1 -
libc/src/__support/OSUtil/baremetal/exit.cpp | 5 ++---
libc/src/__support/OSUtil/exit.h | 2 +-
libc/src/__support/OSUtil/linux/exit.cpp | 10 ++--------
libc/src/__support/libc_assert.h | 5 +++--
libc/src/stdlib/CMakeLists.txt | 6 +++---
libc/src/stdlib/quick_exit.cpp | 2 +-
libc/test/src/stdlib/CMakeLists.txt | 4 ----
libc/utils/HdrGen/Main.cpp | 1 -
9 files changed, 12 insertions(+), 24 deletions(-)
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index 20a95b6aae385..9ec9ee7521c7e 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -1072,7 +1072,6 @@ def StdC : StandardSpec<"stdc"> {
FunctionSpec<"exit", RetValSpec<NoReturn>, [ArgSpec<IntType>]>,
FunctionSpec<"atexit", RetValSpec<IntType>, [ArgSpec<AtexitHandlerT>]>,
FunctionSpec<"quick_exit", RetValSpec<NoReturn>, [ArgSpec<IntType>]>,
-
]
>;
diff --git a/libc/src/__support/OSUtil/baremetal/exit.cpp b/libc/src/__support/OSUtil/baremetal/exit.cpp
index c77e21ae6602d..31d2c979df0b2 100644
--- a/libc/src/__support/OSUtil/baremetal/exit.cpp
+++ b/libc/src/__support/OSUtil/baremetal/exit.cpp
@@ -1,4 +1,4 @@
-//===----- Baremetal implementation of a quick exit function ----*- C++ -*-===//
+//===----- Baremetal implementation of a exit function ----*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -16,7 +16,6 @@ namespace internal {
[[noreturn]] void exit(int status) { __llvm_libc_quick_exit(status); }
-
-}
+} // namespace internal
} // namespace LIBC_NAMESPACE
diff --git a/libc/src/__support/OSUtil/exit.h b/libc/src/__support/OSUtil/exit.h
index 5bd967ecf8777..694d3c92ca258 100644
--- a/libc/src/__support/OSUtil/exit.h
+++ b/libc/src/__support/OSUtil/exit.h
@@ -16,6 +16,6 @@ namespace internal {
}
-}
+} // namespace LIBC_NAMESPACE
#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_QUICK_EXIT_H
diff --git a/libc/src/__support/OSUtil/linux/exit.cpp b/libc/src/__support/OSUtil/linux/exit.cpp
index 8dccfc22f3799..85e0b825ee5ef 100644
--- a/libc/src/__support/OSUtil/linux/exit.cpp
+++ b/libc/src/__support/OSUtil/linux/exit.cpp
@@ -10,9 +10,7 @@
#include "syscall.h" // For internal syscall function.
#include <sys/syscall.h> // For syscall numbers.
-namespace LIBC_NAMESPACE {
-namespace internal {
-
+namespace LIBC_NAMESPACE::internal {
// mark as no_stack_protector for x86 since TLS can be torn down before calling
// quick_exit so that the stack protector canary cannot be loaded.
@@ -26,8 +24,4 @@ exit(int status) {
LIBC_NAMESPACE::syscall_impl<long>(SYS_exit, status);
}
}
-
-
-}
-
-} // namespace LIBC_NAMESPACE
+} // namespace LIBC_NAMESPACE::internal
diff --git a/libc/src/__support/libc_assert.h b/libc/src/__support/libc_assert.h
index ca04e7024964c..438ee3b3e00e0 100644
--- a/libc/src/__support/libc_assert.h
+++ b/libc/src/__support/libc_assert.h
@@ -20,8 +20,8 @@
#else // Not LIBC_COPT_USE_C_ASSERT
-#include "src/__support/OSUtil/io.h"
#include "src/__support/OSUtil/exit.h"
+#include "src/__support/OSUtil/io.h"
#include "src/__support/integer_to_string.h"
#include "src/__support/macros/attributes.h" // For LIBC_INLINE
@@ -56,6 +56,7 @@ LIBC_INLINE void report_assertion_failure(const char *assertion,
// __builtin_trap as it could potentially be implemented using illegal
// instructions which can be very misleading when debugging.
#ifdef NDEBUG
+
#define LIBC_ASSERT(COND) \
do { \
} while (false)
@@ -76,7 +77,7 @@ LIBC_INLINE void report_assertion_failure(const char *assertion,
"' in function: '"); \
LIBC_NAMESPACE::write_to_stderr(__PRETTY_FUNCTION__); \
LIBC_NAMESPACE::write_to_stderr("'\n"); \
- LIBC_NAMESPACE::internal::exit(0xFF); \
+ LIBC_NAMESPACE::internal::exit(0xFF); \
} \
} while (false)
#endif // NDEBUG
diff --git a/libc/src/stdlib/CMakeLists.txt b/libc/src/stdlib/CMakeLists.txt
index ef74ca4fd0e70..7a8db59f691da 100644
--- a/libc/src/stdlib/CMakeLists.txt
+++ b/libc/src/stdlib/CMakeLists.txt
@@ -2,7 +2,6 @@ add_entrypoint_object(
atoi
SRCS
atoi.cpp
- quick_exit.cpp
HDRS
atoi.h
DEPENDS
@@ -14,7 +13,8 @@ add_entrypoint_object(
atof
SRCS
atof.cpp
- atof.h
+ HDRS
+ atof.h
DEPENDS
libc.src.errno.errno
libc.src.__support.str_to_float
@@ -443,7 +443,7 @@ add_entrypoint_object(
quick_exit.h
DEPENDS
libc.src.errno.errno
-
+ libc.src.__support.OSUtil.osutil
)
add_entrypoint_object(
diff --git a/libc/src/stdlib/quick_exit.cpp b/libc/src/stdlib/quick_exit.cpp
index 5b14683a0d956..911e5e68136f0 100644
--- a/libc/src/stdlib/quick_exit.cpp
+++ b/libc/src/stdlib/quick_exit.cpp
@@ -1,4 +1,4 @@
-//===-- Implementation of quick_exit --------------------------------------------===//
+//===-- Implementation of quick_exit --------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
diff --git a/libc/test/src/stdlib/CMakeLists.txt b/libc/test/src/stdlib/CMakeLists.txt
index e07e8b651322e..3eedd6d678c0b 100644
--- a/libc/test/src/stdlib/CMakeLists.txt
+++ b/libc/test/src/stdlib/CMakeLists.txt
@@ -334,11 +334,7 @@ add_libc_test(
quick_exit_test.cpp
DEPENDS
libc.include.stdlib
- libc.src.stdlib._Exit
libc.src.stdlib.quick_exit
- libc.src.stdlib.atexit
- libc.src.__support.CPP.array
- libc.src.__support.CPP.utility
)
if(LLVM_LIBC_FULL_BUILD)
diff --git a/libc/utils/HdrGen/Main.cpp b/libc/utils/HdrGen/Main.cpp
index 92269dd70ae19..d3418f206b10e 100644
--- a/libc/utils/HdrGen/Main.cpp
+++ b/libc/utils/HdrGen/Main.cpp
@@ -65,4 +65,3 @@ int main(int argc, char *argv[]) {
llvm::cl::ParseCommandLineOptions(argc, argv);
return TableGenMain(argv[0], &llvm_libc::HeaderGeneratorMain);
}
-
>From c69c2ba6d235c07d496236db5ba34f8c6ef9d997 Mon Sep 17 00:00:00 2001
From: Aaryan Shukla <aaryanshukla at google.com>
Date: Wed, 29 May 2024 22:25:26 +0000
Subject: [PATCH 3/8] addressing comments to quick exit function
- some files had lines go over 80 pieces of text
- added missing dependencies on quick exit
- reverted some unnecesary changes made to the make files
- fixed the order of include files to met clang formatting rules.
---
libc/src/__support/OSUtil/gpu/exit.cpp | 3 +--
libc/src/stdlib/quick_exit.cpp | 9 +++------
libc/test/IntegrationTest/test.h | 15 ++++++++-------
3 files changed, 12 insertions(+), 15 deletions(-)
diff --git a/libc/src/__support/OSUtil/gpu/exit.cpp b/libc/src/__support/OSUtil/gpu/exit.cpp
index e9744a69650a4..c99bb77c16e85 100644
--- a/libc/src/__support/OSUtil/gpu/exit.cpp
+++ b/libc/src/__support/OSUtil/gpu/exit.cpp
@@ -26,6 +26,5 @@ namespace internal {
gpu::end_program();
}
-
-}
+} // namespace internal
} // namespace LIBC_NAMESPACE
diff --git a/libc/src/stdlib/quick_exit.cpp b/libc/src/stdlib/quick_exit.cpp
index 911e5e68136f0..14f7f78169033 100644
--- a/libc/src/stdlib/quick_exit.cpp
+++ b/libc/src/stdlib/quick_exit.cpp
@@ -10,8 +10,7 @@
#include "src/__support/OSUtil/exit.h"
#include "src/__support/common.h"
-//extern "C" void __cxa_finalize(void *);
-
+// extern "C" void __cxa_finalize(void *);
namespace LIBC_NAMESPACE {
[[noreturn]] LLVM_LIBC_FUNCTION(void, quick_exit, (int status)) {
@@ -19,7 +18,5 @@ namespace LIBC_NAMESPACE {
exit(status);
}
-
-}
- // namespace LIBC_NAMESPACE
-
+} // namespace LIBC_NAMESPACE
+ // namespace LIBC_NAMESPACE
diff --git a/libc/test/IntegrationTest/test.h b/libc/test/IntegrationTest/test.h
index 14e6f22f0ee67..2b28b97340659 100644
--- a/libc/test/IntegrationTest/test.h
+++ b/libc/test/IntegrationTest/test.h
@@ -9,24 +9,25 @@
#ifndef LLVM_LIBC_UTILS_INTEGRATION_TEST_TEST_H
#define LLVM_LIBC_UTILS_INTEGRATION_TEST_TEST_H
-#include "src/__support/OSUtil/io.h"
#include "src/__support/OSUtil/exit.h"
+#include "src/__support/OSUtil/io.h"
#define __AS_STRING(val) #val
#define __CHECK_TRUE(file, line, val, should_exit) \
if (!(val)) { \
LIBC_NAMESPACE::write_to_stderr(file ":" __AS_STRING( \
line) ": Expected '" #val "' to be true, but is false\n"); \
- if (should_exit) \
- LIBC_NAMESPACE::internal::exit(127); \
- }
+ if (should_exit)
+
+LIBC_NAMESPACE::internal::exit(127);
+}
#define __CHECK_FALSE(file, line, val, should_exit) \
if (val) { \
LIBC_NAMESPACE::write_to_stderr(file ":" __AS_STRING( \
line) ": Expected '" #val "' to be false, but is true\n"); \
if (should_exit) \
- LIBC_NAMESPACE::internal::exit(127); \
+ LIBC_NAMESPACE::internal::exit(127); \
}
#define __CHECK_EQ(file, line, val1, val2, should_exit) \
@@ -34,7 +35,7 @@
LIBC_NAMESPACE::write_to_stderr(file ":" __AS_STRING( \
line) ": Expected '" #val1 "' to be equal to '" #val2 "'\n"); \
if (should_exit) \
- LIBC_NAMESPACE::internal::exit(127); \
+ LIBC_NAMESPACE::internal::exit(127); \
}
#define __CHECK_NE(file, line, val1, val2, should_exit) \
@@ -42,7 +43,7 @@
LIBC_NAMESPACE::write_to_stderr(file ":" __AS_STRING( \
line) ": Expected '" #val1 "' to not be equal to '" #val2 "'\n"); \
if (should_exit) \
- LIBC_NAMESPACE::internal::exit(127); \
+ LIBC_NAMESPACE::internal::exit(127); \
}
////////////////////////////////////////////////////////////////////////////////
>From 4190cb0f8b8e665c11cab2f6a1d8b2cb78ab5287 Mon Sep 17 00:00:00 2001
From: Aaryan Shukla <aaryanshukla at google.com>
Date: Thu, 30 May 2024 20:53:43 +0000
Subject: [PATCH 4/8] fixed no_stack_proctector brackets and noreturn,
including formatting
added no_stack_proctector and noreturn brackets.
removed unnecesary stdlib.h files.
fixed line formatting for test.h files.
---
libc/src/__support/OSUtil/baremetal/exit.cpp | 2 +-
libc/src/__support/OSUtil/linux/exit.cpp | 5 ++---
libc/src/stdlib/CMakeLists.txt | 1 -
libc/src/stdlib/quick_exit.cpp | 1 -
libc/src/stdlib/quick_exit.h | 3 ---
libc/test/IntegrationTest/test.h | 7 +++----
libc/test/src/stdlib/quick_exit_test.cpp | 2 --
7 files changed, 6 insertions(+), 15 deletions(-)
diff --git a/libc/src/__support/OSUtil/baremetal/exit.cpp b/libc/src/__support/OSUtil/baremetal/exit.cpp
index 31d2c979df0b2..c9a166fedf3c1 100644
--- a/libc/src/__support/OSUtil/baremetal/exit.cpp
+++ b/libc/src/__support/OSUtil/baremetal/exit.cpp
@@ -1,4 +1,4 @@
-//===----- Baremetal implementation of a exit function ----*- C++ -*-===//
+//===----- Baremetal implementation of an exit function ----*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
diff --git a/libc/src/__support/OSUtil/linux/exit.cpp b/libc/src/__support/OSUtil/linux/exit.cpp
index 85e0b825ee5ef..48c385129b1ae 100644
--- a/libc/src/__support/OSUtil/linux/exit.cpp
+++ b/libc/src/__support/OSUtil/linux/exit.cpp
@@ -11,13 +11,12 @@
#include <sys/syscall.h> // For syscall numbers.
namespace LIBC_NAMESPACE::internal {
-
// mark as no_stack_protector for x86 since TLS can be torn down before calling
// quick_exit so that the stack protector canary cannot be loaded.
#ifdef LIBC_TARGET_ARCH_IS_X86
-__attribute__((no_stack_protector))
+[[clang::no_stack_protector]]
#endif
-__attribute__((noreturn)) void
+[[noreturn]] void
exit(int status) {
for (;;) {
LIBC_NAMESPACE::syscall_impl<long>(SYS_exit_group, status);
diff --git a/libc/src/stdlib/CMakeLists.txt b/libc/src/stdlib/CMakeLists.txt
index 7a8db59f691da..59eeb71bfbfb9 100644
--- a/libc/src/stdlib/CMakeLists.txt
+++ b/libc/src/stdlib/CMakeLists.txt
@@ -442,7 +442,6 @@ add_entrypoint_object(
HDRS
quick_exit.h
DEPENDS
- libc.src.errno.errno
libc.src.__support.OSUtil.osutil
)
diff --git a/libc/src/stdlib/quick_exit.cpp b/libc/src/stdlib/quick_exit.cpp
index 14f7f78169033..20d720b731ed5 100644
--- a/libc/src/stdlib/quick_exit.cpp
+++ b/libc/src/stdlib/quick_exit.cpp
@@ -19,4 +19,3 @@ namespace LIBC_NAMESPACE {
}
} // namespace LIBC_NAMESPACE
- // namespace LIBC_NAMESPACE
diff --git a/libc/src/stdlib/quick_exit.h b/libc/src/stdlib/quick_exit.h
index 1ebf689e1868e..a2fdeedc853ca 100644
--- a/libc/src/stdlib/quick_exit.h
+++ b/libc/src/stdlib/quick_exit.h
@@ -8,9 +8,6 @@
#ifndef LLVM_LIBC_SRC_STDLIB_QUICK_EXIT_H
#define LLVM_LIBC_SRC_STDLIB_QUICK_EXIT_H
-
-#include <stdlib.h>
-
namespace LIBC_NAMESPACE {
[[noreturn]] void quick_exit(int status);
diff --git a/libc/test/IntegrationTest/test.h b/libc/test/IntegrationTest/test.h
index 2b28b97340659..5be66d9edff02 100644
--- a/libc/test/IntegrationTest/test.h
+++ b/libc/test/IntegrationTest/test.h
@@ -17,10 +17,9 @@
if (!(val)) { \
LIBC_NAMESPACE::write_to_stderr(file ":" __AS_STRING( \
line) ": Expected '" #val "' to be true, but is false\n"); \
- if (should_exit)
-
-LIBC_NAMESPACE::internal::exit(127);
-}
+ if (should_exit) \
+ LIBC_NAMESPACE::internal::exit(127); \
+ }
#define __CHECK_FALSE(file, line, val, should_exit) \
if (val) { \
diff --git a/libc/test/src/stdlib/quick_exit_test.cpp b/libc/test/src/stdlib/quick_exit_test.cpp
index 8ed878a11575b..901b49efbc6b4 100644
--- a/libc/test/src/stdlib/quick_exit_test.cpp
+++ b/libc/test/src/stdlib/quick_exit_test.cpp
@@ -9,8 +9,6 @@
#include "src/stdlib/quick_exit.h"
#include "test/UnitTest/Test.h"
-#include <stdlib.h>
-
TEST(LlvmLibcStdlib, quick_exit) {
EXPECT_EXITS([] { LIBC_NAMESPACE::quick_exit(1); }, 1);
EXPECT_EXITS([] { LIBC_NAMESPACE::quick_exit(65); }, 65);
>From 2949dbd0f0f062fdd1c8cb78666c690e487bd9d9 Mon Sep 17 00:00:00 2001
From: Aaryan Shukla <aaryanshukla at google.com>
Date: Thu, 30 May 2024 22:03:26 +0000
Subject: [PATCH 5/8] added internal in front of exit for quick_exit
put internal in front of the calling for exit.
---
libc/src/stdlib/quick_exit.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libc/src/stdlib/quick_exit.cpp b/libc/src/stdlib/quick_exit.cpp
index 20d720b731ed5..bee58163ed7b3 100644
--- a/libc/src/stdlib/quick_exit.cpp
+++ b/libc/src/stdlib/quick_exit.cpp
@@ -15,7 +15,7 @@ namespace LIBC_NAMESPACE {
[[noreturn]] LLVM_LIBC_FUNCTION(void, quick_exit, (int status)) {
//__cxa_finalize(nullptr);
- exit(status);
+ internal::exit(status);
}
} // namespace LIBC_NAMESPACE
>From 453836de90d08091c4f6f84823d4fcf0c33a47de Mon Sep 17 00:00:00 2001
From: Aaryan Shukla <aaryanshukla at google.com>
Date: Thu, 30 May 2024 23:12:31 +0000
Subject: [PATCH 6/8] updated build.BAZEL, changed all quick_exit to exit
changed all areas from quick_exit to exit in build.BAZEL.
---
utils/bazel/llvm-project-overlay/libc/BUILD.bazel | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index 446499cf15d7b..6b312fb848a47 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -630,7 +630,7 @@ libc_support_library(
":__support_integer_to_string",
":__support_macros_attributes",
":__support_osutil_io",
- ":__support_osutil_quick_exit",
+ ":__support_osutil_exit",
],
)
@@ -1062,9 +1062,9 @@ libc_support_library(
)
libc_support_library(
- name = "__support_osutil_quick_exit",
- srcs = ["src/__support/OSUtil/linux/quick_exit.cpp"],
- hdrs = ["src/__support/OSUtil/quick_exit.h"],
+ name = "__support_osutil_exit",
+ srcs = ["src/__support/OSUtil/linux/exit.cpp"],
+ hdrs = ["src/__support/OSUtil/exit.h"],
target_compatible_with = select({
"@platforms//os:linux": [],
"//conditions:default": ["@platforms//:incompatible"],
>From 17647b27d85b5ec8cf58b5f145c2bc57e449a496 Mon Sep 17 00:00:00 2001
From: Aaryan Shukla <aaryanshukla at google.com>
Date: Thu, 30 May 2024 23:32:43 +0000
Subject: [PATCH 7/8] changed quick_exit to exit in cmakefiles in gpu and
baremetal
modified quick_exit to exit in cmakefiles.
---
libc/src/__support/OSUtil/baremetal/CMakeLists.txt | 2 +-
libc/src/__support/OSUtil/gpu/CMakeLists.txt | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/libc/src/__support/OSUtil/baremetal/CMakeLists.txt b/libc/src/__support/OSUtil/baremetal/CMakeLists.txt
index e78301d104c1f..8f9200ad0bd96 100644
--- a/libc/src/__support/OSUtil/baremetal/CMakeLists.txt
+++ b/libc/src/__support/OSUtil/baremetal/CMakeLists.txt
@@ -2,7 +2,7 @@ add_object_library(
baremetal_util
SRCS
io.cpp
- quick_exit.cpp
+ exit.cpp
HDRS
io.h
DEPENDS
diff --git a/libc/src/__support/OSUtil/gpu/CMakeLists.txt b/libc/src/__support/OSUtil/gpu/CMakeLists.txt
index 0c89f9223678b..6cb3aa30f249e 100644
--- a/libc/src/__support/OSUtil/gpu/CMakeLists.txt
+++ b/libc/src/__support/OSUtil/gpu/CMakeLists.txt
@@ -1,7 +1,7 @@
add_object_library(
gpu_util
SRCS
- quick_exit.cpp
+ exit.cpp
io.cpp
HDRS
io.h
>From 1bde84a0207e914eab42d4e10e3a6205401eacb5 Mon Sep 17 00:00:00 2001
From: Aaryan Shukla <aaryanshukla at google.com>
Date: Mon, 3 Jun 2024 22:32:33 +0000
Subject: [PATCH 8/8] [libc] added at_quick_exit function
- reused functions from atexit
- added to entrypoints and cmake
- test cases added and passed
- create helper function exit_handler
---
libc/config/linux/x86_64/entrypoints.txt | 1 +
libc/spec/stdc.td | 2 +
libc/src/stdlib/CMakeLists.txt | 36 +++++++++
libc/src/stdlib/at_quick_exit.cpp | 37 +++++++++
libc/src/stdlib/at_quick_exit.h | 17 ++++
libc/src/stdlib/atexit.cpp | 72 +----------------
libc/src/stdlib/atexit.h | 5 --
libc/src/stdlib/exit_handler.cpp | 46 +++++++++++
libc/src/stdlib/exit_handler.h | 52 ++++++++++++
libc/src/stdlib/quick_exit.cpp | 5 +-
libc/test/src/stdlib/CMakeLists.txt | 17 ++++
libc/test/src/stdlib/at_quick_exit_test.cpp | 90 +++++++++++++++++++++
12 files changed, 306 insertions(+), 74 deletions(-)
create mode 100644 libc/src/stdlib/at_quick_exit.cpp
create mode 100644 libc/src/stdlib/at_quick_exit.h
create mode 100644 libc/src/stdlib/exit_handler.cpp
create mode 100644 libc/src/stdlib/exit_handler.h
create mode 100644 libc/test/src/stdlib/at_quick_exit_test.cpp
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index b6ead64e208c7..74f94e12a5f25 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -731,6 +731,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.stdlib.atexit
libc.src.stdlib.exit
libc.src.stdlib.quick_exit
+ libc.src.stdlib.at_quick_exit
libc.src.stdlib.getenv
# signal.h entrypoints
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index 9ec9ee7521c7e..4bf0e2a99c0e1 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -1072,6 +1072,8 @@ def StdC : StandardSpec<"stdc"> {
FunctionSpec<"exit", RetValSpec<NoReturn>, [ArgSpec<IntType>]>,
FunctionSpec<"atexit", RetValSpec<IntType>, [ArgSpec<AtexitHandlerT>]>,
FunctionSpec<"quick_exit", RetValSpec<NoReturn>, [ArgSpec<IntType>]>,
+ FunctionSpec<"at_quick_exit", RetValSpec<IntType>, [ArgSpec<IntType>]>,
+
]
>;
diff --git a/libc/src/stdlib/CMakeLists.txt b/libc/src/stdlib/CMakeLists.txt
index 59eeb71bfbfb9..fa4ee33cfa0e0 100644
--- a/libc/src/stdlib/CMakeLists.txt
+++ b/libc/src/stdlib/CMakeLists.txt
@@ -405,6 +405,23 @@ add_entrypoint_object(
libc.src.__support.OSUtil.osutil
)
+add_object_library(
+ exit_handler
+ SRCS
+ exit_handler.cpp
+ HDRS
+ exit_handler.h
+ CXX_STANDARD
+ 20 # For constinit
+ DEPENDS
+ libc.src.__support.CPP.mutex
+ libc.src.__support.CPP.new
+ libc.src.__support.OSUtil.osutil
+ libc.src.__support.blockstore
+ libc.src.__support.fixedvector
+ libc.src.__support.threads.mutex
+)
+
add_entrypoint_object(
atexit
SRCS
@@ -420,6 +437,7 @@ add_entrypoint_object(
libc.src.__support.blockstore
libc.src.__support.fixedvector
libc.src.__support.threads.mutex
+ .exit_handler
)
add_entrypoint_object(
@@ -432,6 +450,7 @@ add_entrypoint_object(
._Exit
.atexit
libc.src.__support.OSUtil.osutil
+ .exit_handler
)
@@ -443,6 +462,23 @@ add_entrypoint_object(
quick_exit.h
DEPENDS
libc.src.__support.OSUtil.osutil
+ .exit_handler
+)
+
+add_entrypoint_object(
+ at_quick_exit
+ SRCS
+ at_quick_exit.cpp
+ HDRS
+ at_quick_exit.h
+ DEPENDS
+ libc.src.__support.CPP.mutex
+ libc.src.__support.CPP.new
+ libc.src.__support.OSUtil.osutil
+ libc.src.__support.blockstore
+ libc.src.__support.fixedvector
+ libc.src.__support.threads.mutex
+ .exit_handler
)
add_entrypoint_object(
diff --git a/libc/src/stdlib/at_quick_exit.cpp b/libc/src/stdlib/at_quick_exit.cpp
new file mode 100644
index 0000000000000..9d06dbd324a46
--- /dev/null
+++ b/libc/src/stdlib/at_quick_exit.cpp
@@ -0,0 +1,37 @@
+//===-- Implementation of at_quick_exit -----------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/stdlib/at_quick_exit.h"
+#include "src/__support/CPP/mutex.h" // lock_guard
+#include "src/__support/blockstore.h"
+#include "src/__support/common.h"
+#include "src/__support/fixedvector.h"
+#include "src/__support/threads/mutex.h"
+#include "src/stdlib/exit_handler.h"
+namespace LIBC_NAMESPACE {
+
+extern "C" {
+
+int __cxa_at_quick_exit(AtExitCallback *callback, void *payload, void *) {
+ return add_atexit_unit(at_quick_exit_callbacks, {callback, payload});
+}
+
+void __cxa_finalize_quick_exit(void *dso) {
+ if (!dso)
+ call_exit_callbacks(at_quick_exit_callbacks);
+}
+
+} // extern "C"
+
+LLVM_LIBC_FUNCTION(int, at_quick_exit, (StdCAtExitCallback * callback)) {
+ return add_atexit_unit(
+ at_quick_exit_callbacks,
+ {&stdc_at_exit_func, reinterpret_cast<void *>(callback)});
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/stdlib/at_quick_exit.h b/libc/src/stdlib/at_quick_exit.h
new file mode 100644
index 0000000000000..d089e5462605b
--- /dev/null
+++ b/libc/src/stdlib/at_quick_exit.h
@@ -0,0 +1,17 @@
+//===-- Implementation header for at_quick_exit -----------------*- 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_STDLIB_AT_QUICK_EXIT_H
+#define LLVM_LIBC_SRC_STDLIB_AT_QUICK_EXIT_H
+
+namespace LIBC_NAMESPACE {
+
+int at_quick_exit(void (*function)());
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_STDLIB_AT_QUICK_EXIT_H
diff --git a/libc/src/stdlib/atexit.cpp b/libc/src/stdlib/atexit.cpp
index 4f0497444773d..35460f1817b7a 100644
--- a/libc/src/stdlib/atexit.cpp
+++ b/libc/src/stdlib/atexit.cpp
@@ -12,89 +12,25 @@
#include "src/__support/common.h"
#include "src/__support/fixedvector.h"
#include "src/__support/threads/mutex.h"
-
+#include "src/stdlib/exit_handler.h"
namespace LIBC_NAMESPACE {
-namespace {
-
-Mutex handler_list_mtx(false, false, false);
-
-using AtExitCallback = void(void *);
-using StdCAtExitCallback = void(void);
-
-struct AtExitUnit {
- AtExitCallback *callback = nullptr;
- void *payload = nullptr;
- constexpr AtExitUnit() = default;
- constexpr AtExitUnit(AtExitCallback *c, void *p) : callback(c), payload(p) {}
-};
-
-#if defined(LIBC_TARGET_ARCH_IS_GPU)
-// The GPU build cannot handle the potentially recursive definitions required by
-// the BlockStore class. Additionally, the liklihood that someone exceeds this
-// while executing on the GPU is extremely small.
-// FIXME: It is not generally safe to use 'atexit' on the GPU because the
-// mutexes simply passthrough. We will need a lock free stack.
-using ExitCallbackList = FixedVector<AtExitUnit, 64>;
-#elif defined(LIBC_COPT_PUBLIC_PACKAGING)
-using ExitCallbackList = ReverseOrderBlockStore<AtExitUnit, 32>;
-#else
-// BlockStore uses dynamic memory allocation. To avoid dynamic memory
-// allocation in tests, we use a fixed size callback list when built for
-// tests.
-// If we use BlockStore, then we will have to pull in malloc etc into
-// the tests. While this is not bad, the problem we have currently is
-// that LLVM libc' allocator is SCUDO. So, we will end up pulling SCUDO's
-// deps also (some of which are not yet available in LLVM libc) into the
-// integration tests.
-using ExitCallbackList = FixedVector<AtExitUnit, CALLBACK_LIST_SIZE_FOR_TESTS>;
-#endif // LIBC_COPT_PUBLIC_PACKAGING
-
-constinit ExitCallbackList exit_callbacks;
-
-void stdc_at_exit_func(void *payload) {
- reinterpret_cast<StdCAtExitCallback *>(payload)();
-}
-
-void call_exit_callbacks() {
- handler_list_mtx.lock();
- while (!exit_callbacks.empty()) {
- AtExitUnit &unit = exit_callbacks.back();
- exit_callbacks.pop_back();
- handler_list_mtx.unlock();
- unit.callback(unit.payload);
- handler_list_mtx.lock();
- }
- ExitCallbackList::destroy(&exit_callbacks);
-}
-
-int add_atexit_unit(const AtExitUnit &unit) {
- cpp::lock_guard lock(handler_list_mtx);
- if (exit_callbacks.push_back(unit))
- return 0;
- return -1;
-}
-
-} // namespace
-
extern "C" {
-// TODO: Handle the last dso handle argument.
int __cxa_atexit(AtExitCallback *callback, void *payload, void *) {
- return add_atexit_unit({callback, payload});
+ return add_atexit_unit(atexit_callbacks, {callback, payload});
}
-// TODO: Handle the dso handle argument. call_exit_callbacks should only invoke
-// the callbacks from this DSO. Requires adding support for __dso_handle.
void __cxa_finalize(void *dso) {
if (!dso)
- call_exit_callbacks();
+ call_exit_callbacks(atexit_callbacks);
}
} // extern "C"
LLVM_LIBC_FUNCTION(int, atexit, (StdCAtExitCallback * callback)) {
return add_atexit_unit(
+ atexit_callbacks,
{&stdc_at_exit_func, reinterpret_cast<void *>(callback)});
}
diff --git a/libc/src/stdlib/atexit.h b/libc/src/stdlib/atexit.h
index 7cf9d7c92191d..f9323be257084 100644
--- a/libc/src/stdlib/atexit.h
+++ b/libc/src/stdlib/atexit.h
@@ -8,13 +8,8 @@
#ifndef LLVM_LIBC_SRC_STDLIB_ATEXIT_H
#define LLVM_LIBC_SRC_STDLIB_ATEXIT_H
-
-#include <stddef.h> // For size_t
-
namespace LIBC_NAMESPACE {
-constexpr size_t CALLBACK_LIST_SIZE_FOR_TESTS = 1024;
-
int atexit(void (*function)());
} // namespace LIBC_NAMESPACE
diff --git a/libc/src/stdlib/exit_handler.cpp b/libc/src/stdlib/exit_handler.cpp
new file mode 100644
index 0000000000000..ac69726a90a12
--- /dev/null
+++ b/libc/src/stdlib/exit_handler.cpp
@@ -0,0 +1,46 @@
+//===-- Implementation of exit_handler-------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/stdlib/exit_handler.h"
+#include "src/__support/CPP/mutex.h" // lock_guard
+#include "src/__support/blockstore.h"
+#include "src/__support/common.h"
+#include "src/__support/fixedvector.h"
+#include "src/__support/threads/mutex.h"
+
+namespace LIBC_NAMESPACE {
+
+constinit ExitCallbackList at_quick_exit_callbacks;
+constinit ExitCallbackList atexit_callbacks;
+
+Mutex handler_list_mtx(false, false, false);
+
+void stdc_at_exit_func(void *payload) {
+ reinterpret_cast<StdCAtExitCallback *>(payload)();
+}
+
+void call_exit_callbacks(ExitCallbackList &callbacks) {
+ handler_list_mtx.lock();
+ while (!callbacks.empty()) {
+ AtExitUnit &unit = callbacks.back();
+ callbacks.pop_back();
+ handler_list_mtx.unlock();
+ unit.callback(unit.payload);
+ handler_list_mtx.lock();
+ }
+ ExitCallbackList::destroy(&callbacks);
+}
+
+int add_atexit_unit(ExitCallbackList &callbacks, const AtExitUnit &unit) {
+ cpp::lock_guard lock(handler_list_mtx);
+ if (callbacks.push_back(unit))
+ return 0;
+ return -1;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/stdlib/exit_handler.h b/libc/src/stdlib/exit_handler.h
new file mode 100644
index 0000000000000..473a4d32aa3ca
--- /dev/null
+++ b/libc/src/stdlib/exit_handler.h
@@ -0,0 +1,52 @@
+//===-- Implementation header for exit_handler ------------------*- 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_STDLIB_EXIT_HANDLER_H
+#define LLVM_LIBC_SRC_STDLIB_EXIT_HANDLER_H
+
+#include "src/__support/CPP/mutex.h" // lock_guard
+#include "src/__support/blockstore.h"
+#include "src/__support/common.h"
+#include "src/__support/fixedvector.h"
+#include "src/__support/threads/mutex.h"
+
+namespace LIBC_NAMESPACE {
+
+using AtExitCallback = void(void *);
+using StdCAtExitCallback = void(void);
+constexpr size_t CALLBACK_LIST_SIZE_FOR_TESTS = 1024;
+
+struct AtExitUnit {
+ AtExitCallback *callback = nullptr;
+ void *payload = nullptr;
+ constexpr AtExitUnit() = default;
+ constexpr AtExitUnit(AtExitCallback *c, void *p) : callback(c), payload(p) {}
+};
+
+#if defined(LIBC_TARGET_ARCH_IS_GPU)
+using ExitCallbackList = FixedVector<AtExitUnit, 64>;
+#elif defined(LIBC_COPT_PUBLIC_PACKAGING)
+using ExitCallbackList = ReverseOrderBlockStore<AtExitUnit, 32>;
+#else
+using ExitCallbackList = FixedVector<AtExitUnit, CALLBACK_LIST_SIZE_FOR_TESTS>;
+#endif
+
+extern ExitCallbackList atexit_callbacks;
+extern ExitCallbackList at_quick_exit_callbacks;
+
+extern Mutex handler_list_mtx;
+
+void stdc_at_exit_func(void *payload);
+
+void call_exit_callbacks(ExitCallbackList &callbacks);
+
+int add_atexit_unit(ExitCallbackList &callbacks, const AtExitUnit &unit);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_STDLIB_EXIT_HANDLER_H
diff --git a/libc/src/stdlib/quick_exit.cpp b/libc/src/stdlib/quick_exit.cpp
index bee58163ed7b3..38f0a3db3e2cf 100644
--- a/libc/src/stdlib/quick_exit.cpp
+++ b/libc/src/stdlib/quick_exit.cpp
@@ -9,12 +9,15 @@
#include "src/stdlib/quick_exit.h"
#include "src/__support/OSUtil/exit.h"
#include "src/__support/common.h"
+#include "src/stdlib/exit_handler.h"
// extern "C" void __cxa_finalize(void *);
namespace LIBC_NAMESPACE {
+extern ExitCallbackList at_quick_exit_callbacks;
+
[[noreturn]] LLVM_LIBC_FUNCTION(void, quick_exit, (int status)) {
- //__cxa_finalize(nullptr);
+ call_exit_callbacks(at_quick_exit_callbacks);
internal::exit(status);
}
diff --git a/libc/test/src/stdlib/CMakeLists.txt b/libc/test/src/stdlib/CMakeLists.txt
index 3eedd6d678c0b..bbbc828579365 100644
--- a/libc/test/src/stdlib/CMakeLists.txt
+++ b/libc/test/src/stdlib/CMakeLists.txt
@@ -339,6 +339,23 @@ add_libc_test(
if(LLVM_LIBC_FULL_BUILD)
+ add_libc_test(
+ at_quick_exit_test
+ UNIT_TEST_ONLY
+ SUITE
+ libc-stdlib-tests
+ SRCS
+ at_quick_exit_test.cpp
+ DEPENDS
+ libc.include.stdlib
+ libc.src.stdlib._Exit
+ libc.src.stdlib.exit
+ libc.src.stdlib.at_quick_exit
+ libc.src.stdlib.quick_exit
+ libc.src.__support.CPP.array
+ libc.src.__support.CPP.utility
+ )
+
add_libc_test(
_Exit_test
# The EXPECT_EXITS test is only availible for unit tests.
diff --git a/libc/test/src/stdlib/at_quick_exit_test.cpp b/libc/test/src/stdlib/at_quick_exit_test.cpp
new file mode 100644
index 0000000000000..2c94b59d47bef
--- /dev/null
+++ b/libc/test/src/stdlib/at_quick_exit_test.cpp
@@ -0,0 +1,90 @@
+//===-- Unittests for at_quick_exit ---------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/CPP/array.h"
+#include "src/__support/CPP/utility.h"
+#include "src/stdlib/at_quick_exit.h"
+#include "src/stdlib/quick_exit.h"
+#include "test/UnitTest/Test.h"
+
+static int a;
+TEST(LlvmLibcAtQuickExit, Basic) {
+ // In case tests ever run multiple times.
+ a = 0;
+
+ auto test = [] {
+ int status = LIBC_NAMESPACE::at_quick_exit(+[] {
+ if (a != 1)
+ __builtin_trap();
+ });
+ status |= LIBC_NAMESPACE::at_quick_exit(+[] { a++; });
+ if (status)
+ __builtin_trap();
+
+ LIBC_NAMESPACE::quick_exit(0);
+ };
+ EXPECT_EXITS(test, 0);
+}
+
+TEST(LlvmLibcAtQuickExit, AtQuickExitCallsSysExit) {
+ auto test = [] {
+ LIBC_NAMESPACE::at_quick_exit(+[] { _Exit(1); });
+ LIBC_NAMESPACE::quick_exit(0);
+ };
+ EXPECT_EXITS(test, 1);
+}
+
+static int size;
+static LIBC_NAMESPACE::cpp::array<int, 256> arr;
+
+template <int... Ts>
+void register_at_quick_exit_handlers(
+ LIBC_NAMESPACE::cpp::integer_sequence<int, Ts...>) {
+ (LIBC_NAMESPACE::at_quick_exit(+[] { arr[size++] = Ts; }), ...);
+}
+
+template <int count> constexpr auto get_test() {
+ return [] {
+ LIBC_NAMESPACE::at_quick_exit(+[] {
+ if (size != count)
+ __builtin_trap();
+ for (int i = 0; i < count; i++)
+ if (arr[i] != count - 1 - i)
+ __builtin_trap();
+ });
+ register_at_quick_exit_handlers(
+ LIBC_NAMESPACE::cpp::make_integer_sequence<int, count>{});
+ LIBC_NAMESPACE::quick_exit(0);
+ };
+}
+
+TEST(LlvmLibcAtQuickExit, ReverseOrder) {
+ // In case tests ever run multiple times.
+ size = 0;
+
+ auto test = get_test<32>();
+ EXPECT_EXITS(test, 0);
+}
+
+TEST(LlvmLibcAtQuickExit, Many) {
+ // In case tests ever run multiple times.
+ size = 0;
+
+ auto test = get_test<256>();
+ EXPECT_EXITS(test, 0);
+}
+
+TEST(LlvmLibcAtQuickExit, HandlerCallsAtQuickExit) {
+ auto test = [] {
+ LIBC_NAMESPACE::at_quick_exit(+[] {
+ LIBC_NAMESPACE::at_quick_exit(+[] { LIBC_NAMESPACE::quick_exit(1); });
+ });
+ LIBC_NAMESPACE::quick_exit(0);
+ };
+ EXPECT_EXITS(test, 1);
+}
\ No newline at end of file
More information about the libc-commits
mailing list