diff options
| author | Rich Felker <dalias@aerifal.cx> | 2011-02-12 00:22:29 -0500 | 
|---|---|---|
| committer | Rich Felker <dalias@aerifal.cx> | 2011-02-12 00:22:29 -0500 | 
| commit | 0b44a0315b47dd8eced9f3b7f31580cf14bbfc01 (patch) | |
| tree | 6eaef0d8a720fa3da580de87b647fff796fe80b3 /src/exit | |
| download | musl-0b44a0315b47dd8eced9f3b7f31580cf14bbfc01.tar.gz | |
initial check-in, version 0.5.0v0.5.0
Diffstat (limited to 'src/exit')
| -rw-r--r-- | src/exit/_Exit.c | 9 | ||||
| -rw-r--r-- | src/exit/abort.c | 8 | ||||
| -rw-r--r-- | src/exit/assert.c | 9 | ||||
| -rw-r--r-- | src/exit/atexit.c | 57 | ||||
| -rw-r--r-- | src/exit/exit.c | 28 | 
5 files changed, 111 insertions, 0 deletions
| diff --git a/src/exit/_Exit.c b/src/exit/_Exit.c new file mode 100644 index 00000000..8ef85a8f --- /dev/null +++ b/src/exit/_Exit.c @@ -0,0 +1,9 @@ +#include <stdlib.h> +#define SYSCALL_NORETURN +#include "syscall.h" + +void _Exit(int ec) +{ +	syscall1(__NR_exit_group, ec); +	syscall1(__NR_exit, ec); +} diff --git a/src/exit/abort.c b/src/exit/abort.c new file mode 100644 index 00000000..9a1c3d40 --- /dev/null +++ b/src/exit/abort.c @@ -0,0 +1,8 @@ +#include <stdlib.h> +#include <signal.h> + +void abort(void) +{ +	raise(SIGABRT); +	for (;;); +} diff --git a/src/exit/assert.c b/src/exit/assert.c new file mode 100644 index 00000000..e87442a7 --- /dev/null +++ b/src/exit/assert.c @@ -0,0 +1,9 @@ +#include <stdio.h> +#include <stdlib.h> + +void __assert_fail(const char *expr, const char *file, int line, const char *func) +{ +	fprintf(stderr, "Assertion failed: %s (%s: %s: %d)\n", expr, file, func, line); +	fflush(NULL); +	abort(); +} diff --git a/src/exit/atexit.c b/src/exit/atexit.c new file mode 100644 index 00000000..49c060e6 --- /dev/null +++ b/src/exit/atexit.c @@ -0,0 +1,57 @@ +#include <stddef.h> +#include <stdlib.h> +#include <limits.h> +#include "libc.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); +} builtin, *head; + +static int run_atexit_functions(void) +{ +	int i; +	for (; head; head=head->next) { +		for (i=COUNT-1; i>=0 && !head->f[i]; i--); +		for (; i>=0; i--) head->f[i](); +	} +	return 0; +} + +int (*const __funcs_on_exit)(void) = run_atexit_functions; + +int atexit(void (*func)(void)) +{ +	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 */ +	if (!head) head = &builtin; + +	/* If the current function list is full, add a new one */ +	if (head->f[COUNT-1]) { +		struct fl *new_fl = calloc(sizeof(struct fl), 1); +		if (!new_fl) { +			UNLOCK(&lock); +			return -1; +		} +		new_fl->next = head; +		head = new_fl; +	} + +	/* Append function to the list. */ +	for (i=0; i<COUNT && head->f[i]; i++); +	head->f[i] = func; + +	UNLOCK(&lock); +	return 0; +} diff --git a/src/exit/exit.c b/src/exit/exit.c new file mode 100644 index 00000000..d0c1bfc1 --- /dev/null +++ b/src/exit/exit.c @@ -0,0 +1,28 @@ +#include <stdlib.h> +#include <unistd.h> +#include <stdio.h> +#include "libc.h" + +/* __overflow.c and atexit.c override these */ +static int (*const dummy)() = 0; +weak_alias(dummy, __funcs_on_exit); +weak_alias(dummy, __fflush_on_exit); + +void exit(int code) +{ +	static int lock; + +	/* If more than one thread calls exit, hang until _Exit ends it all */ +	LOCK(&lock); + +	/* Only do atexit & stdio flush if they were actually used */ +	if (__funcs_on_exit) __funcs_on_exit(); +	if (__fflush_on_exit) __fflush_on_exit(0); + +	/* Destructor s**t is kept separate from atexit to avoid bloat */ +	if (libc.fini) libc.fini(); +	if (libc.ldso_fini) libc.ldso_fini(); + +	_Exit(code); +	for(;;); +} | 
