[libc] Implement atexit et al

This commit joins the implementation of exit, _Exit, and abort into a
single translation unit, and also adds atexit, at_quick_exit, and
quick_exit. While this does go against the ideal of all libc functions
being in their own translation unit, their implementations are very
related, and so I think this makes sense.
This commit is contained in:
Justin C. Miller
2022-02-10 20:36:04 -08:00
parent c0ae77cd64
commit 195b635f74
3 changed files with 80 additions and 48 deletions

View File

@@ -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 <stdlib.h>
#include <j6/syscalls.h>
void
_Exit( int status )
{
j6_process_exit(status);
}

View File

@@ -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 <stdlib.h>
#include <stdint.h>
void
abort()
{
_Exit(INT32_MIN);
}

View File

@@ -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 <stdlib.h> #include <stdlib.h>
#include <j6/syscalls.h>
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<c_callback>(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<void*>(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<void*>(func)};
return 0;
}
void void
exit(int status) exit(int status)
{ {
_Exit(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);
} }