diff --git a/musl_src.gni b/musl_src.gni index 61988bcc11e47bb758a657b5b391672f7e1d2277..55d9c5143e719bf6d73d9d2cb78160388a0a1093 100755 --- a/musl_src.gni +++ b/musl_src.gni @@ -1850,6 +1850,7 @@ musl_src_porting_file = [ "src/thread/arm/syscall_cp.s", "src/ldso/dlclose.c", "ldso/dynlink.c", + "src/exit/atexit.c", "crt/arm/crti.s", "crt/aarch64/crti.s", ] diff --git a/porting/linux/user/src/exit/atexit.c b/porting/linux/user/src/exit/atexit.c new file mode 100644 index 0000000000000000000000000000000000000000..ff683dd6142d99ea23705957db67e9408893edfb --- /dev/null +++ b/porting/linux/user/src/exit/atexit.c @@ -0,0 +1,92 @@ +#include +#include +#include "libc.h" +#include "lock.h" + +/* Ensure that at least 32 atexit handlers can be registered without malloc */ +#define COUNT 32 + +static struct fl +{ + struct fl *next; + void (*f[COUNT])(void *); + void *a[COUNT]; + void *dso[COUNT]; +} builtin, *head; + +static int slot; +static volatile int lock[1]; + +void __funcs_on_exit() +{ + void (*func)(void *), *arg; + LOCK(lock); + for (; head; head=head->next, slot=COUNT) while(slot-->0) { + if (head->dso[slot] != NULL) { + func = head->f[slot]; + arg = head->a[slot]; + UNLOCK(lock); + func(arg); + LOCK(lock); + } + } + UNLOCK(lock); +} + +void __cxa_finalize(void *dso) +{ + void (*func)(void *), *arg; + LOCK(lock); + for (; head; head=head->next, slot=COUNT) while(slot-->0) { + if (dso == head->dso[slot]) { + func = head->f[slot]; + arg = head->a[slot]; + UNLOCK(lock); + func(arg); + LOCK(lock); + + head->dso[slot] = NULL; + } + } + UNLOCK(lock); +} + +int __cxa_atexit(void (*func)(void *), void *arg, void *dso) +{ + LOCK(lock); + + /* Defer initialization of head so it can be in BSS */ + if (!head) head = &builtin; + + /* If the current function list is full, add a new one */ + if (slot==COUNT) { + struct fl *new_fl = calloc(sizeof(struct fl), 1); + if (!new_fl) { + UNLOCK(lock); + return -1; + } + new_fl->next = head; + head = new_fl; + slot = 0; + } + + /* Append function to the list. */ + head->f[slot] = func; + head->a[slot] = arg; + head->dso[slot] = dso; + + slot++; + + UNLOCK(lock); + return 0; +} + +static void call(void *p) +{ + ((void (*)(void))(uintptr_t)p)(); +} + +int atexit(void (*func)(void)) +{ + return __cxa_atexit(call, (void *)(uintptr_t)func, 0); +} \ No newline at end of file