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 /src | |
| 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.
Diffstat (limited to 'src')
| -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); +} | 
