mirror of
https://git.planet-casio.com/Vhex-Kernel-Core/fxlibc.git
synced 2025-05-27 14:05:11 +02:00
dso, stdlib: __cxa_atexit(), __dso_handle, atexit() (TEST)
This commit is contained in:
parent
95e33092ec
commit
7c4de3e295
6 changed files with 81 additions and 2 deletions
|
@ -70,6 +70,8 @@ set(SOURCES
|
|||
3rdparty/grisu2b_59_56/grisu2b_59_56.c
|
||||
3rdparty/tinymt32/rand.c
|
||||
3rdparty/tinymt32/tinymt32.c
|
||||
# C++ API details
|
||||
src/dso.c
|
||||
# assert
|
||||
src/assert/assert.c
|
||||
# ctype
|
||||
|
@ -157,6 +159,7 @@ set(SOURCES
|
|||
# stdlib
|
||||
src/stdlib/abort.c
|
||||
src/stdlib/abs.c
|
||||
src/stdlib/atexit.c
|
||||
src/stdlib/atof.c
|
||||
src/stdlib/atoi.c
|
||||
src/stdlib/atol.c
|
||||
|
|
4
STATUS
4
STATUS
|
@ -162,7 +162,7 @@ TEST: Function/symbol/macro needs to be tested
|
|||
7.20.3.3 malloc - (gint)
|
||||
7.20.3.4 realloc - (gint)
|
||||
7.20.4.1 abort - (stream flushing/closing/etc?)
|
||||
7.20.4.2 atexit TODO
|
||||
7.20.4.2 atexit TEST
|
||||
7.20.4.3 exit - (stream flushing/closing/etc?)
|
||||
7.20.4.4 _Exit - (gint)
|
||||
7.20.4.5 getenv TODO
|
||||
|
@ -173,6 +173,8 @@ TEST: Function/symbol/macro needs to be tested
|
|||
7.20.6.2 div, ldiv, lldiv -
|
||||
7.20.7 Multibyte/wide char conv TODO
|
||||
7.20.8 Multibyte/wide string conv TODO
|
||||
(EXT) __cxa_atexit TEST
|
||||
(EXT) __cxa_finalize TEST
|
||||
|
||||
7.21 <string.h>
|
||||
7.21.2.1 memcpy -
|
||||
|
|
|
@ -38,6 +38,7 @@ extern void free(void *__ptr);
|
|||
__attribute__((noreturn))
|
||||
extern void abort(void);
|
||||
|
||||
/* Register a function to be called at program exit. */
|
||||
extern int atexit(void (*__func)(void));
|
||||
|
||||
/* Exit; calls handlers, flushes and closes streams and temporary files. */
|
||||
|
|
62
src/dso.c
Normal file
62
src/dso.c
Normal file
|
@ -0,0 +1,62 @@
|
|||
#include <stddef.h>
|
||||
|
||||
/* We don't support shared object loading, so provide a single handle */
|
||||
__attribute__((visibility("hidden")))
|
||||
void *__dso_handle = (void *)&__dso_handle;
|
||||
|
||||
/* Number of atexit() calls supported, must be at least 32 (7.20.4.2§3).*/
|
||||
#define ATEXIT_MAX 32
|
||||
|
||||
struct dtor {
|
||||
void (*f)(void *);
|
||||
void *p;
|
||||
void *d;
|
||||
};
|
||||
|
||||
static struct dtor _dtors[ATEXIT_MAX];
|
||||
static int _dtor_count = 0;
|
||||
|
||||
int __cxa_atexit(void (*f)(void *), void *p, void *d)
|
||||
{
|
||||
if(_dtor_count >= ATEXIT_MAX)
|
||||
return 1;
|
||||
_dtors[_dtor_count++] = (struct dtor){ f, p, d };
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We walk the destructor list in reverse order. Destructors may themselves
|
||||
call __cxa_atexit(), causing new destructors to be added. When that
|
||||
happens, we must call the new ones first before resuming (7.20.4.3§3). We
|
||||
track changes in _dtor_count to detect this situation.
|
||||
|
||||
This function calls destructs in the interval [low..high) that match DSO
|
||||
handle d, plus any other destructors registered as a consequence.
|
||||
_dtor_count may increase. */
|
||||
static void call_dtors_in_interval(void *d, int low, int high)
|
||||
{
|
||||
int end = _dtor_count;
|
||||
|
||||
for(int i = high - 1; i >= low; i--) {
|
||||
if(d == NULL || _dtors[i].d == d)
|
||||
_dtors[i].f(_dtors[i].p);
|
||||
|
||||
if(_dtor_count > end) {
|
||||
call_dtors_in_interval(d, end, _dtor_count);
|
||||
end = _dtor_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __cxa_finalize(void *d)
|
||||
{
|
||||
call_dtors_in_interval(d, 0, _dtor_count);
|
||||
|
||||
/* Re-compact the array to keep only destructors we didn't call. */
|
||||
int j = 0;
|
||||
for(int i = 0; i < _dtor_count; i++) {
|
||||
if(d == NULL || _dtors[i].d == d)
|
||||
continue;
|
||||
_dtors[j++] = _dtors[i];
|
||||
}
|
||||
_dtor_count = j;
|
||||
}
|
8
src/stdlib/atexit.c
Normal file
8
src/stdlib/atexit.c
Normal file
|
@ -0,0 +1,8 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
extern int __cxa_atexit(void (*f)(void *), void *p, void *d);
|
||||
|
||||
int atexit(void (*f)(void))
|
||||
{
|
||||
return __cxa_atexit((void (*)(void *))f, NULL, NULL);
|
||||
}
|
|
@ -1,8 +1,11 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
extern void __cxa_finalize(void *d);
|
||||
|
||||
void exit(int rc)
|
||||
{
|
||||
/* TODO: invoke atexit callbacks */
|
||||
__cxa_finalize(NULL);
|
||||
|
||||
/* TODO: exit: Flush all streams */
|
||||
/* TODO: exit: Close all streams */
|
||||
/* TODO: exit: Remove temporary files */
|
||||
|
|
Loading…
Add table
Reference in a new issue