[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:
@@ -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);
|
|
||||||
}
|
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user