diff options
author | Rich Felker <dalias@aerifal.cx> | 2011-10-14 23:21:54 -0400 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2011-10-14 23:21:54 -0400 |
commit | b7c683be35586f671d91c9883c9a41920938df9b (patch) | |
tree | deba5d24ca3cfe368e824c1ee2b56665ea01ebc4 | |
parent | f753049a50132a23849ef89a8af5ff86ad595c25 (diff) | |
download | musl-b7c683be35586f671d91c9883c9a41920938df9b.tar.gz |
support __cxa_atexit, and registering atexit functions from atexit handlers
mildly tested; may have bugs. the locking should be updated not to use
spinlocks but that's outside the scope of this one module.
-rw-r--r-- | src/exit/atexit.c | 33 |
1 files changed, 26 insertions, 7 deletions
diff --git a/src/exit/atexit.c b/src/exit/atexit.c index 6f00e374..c613d85b 100644 --- a/src/exit/atexit.c +++ b/src/exit/atexit.c @@ -1,5 +1,6 @@ #include <stddef.h> #include <stdlib.h> +#include <stdint.h> #include <limits.h> #include "libc.h" @@ -9,26 +10,33 @@ static struct fl { struct fl *next; - void (*f[COUNT])(void); + void (*f[COUNT])(void *); + void *a[COUNT]; } builtin, *head; +static int lock; + void __funcs_on_exit() { int i; + void (*func)(void *), *arg; + LOCK(&lock); for (; head; head=head->next) { for (i=COUNT-1; i>=0 && !head->f[i]; i--); - for (; i>=0; i--) head->f[i](); + if (i<0) continue; + func = head->f[i]; + arg = head->a[i]; + head->f[i] = 0; + UNLOCK(&lock); + func(arg); + LOCK(&lock); } } -int atexit(void (*func)(void)) +int __cxa_atexit(void (*func)(void *), void *arg, void *dso) { - static int lock; int i; - /* Hook for atexit extensions */ - if (libc.atexit) return libc.atexit(func); - LOCK(&lock); /* Defer initialization of head so it can be in BSS */ @@ -48,7 +56,18 @@ int atexit(void (*func)(void)) /* Append function to the list. */ for (i=0; i<COUNT && head->f[i]; i++); head->f[i] = func; + head->a[i] = arg; 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); +} |