Skip to content

Commit 39d38d6

Browse files
authored
[libc] at_quick_exit function implemented (#94317)
- added at_quick_exit function - used helper file exit_handler which reuses code from atexit - atexit now calls helper functions from exit_handler - test cases and dependencies are added --------- Co-authored-by: Aaryan Shukla <[email protected]>
1 parent e8500a7 commit 39d38d6

File tree

14 files changed

+315
-88
lines changed

14 files changed

+315
-88
lines changed

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,6 @@ set(TARGET_LIBC_ENTRYPOINTS
173173
libc.src.stdlib.atoll
174174
libc.src.stdlib.bsearch
175175
libc.src.stdlib.div
176-
libc.src.stdlib.quick_exit
177176
libc.src.stdlib.labs
178177
libc.src.stdlib.ldiv
179178
libc.src.stdlib.llabs
@@ -770,9 +769,11 @@ if(LLVM_LIBC_FULL_BUILD)
770769
# stdlib.h entrypoints
771770
libc.src.stdlib._Exit
772771
libc.src.stdlib.abort
772+
libc.src.stdlib.at_quick_exit
773773
libc.src.stdlib.atexit
774774
libc.src.stdlib.exit
775775
libc.src.stdlib.getenv
776+
libc.src.stdlib.quick_exit
776777

777778
# signal.h entrypoints
778779
libc.src.signal.raise

libc/hdr/types/CMakeLists.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,3 +117,12 @@ add_proxy_header_library(
117117
libc.include.llvm-libc-types.pid_t
118118
libc.include.sys_types
119119
)
120+
121+
add_proxy_header_library(
122+
atexithandler_t
123+
HDRS
124+
atexithandler_t.h
125+
FULL_BUILD_DEPENDS
126+
libc.include.llvm-libc-types.atexithandler_t
127+
libc.include.stdlib
128+
)

libc/hdr/types/atexithandler_t.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//===-- Definition of macros from atexithandler_t.h -----------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_HDR_ATEXITHANDLER_T_H
10+
#define LLVM_LIBC_HDR_ATEXITHANDLER_T_H
11+
12+
#ifdef LIBC_FULL_BUILD
13+
14+
#include "include/llvm-libc-types/__atexithandler_t.h"
15+
16+
#else // overlay mode
17+
18+
#error // type not available in overlay mode
19+
20+
#endif // LLVM_LIBC_FULL_BUILD
21+
22+
#endif // LLVM_LIBC_HDR_ATEXITHANDLER_T_H

libc/spec/stdc.td

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1107,8 +1107,9 @@ def StdC : StandardSpec<"stdc"> {
11071107
FunctionSpec<"free", RetValSpec<VoidType>, [ArgSpec<VoidPtr>]>,
11081108

11091109
FunctionSpec<"_Exit", RetValSpec<NoReturn>, [ArgSpec<IntType>]>,
1110-
FunctionSpec<"exit", RetValSpec<NoReturn>, [ArgSpec<IntType>]>,
1110+
FunctionSpec<"at_quick_exit", RetValSpec<IntType>, [ArgSpec<AtexitHandlerT>]>,
11111111
FunctionSpec<"atexit", RetValSpec<IntType>, [ArgSpec<AtexitHandlerT>]>,
1112+
FunctionSpec<"exit", RetValSpec<NoReturn>, [ArgSpec<IntType>]>,
11121113
FunctionSpec<"quick_exit", RetValSpec<NoReturn>, [ArgSpec<IntType>]>,
11131114
]
11141115
>;

libc/src/stdlib/CMakeLists.txt

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ add_entrypoint_object(
5050
quick_exit.h
5151
DEPENDS
5252
libc.src.__support.OSUtil.osutil
53+
.exit_handler
5354
)
5455

5556
add_entrypoint_object(
@@ -415,14 +416,14 @@ add_entrypoint_object(
415416
libc.src.__support.OSUtil.osutil
416417
)
417418

418-
add_entrypoint_object(
419-
atexit
419+
add_object_library(
420+
exit_handler
420421
SRCS
421-
atexit.cpp
422+
exit_handler.cpp
422423
HDRS
423-
atexit.h
424+
exit_handler.h
424425
CXX_STANDARD
425-
20 # For constinit of the atexit callback list.
426+
20 # For constinit
426427
DEPENDS
427428
libc.src.__support.CPP.mutex
428429
libc.src.__support.CPP.new
@@ -432,6 +433,26 @@ add_entrypoint_object(
432433
libc.src.__support.threads.mutex
433434
)
434435

436+
add_entrypoint_object(
437+
atexit
438+
SRCS
439+
atexit.cpp
440+
HDRS
441+
atexit.h
442+
DEPENDS
443+
.exit_handler
444+
)
445+
446+
add_entrypoint_object(
447+
at_quick_exit
448+
SRCS
449+
at_quick_exit.cpp
450+
HDRS
451+
at_quick_exit.h
452+
DEPENDS
453+
.exit_handler
454+
)
455+
435456
add_entrypoint_object(
436457
exit
437458
SRCS
@@ -442,6 +463,7 @@ add_entrypoint_object(
442463
._Exit
443464
.atexit
444465
libc.src.__support.OSUtil.osutil
466+
.exit_handler
445467
)
446468

447469
add_entrypoint_object(

libc/src/stdlib/at_quick_exit.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//===-- Implementation of at_quick_exit -----------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "src/stdlib/at_quick_exit.h"
10+
#include "hdr/types/atexithandler_t.h"
11+
#include "src/__support/common.h"
12+
#include "src/stdlib/exit_handler.h"
13+
14+
namespace LIBC_NAMESPACE {
15+
16+
LLVM_LIBC_FUNCTION(int, at_quick_exit, (__atexithandler_t callback)) {
17+
return add_atexit_unit(
18+
at_quick_exit_callbacks,
19+
{&stdc_at_exit_func, reinterpret_cast<void *>(callback)});
20+
}
21+
22+
} // namespace LIBC_NAMESPACE

libc/src/stdlib/at_quick_exit.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===-- Implementation header for at_quick_exit -----------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_SRC_STDLIB_AT_QUICK_EXIT_H
10+
#define LLVM_LIBC_SRC_STDLIB_AT_QUICK_EXIT_H
11+
12+
#include "hdr/types/atexithandler_t.h"
13+
14+
namespace LIBC_NAMESPACE {
15+
16+
int at_quick_exit(__atexithandler_t);
17+
18+
} // namespace LIBC_NAMESPACE
19+
20+
#endif // LLVM_LIBC_SRC_STDLIB_AT_QUICK_EXIT_H

libc/src/stdlib/atexit.cpp

Lines changed: 6 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -7,95 +7,28 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "src/stdlib/atexit.h"
10-
#include "src/__support/CPP/mutex.h" // lock_guard
11-
#include "src/__support/blockstore.h"
10+
#include "hdr/types/atexithandler_t.h"
1211
#include "src/__support/common.h"
13-
#include "src/__support/fixedvector.h"
14-
#include "src/__support/threads/mutex.h"
12+
#include "src/stdlib/exit_handler.h"
1513

1614
namespace LIBC_NAMESPACE {
1715

18-
namespace {
19-
20-
Mutex handler_list_mtx(/*timed=*/false, /*recursive=*/false, /*robust=*/false,
21-
/*pshared=*/false);
22-
23-
using AtExitCallback = void(void *);
24-
using StdCAtExitCallback = void(void);
25-
26-
struct AtExitUnit {
27-
AtExitCallback *callback = nullptr;
28-
void *payload = nullptr;
29-
constexpr AtExitUnit() = default;
30-
constexpr AtExitUnit(AtExitCallback *c, void *p) : callback(c), payload(p) {}
31-
};
32-
33-
#if defined(LIBC_TARGET_ARCH_IS_GPU)
34-
// The GPU build cannot handle the potentially recursive definitions required by
35-
// the BlockStore class. Additionally, the liklihood that someone exceeds this
36-
// while executing on the GPU is extremely small.
37-
// FIXME: It is not generally safe to use 'atexit' on the GPU because the
38-
// mutexes simply passthrough. We will need a lock free stack.
39-
using ExitCallbackList = FixedVector<AtExitUnit, 64>;
40-
#elif defined(LIBC_COPT_PUBLIC_PACKAGING)
41-
using ExitCallbackList = ReverseOrderBlockStore<AtExitUnit, 32>;
42-
#else
43-
// BlockStore uses dynamic memory allocation. To avoid dynamic memory
44-
// allocation in tests, we use a fixed size callback list when built for
45-
// tests.
46-
// If we use BlockStore, then we will have to pull in malloc etc into
47-
// the tests. While this is not bad, the problem we have currently is
48-
// that LLVM libc' allocator is SCUDO. So, we will end up pulling SCUDO's
49-
// deps also (some of which are not yet available in LLVM libc) into the
50-
// integration tests.
51-
using ExitCallbackList = FixedVector<AtExitUnit, CALLBACK_LIST_SIZE_FOR_TESTS>;
52-
#endif // LIBC_COPT_PUBLIC_PACKAGING
53-
54-
constinit ExitCallbackList exit_callbacks;
55-
56-
void stdc_at_exit_func(void *payload) {
57-
reinterpret_cast<StdCAtExitCallback *>(payload)();
58-
}
59-
60-
void call_exit_callbacks() {
61-
handler_list_mtx.lock();
62-
while (!exit_callbacks.empty()) {
63-
AtExitUnit &unit = exit_callbacks.back();
64-
exit_callbacks.pop_back();
65-
handler_list_mtx.unlock();
66-
unit.callback(unit.payload);
67-
handler_list_mtx.lock();
68-
}
69-
ExitCallbackList::destroy(&exit_callbacks);
70-
}
71-
72-
int add_atexit_unit(const AtExitUnit &unit) {
73-
cpp::lock_guard lock(handler_list_mtx);
74-
if (exit_callbacks.push_back(unit))
75-
return 0;
76-
return -1;
77-
}
78-
79-
} // namespace
80-
8116
extern "C" {
8217

83-
// TODO: Handle the last dso handle argument.
8418
int __cxa_atexit(AtExitCallback *callback, void *payload, void *) {
85-
return add_atexit_unit({callback, payload});
19+
return add_atexit_unit(atexit_callbacks, {callback, payload});
8620
}
8721

88-
// TODO: Handle the dso handle argument. call_exit_callbacks should only invoke
89-
// the callbacks from this DSO. Requires adding support for __dso_handle.
9022
void __cxa_finalize(void *dso) {
9123
if (!dso)
92-
call_exit_callbacks();
24+
call_exit_callbacks(atexit_callbacks);
9325
}
9426

9527
} // extern "C"
9628

97-
LLVM_LIBC_FUNCTION(int, atexit, (StdCAtExitCallback * callback)) {
29+
LLVM_LIBC_FUNCTION(int, atexit, (__atexithandler_t callback)) {
9830
return add_atexit_unit(
31+
atexit_callbacks,
9932
{&stdc_at_exit_func, reinterpret_cast<void *>(callback)});
10033
}
10134

libc/src/stdlib/atexit.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,10 @@
99
#ifndef LLVM_LIBC_SRC_STDLIB_ATEXIT_H
1010
#define LLVM_LIBC_SRC_STDLIB_ATEXIT_H
1111

12-
#include <stddef.h> // For size_t
13-
12+
#include "hdr/types/atexithandler_t.h"
1413
namespace LIBC_NAMESPACE {
1514

16-
constexpr size_t CALLBACK_LIST_SIZE_FOR_TESTS = 1024;
17-
18-
int atexit(void (*function)());
15+
int atexit(__atexithandler_t);
1916

2017
} // namespace LIBC_NAMESPACE
2118

libc/src/stdlib/exit_handler.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//===--- Implementation of exit_handler------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "src/stdlib/exit_handler.h"
10+
#include "src/__support/CPP/mutex.h" // lock_guard
11+
12+
namespace LIBC_NAMESPACE {
13+
14+
constinit ExitCallbackList at_quick_exit_callbacks;
15+
constinit ExitCallbackList atexit_callbacks;
16+
17+
Mutex handler_list_mtx(false, false, false, false);
18+
19+
void stdc_at_exit_func(void *payload) {
20+
reinterpret_cast<StdCAtExitCallback *>(payload)();
21+
}
22+
23+
void call_exit_callbacks(ExitCallbackList &callbacks) {
24+
handler_list_mtx.lock();
25+
while (!callbacks.empty()) {
26+
AtExitUnit &unit = callbacks.back();
27+
callbacks.pop_back();
28+
handler_list_mtx.unlock();
29+
unit.callback(unit.payload);
30+
handler_list_mtx.lock();
31+
}
32+
ExitCallbackList::destroy(&callbacks);
33+
}
34+
35+
int add_atexit_unit(ExitCallbackList &callbacks, const AtExitUnit &unit) {
36+
cpp::lock_guard lock(handler_list_mtx);
37+
if (callbacks.push_back(unit))
38+
return 0;
39+
return -1;
40+
}
41+
42+
} // namespace LIBC_NAMESPACE

libc/src/stdlib/exit_handler.h

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
//===-- Implementation header for exit_handler ------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_SRC_STDLIB_EXIT_HANDLER_H
10+
#define LLVM_LIBC_SRC_STDLIB_EXIT_HANDLER_H
11+
12+
#include "src/__support/CPP/mutex.h" // lock_guard
13+
#include "src/__support/blockstore.h"
14+
#include "src/__support/common.h"
15+
#include "src/__support/fixedvector.h"
16+
#include "src/__support/threads/mutex.h"
17+
18+
namespace LIBC_NAMESPACE {
19+
20+
using AtExitCallback = void(void *);
21+
using StdCAtExitCallback = void(void);
22+
constexpr size_t CALLBACK_LIST_SIZE_FOR_TESTS = 1024;
23+
24+
struct AtExitUnit {
25+
AtExitCallback *callback = nullptr;
26+
void *payload = nullptr;
27+
LIBC_INLINE constexpr AtExitUnit() = default;
28+
LIBC_INLINE constexpr AtExitUnit(AtExitCallback *c, void *p)
29+
: callback(c), payload(p) {}
30+
};
31+
32+
#if defined(LIBC_TARGET_ARCH_IS_GPU)
33+
using ExitCallbackList = FixedVector<AtExitUnit, 64>;
34+
#elif defined(LIBC_COPT_PUBLIC_PACKAGING)
35+
using ExitCallbackList = ReverseOrderBlockStore<AtExitUnit, 32>;
36+
#else
37+
using ExitCallbackList = FixedVector<AtExitUnit, CALLBACK_LIST_SIZE_FOR_TESTS>;
38+
#endif
39+
40+
extern ExitCallbackList atexit_callbacks;
41+
extern ExitCallbackList at_quick_exit_callbacks;
42+
43+
extern Mutex handler_list_mtx;
44+
45+
void stdc_at_exit_func(void *payload);
46+
47+
void call_exit_callbacks(ExitCallbackList &callbacks);
48+
49+
int add_atexit_unit(ExitCallbackList &callbacks, const AtExitUnit &unit);
50+
51+
} // namespace LIBC_NAMESPACE
52+
53+
#endif // LLVM_LIBC_SRC_STDLIB_EXIT_HANDLER_H

0 commit comments

Comments
 (0)