summaryrefslogtreecommitdiff
path: root/src/exit/atexit.c
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2011-10-14 23:21:54 -0400
committerRich Felker <dalias@aerifal.cx>2011-10-14 23:21:54 -0400
commitb7c683be35586f671d91c9883c9a41920938df9b (patch)
treedeba5d24ca3cfe368e824c1ee2b56665ea01ebc4 /src/exit/atexit.c
parentf753049a50132a23849ef89a8af5ff86ad595c25 (diff)
downloadmusl-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.
Diffstat (limited to 'src/exit/atexit.c')
-rw-r--r--src/exit/atexit.c33
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);
+}