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.
This commit is contained in:
Rich Felker 2011-10-14 23:21:54 -04:00
parent f753049a50
commit b7c683be35

View File

@ -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);
}