summaryrefslogtreecommitdiff
path: root/src/exit
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2011-02-12 00:22:29 -0500
committerRich Felker <dalias@aerifal.cx>2011-02-12 00:22:29 -0500
commit0b44a0315b47dd8eced9f3b7f31580cf14bbfc01 (patch)
tree6eaef0d8a720fa3da580de87b647fff796fe80b3 /src/exit
downloadmusl-0b44a0315b47dd8eced9f3b7f31580cf14bbfc01.tar.gz
initial check-in, version 0.5.0v0.5.0
Diffstat (limited to 'src/exit')
-rw-r--r--src/exit/_Exit.c9
-rw-r--r--src/exit/abort.c8
-rw-r--r--src/exit/assert.c9
-rw-r--r--src/exit/atexit.c57
-rw-r--r--src/exit/exit.c28
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(;;);
+}