diff --git a/src/libraries/libc/stdlib/_Exit.cpp b/src/libraries/libc/stdlib/_Exit.cpp deleted file mode 100644 index f4179be..0000000 --- a/src/libraries/libc/stdlib/_Exit.cpp +++ /dev/null @@ -1,18 +0,0 @@ -/** \file _Exit.cpp - * - * This file is part of the C standard library for the jsix operating - * system. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - */ - -#include -#include - -void -_Exit( int status ) -{ - j6_process_exit(status); -} diff --git a/src/libraries/libc/stdlib/abort.cpp b/src/libraries/libc/stdlib/abort.cpp deleted file mode 100644 index 23a41e5..0000000 --- a/src/libraries/libc/stdlib/abort.cpp +++ /dev/null @@ -1,18 +0,0 @@ -/** \file abort.cpp - * - * This file is part of the C standard library for the jsix operating - * system. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - */ - -#include -#include - -void -abort() -{ - _Exit(INT32_MIN); -} diff --git a/src/libraries/libc/stdlib/exit.cpp b/src/libraries/libc/stdlib/exit.cpp index c2b1ed0..0a0a473 100644 --- a/src/libraries/libc/stdlib/exit.cpp +++ b/src/libraries/libc/stdlib/exit.cpp @@ -1,17 +1,85 @@ -/** \file exit.cpp - * - * This file is part of the C standard library for the jsix operating - * system. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - */ - #include +#include -void -exit( int status ) +using cxa_callback = void (*)(void *); +using c_callback = void (*)(void); + +namespace { + +constexpr size_t max_atexit = 64; + +struct atexit_item { + cxa_callback cb; + void *arg; +}; + +size_t atexit_count = 0; +atexit_item atexit_array[max_atexit]; + +size_t quick_exit_count = 0; +atexit_item quick_exit_array[max_atexit]; + +[[noreturn]] inline void +exit_with_callbacks(int status, atexit_item *cbs, size_t count) +{ + for (size_t i = count - 1; i < count; --i) { + atexit_item &item = cbs[i]; + item.cb(item.arg); + } + _Exit(status); } + +void +bare_callback(void *real_cb) +{ + reinterpret_cast(real_cb)(); +} + +} // namespace + +extern "C" int +__cxa_atexit(cxa_callback cb, void *arg, void *dso) +{ + if (atexit_count == max_atexit) return -1; + atexit_array[atexit_count++] = {cb, arg}; + return 0; +} + +int +atexit( void (*func)(void) ) +{ + return __cxa_atexit(bare_callback, reinterpret_cast(func), nullptr); +} + +int at_quick_exit( void (*func)(void) ) +{ + if (quick_exit_count == max_atexit) return -1; + quick_exit_array[quick_exit_count++] = {&bare_callback, reinterpret_cast(func)}; + return 0; +} + +void +exit(int status) +{ + exit_with_callbacks(status, atexit_array, atexit_count); +} + +void +quick_exit(int status) +{ + exit_with_callbacks(status, quick_exit_array, quick_exit_count); +} + +void +abort() +{ + _Exit(INT32_MIN); +} + +void +_Exit( int status ) +{ + j6_process_exit(status); +}